diff --git a/English.lproj/InfoPlist.strings b/English.lproj/InfoPlist.strings
new file mode 100644
index 0000000..5e45963
Binary files /dev/null and b/English.lproj/InfoPlist.strings differ
diff --git a/Info.plist b/Info.plist
new file mode 100644
index 0000000..1dedf8f
--- /dev/null
+++ b/Info.plist
@@ -0,0 +1,38 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ English
+ CFBundleExecutable
+ ${EXECUTABLE_NAME}
+ CFBundleIconFile
+
+ CFBundleIdentifier
+ org.openemu.${PRODUCT_NAME:rfc1034identifier}
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundlePackageType
+ BNDL
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ 1.18
+ NSPrincipalClass
+ OEGameCoreController
+ OEGameCoreClass
+ OdysseyGameCore
+ OEGameCorePlayerCount
+ 1
+ OEProjectURL
+ http://sourceforge.net/projects/o2em/
+ OESystemIdentifiers
+
+ openemu.system.odyssey2
+
+ SUEnableAutomaticChecks
+ 1
+ SUFeedURL
+ https://raw.github.com/OpenEmu/OpenEmu-Update/master/vecxgl_appcast.xml
+
+
diff --git a/O2EM.xcodeproj/TemplateIcon.icns b/O2EM.xcodeproj/TemplateIcon.icns
new file mode 100644
index 0000000..62cb701
Binary files /dev/null and b/O2EM.xcodeproj/TemplateIcon.icns differ
diff --git a/O2EM.xcodeproj/project.pbxproj b/O2EM.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..5b3464a
--- /dev/null
+++ b/O2EM.xcodeproj/project.pbxproj
@@ -0,0 +1,596 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXAggregateTarget section */
+ 82CAFD070FEDD57400CCDC7E /* Distribution */ = {
+ isa = PBXAggregateTarget;
+ buildConfigurationList = 82CAFD170FEDD58500CCDC7E /* Build configuration list for PBXAggregateTarget "Distribution" */;
+ buildPhases = (
+ 82CAFD250FEDD5CD00CCDC7E /* CopyFiles */,
+ 82CAFD060FEDD57400CCDC7E /* ShellScript */,
+ );
+ dependencies = (
+ 82CAFD0B0FEDD57B00CCDC7E /* PBXTargetDependency */,
+ );
+ name = Distribution;
+ productName = Distribution;
+ };
+ 82D815AB0F1D882B00EF8CF5 /* Build & Install O2EM */ = {
+ isa = PBXAggregateTarget;
+ buildConfigurationList = 82D815B90F1D883D00EF8CF5 /* Build configuration list for PBXAggregateTarget "Build & Install O2EM" */;
+ buildPhases = (
+ 82D815AA0F1D882B00EF8CF5 /* ShellScript */,
+ );
+ dependencies = (
+ 82D815AF0F1D883500EF8CF5 /* PBXTargetDependency */,
+ );
+ name = "Build & Install O2EM";
+ productName = "Build & Install";
+ };
+/* End PBXAggregateTarget section */
+
+/* Begin PBXBuildFile section */
+ 8D5B49B0048680CD000E48DA /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C167DFE841241C02AAC07 /* InfoPlist.strings */; };
+ 8D5B49B4048680CD000E48DA /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */; };
+ 94AD8A76199AD89200E6520F /* wrapalleg.c in Sources */ = {isa = PBXBuildFile; fileRef = 94AD8A37199AD89200E6520F /* wrapalleg.c */; };
+ 94AD8A7E199AD89200E6520F /* audio.c in Sources */ = {isa = PBXBuildFile; fileRef = 94AD8A47199AD89200E6520F /* audio.c */; };
+ 94AD8A7F199AD89200E6520F /* cpu.c in Sources */ = {isa = PBXBuildFile; fileRef = 94AD8A4A199AD89200E6520F /* cpu.c */; };
+ 94AD8A80199AD89200E6520F /* crc32.c in Sources */ = {isa = PBXBuildFile; fileRef = 94AD8A4C199AD89200E6520F /* crc32.c */; };
+ 94AD8A81199AD89200E6520F /* cset.c in Sources */ = {isa = PBXBuildFile; fileRef = 94AD8A4E199AD89200E6520F /* cset.c */; };
+ 94AD8A82199AD89200E6520F /* debug.c in Sources */ = {isa = PBXBuildFile; fileRef = 94AD8A50199AD89200E6520F /* debug.c */; };
+ 94AD8A84199AD89200E6520F /* keyboard.c in Sources */ = {isa = PBXBuildFile; fileRef = 94AD8A53199AD89200E6520F /* keyboard.c */; };
+ 94AD8A93199AD89200E6520F /* score.c in Sources */ = {isa = PBXBuildFile; fileRef = 94AD8A64199AD89200E6520F /* score.c */; };
+ 94AD8A95199AD89200E6520F /* table.c in Sources */ = {isa = PBXBuildFile; fileRef = 94AD8A67199AD89200E6520F /* table.c */; };
+ 94AD8A96199AD89200E6520F /* timefunc.c in Sources */ = {isa = PBXBuildFile; fileRef = 94AD8A69199AD89200E6520F /* timefunc.c */; };
+ 94AD8A97199AD89200E6520F /* vdc.c in Sources */ = {isa = PBXBuildFile; fileRef = 94AD8A6C199AD89200E6520F /* vdc.c */; };
+ 94AD8A98199AD89200E6520F /* vmachine.c in Sources */ = {isa = PBXBuildFile; fileRef = 94AD8A6E199AD89200E6520F /* vmachine.c */; };
+ 94AD8A99199AD89200E6520F /* voice.c in Sources */ = {isa = PBXBuildFile; fileRef = 94AD8A70199AD89200E6520F /* voice.c */; };
+ 94AD8A9A199AD89200E6520F /* vpp.c in Sources */ = {isa = PBXBuildFile; fileRef = 94AD8A72199AD89200E6520F /* vpp.c */; };
+ 94AD8A9B199AD89200E6520F /* vpp_cset.c in Sources */ = {isa = PBXBuildFile; fileRef = 94AD8A74199AD89200E6520F /* vpp_cset.c */; };
+ 94AE2EFA17B0C1330018DFBB /* OpenEmuBase.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 94AE2EF917B0C1330018DFBB /* OpenEmuBase.framework */; };
+ 94AE2EFB17B0C16A0018DFBB /* OdysseyGameCore.m in Sources */ = {isa = PBXBuildFile; fileRef = 941DFB2615B6425200C6552F /* OdysseyGameCore.m */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ 82CAFD0A0FEDD57B00CCDC7E /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 089C1669FE841209C02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 8D5B49AC048680CD000E48DA;
+ remoteInfo = VisualBoyAdvance;
+ };
+ 82D815AE0F1D883500EF8CF5 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 089C1669FE841209C02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 8D5B49AC048680CD000E48DA;
+ remoteInfo = VisualBoyAdvance;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ 82CAFD250FEDD5CD00CCDC7E /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 16;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ 089C1672FE841209C02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; };
+ 089C167EFE841241C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = ""; };
+ 089C167FFE841241C02AAC07 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; };
+ 1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; };
+ 82EC409E0FD9EC420017FC19 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
+ 8D5B49B6048680CD000E48DA /* O2EM.oecoreplugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = O2EM.oecoreplugin; sourceTree = BUILT_PRODUCTS_DIR; };
+ 8D5B49B7048680CD000E48DA /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ 941DFB2615B6425200C6552F /* OdysseyGameCore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OdysseyGameCore.m; sourceTree = ""; };
+ 94404785199D621C002D805E /* OEOdyssey2SystemResponderClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OEOdyssey2SystemResponderClient.h; path = ../../../../Documents/OpenEmu/OpenEmu/Odyssey2/OEOdyssey2SystemResponderClient.h; sourceTree = ""; };
+ 94AD8A37199AD89200E6520F /* wrapalleg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wrapalleg.c; sourceTree = ""; };
+ 94AD8A38199AD89200E6520F /* wrapalleg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wrapalleg.h; sourceTree = ""; };
+ 94AD8A3E199AD89200E6520F /* libretro-o2em.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "libretro-o2em.c"; sourceTree = ""; };
+ 94AD8A3F199AD89200E6520F /* libretro-o2em.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "libretro-o2em.h"; sourceTree = ""; };
+ 94AD8A40199AD89200E6520F /* libretro.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libretro.h; sourceTree = ""; };
+ 94AD8A41199AD89200E6520F /* link.T */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = link.T; sourceTree = ""; };
+ 94AD8A42199AD89200E6520F /* o2em-mapper.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "o2em-mapper.c"; sourceTree = ""; };
+ 94AD8A43199AD89200E6520F /* vkbd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vkbd.c; sourceTree = ""; };
+ 94AD8A44199AD89200E6520F /* vkbd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vkbd.h; sourceTree = ""; };
+ 94AD8A45199AD89200E6520F /* vkbd_def.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vkbd_def.h; sourceTree = ""; };
+ 94AD8A47199AD89200E6520F /* audio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = audio.c; sourceTree = ""; };
+ 94AD8A48199AD89200E6520F /* audio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = audio.h; sourceTree = ""; };
+ 94AD8A49199AD89200E6520F /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = ""; };
+ 94AD8A4A199AD89200E6520F /* cpu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cpu.c; sourceTree = ""; };
+ 94AD8A4B199AD89200E6520F /* cpu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cpu.h; sourceTree = ""; };
+ 94AD8A4C199AD89200E6520F /* crc32.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = crc32.c; sourceTree = ""; };
+ 94AD8A4D199AD89200E6520F /* crc32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crc32.h; sourceTree = ""; };
+ 94AD8A4E199AD89200E6520F /* cset.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cset.c; sourceTree = ""; };
+ 94AD8A4F199AD89200E6520F /* cset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cset.h; sourceTree = ""; };
+ 94AD8A50199AD89200E6520F /* debug.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = debug.c; sourceTree = ""; };
+ 94AD8A51199AD89200E6520F /* debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debug.h; sourceTree = ""; };
+ 94AD8A52199AD89200E6520F /* dis48.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dis48.c; sourceTree = ""; };
+ 94AD8A53199AD89200E6520F /* keyboard.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = keyboard.c; sourceTree = ""; };
+ 94AD8A54199AD89200E6520F /* keyboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = keyboard.h; sourceTree = ""; };
+ 94AD8A55199AD89200E6520F /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = ""; };
+ 94AD8A60199AD89200E6520F /* O2EM116_private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = O2EM116_private.h; sourceTree = ""; };
+ 94AD8A64199AD89200E6520F /* score.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = score.c; sourceTree = ""; };
+ 94AD8A65199AD89200E6520F /* score.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = score.h; sourceTree = ""; };
+ 94AD8A67199AD89200E6520F /* table.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = table.c; sourceTree = ""; };
+ 94AD8A68199AD89200E6520F /* table.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = table.h; sourceTree = ""; };
+ 94AD8A69199AD89200E6520F /* timefunc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = timefunc.c; sourceTree = ""; };
+ 94AD8A6A199AD89200E6520F /* timefunc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = timefunc.h; sourceTree = ""; };
+ 94AD8A6B199AD89200E6520F /* types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = types.h; sourceTree = ""; };
+ 94AD8A6C199AD89200E6520F /* vdc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vdc.c; sourceTree = ""; };
+ 94AD8A6D199AD89200E6520F /* vdc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vdc.h; sourceTree = ""; };
+ 94AD8A6E199AD89200E6520F /* vmachine.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vmachine.c; sourceTree = ""; };
+ 94AD8A6F199AD89200E6520F /* vmachine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vmachine.h; sourceTree = ""; };
+ 94AD8A70199AD89200E6520F /* voice.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = voice.c; sourceTree = ""; };
+ 94AD8A71199AD89200E6520F /* voice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = voice.h; sourceTree = ""; };
+ 94AD8A72199AD89200E6520F /* vpp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vpp.c; sourceTree = ""; };
+ 94AD8A73199AD89200E6520F /* vpp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vpp.h; sourceTree = ""; };
+ 94AD8A74199AD89200E6520F /* vpp_cset.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vpp_cset.c; sourceTree = ""; };
+ 94AD8A75199AD89200E6520F /* vpp_cset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vpp_cset.h; sourceTree = ""; };
+ 94AE2EF917B0C1330018DFBB /* OpenEmuBase.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenEmuBase.framework; path = "../../../Library/Developer/Xcode/DerivedData/OpenEmu-dsehantrxgyfywdpbneyslftzzvv/Build/Products/Debug/OpenEmuBase.framework"; sourceTree = ""; };
+ B5008DAD0E8BFB3E005AECAF /* OdysseyGameCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OdysseyGameCore.h; sourceTree = ""; };
+ D2F7E65807B2D6F200F64583 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = ""; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 8D5B49B3048680CD000E48DA /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8D5B49B4048680CD000E48DA /* Cocoa.framework in Frameworks */,
+ 94AE2EFA17B0C1330018DFBB /* OpenEmuBase.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 089C166AFE841209C02AAC07 /* VisualBoyAdvance */ = {
+ isa = PBXGroup;
+ children = (
+ 94A9E27F157D637B0083A7DC /* Core */,
+ 08FB77AFFE84173DC02AAC07 /* Classes */,
+ 089C167CFE841241C02AAC07 /* Resources */,
+ 089C1671FE841209C02AAC07 /* Frameworks and Libraries */,
+ 19C28FB8FE9D52D311CA2CBB /* Products */,
+ );
+ name = VisualBoyAdvance;
+ sourceTree = "";
+ };
+ 089C1671FE841209C02AAC07 /* Frameworks and Libraries */ = {
+ isa = PBXGroup;
+ children = (
+ 82EC409E0FD9EC420017FC19 /* libz.dylib */,
+ 1058C7ACFEA557BF11CA2CBB /* Linked Frameworks */,
+ 1058C7AEFEA557BF11CA2CBB /* Other Frameworks */,
+ );
+ name = "Frameworks and Libraries";
+ sourceTree = "";
+ };
+ 089C167CFE841241C02AAC07 /* Resources */ = {
+ isa = PBXGroup;
+ children = (
+ 8D5B49B7048680CD000E48DA /* Info.plist */,
+ 089C167DFE841241C02AAC07 /* InfoPlist.strings */,
+ );
+ name = Resources;
+ sourceTree = "";
+ };
+ 08FB77AFFE84173DC02AAC07 /* Classes */ = {
+ isa = PBXGroup;
+ children = (
+ 94404785199D621C002D805E /* OEOdyssey2SystemResponderClient.h */,
+ B5008DAD0E8BFB3E005AECAF /* OdysseyGameCore.h */,
+ 941DFB2615B6425200C6552F /* OdysseyGameCore.m */,
+ );
+ name = Classes;
+ sourceTree = "";
+ };
+ 1058C7ACFEA557BF11CA2CBB /* Linked Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 94AE2EF917B0C1330018DFBB /* OpenEmuBase.framework */,
+ 1058C7ADFEA557BF11CA2CBB /* Cocoa.framework */,
+ );
+ name = "Linked Frameworks";
+ sourceTree = "";
+ };
+ 1058C7AEFEA557BF11CA2CBB /* Other Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 089C167FFE841241C02AAC07 /* AppKit.framework */,
+ D2F7E65807B2D6F200F64583 /* CoreData.framework */,
+ 089C1672FE841209C02AAC07 /* Foundation.framework */,
+ );
+ name = "Other Frameworks";
+ sourceTree = "";
+ };
+ 19C28FB8FE9D52D311CA2CBB /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 8D5B49B6048680CD000E48DA /* O2EM.oecoreplugin */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 94A9E27F157D637B0083A7DC /* Core */ = {
+ isa = PBXGroup;
+ children = (
+ 94AD8A36199AD89200E6520F /* allegrowrapper */,
+ 94AD8A39199AD89200E6520F /* libretro */,
+ 94AD8A46199AD89200E6520F /* src */,
+ );
+ path = Core;
+ sourceTree = "";
+ };
+ 94AD8A36199AD89200E6520F /* allegrowrapper */ = {
+ isa = PBXGroup;
+ children = (
+ 94AD8A37199AD89200E6520F /* wrapalleg.c */,
+ 94AD8A38199AD89200E6520F /* wrapalleg.h */,
+ );
+ path = allegrowrapper;
+ sourceTree = SOURCE_ROOT;
+ };
+ 94AD8A39199AD89200E6520F /* libretro */ = {
+ isa = PBXGroup;
+ children = (
+ 94AD8A3E199AD89200E6520F /* libretro-o2em.c */,
+ 94AD8A3F199AD89200E6520F /* libretro-o2em.h */,
+ 94AD8A40199AD89200E6520F /* libretro.h */,
+ 94AD8A41199AD89200E6520F /* link.T */,
+ 94AD8A42199AD89200E6520F /* o2em-mapper.c */,
+ 94AD8A43199AD89200E6520F /* vkbd.c */,
+ 94AD8A44199AD89200E6520F /* vkbd.h */,
+ 94AD8A45199AD89200E6520F /* vkbd_def.h */,
+ );
+ path = libretro;
+ sourceTree = SOURCE_ROOT;
+ };
+ 94AD8A46199AD89200E6520F /* src */ = {
+ isa = PBXGroup;
+ children = (
+ 94AD8A47199AD89200E6520F /* audio.c */,
+ 94AD8A48199AD89200E6520F /* audio.h */,
+ 94AD8A49199AD89200E6520F /* config.h */,
+ 94AD8A4A199AD89200E6520F /* cpu.c */,
+ 94AD8A4B199AD89200E6520F /* cpu.h */,
+ 94AD8A4C199AD89200E6520F /* crc32.c */,
+ 94AD8A4D199AD89200E6520F /* crc32.h */,
+ 94AD8A4E199AD89200E6520F /* cset.c */,
+ 94AD8A4F199AD89200E6520F /* cset.h */,
+ 94AD8A50199AD89200E6520F /* debug.c */,
+ 94AD8A51199AD89200E6520F /* debug.h */,
+ 94AD8A52199AD89200E6520F /* dis48.c */,
+ 94AD8A53199AD89200E6520F /* keyboard.c */,
+ 94AD8A54199AD89200E6520F /* keyboard.h */,
+ 94AD8A55199AD89200E6520F /* main.c */,
+ 94AD8A60199AD89200E6520F /* O2EM116_private.h */,
+ 94AD8A64199AD89200E6520F /* score.c */,
+ 94AD8A65199AD89200E6520F /* score.h */,
+ 94AD8A67199AD89200E6520F /* table.c */,
+ 94AD8A68199AD89200E6520F /* table.h */,
+ 94AD8A69199AD89200E6520F /* timefunc.c */,
+ 94AD8A6A199AD89200E6520F /* timefunc.h */,
+ 94AD8A6B199AD89200E6520F /* types.h */,
+ 94AD8A6C199AD89200E6520F /* vdc.c */,
+ 94AD8A6D199AD89200E6520F /* vdc.h */,
+ 94AD8A6E199AD89200E6520F /* vmachine.c */,
+ 94AD8A6F199AD89200E6520F /* vmachine.h */,
+ 94AD8A70199AD89200E6520F /* voice.c */,
+ 94AD8A71199AD89200E6520F /* voice.h */,
+ 94AD8A72199AD89200E6520F /* vpp.c */,
+ 94AD8A73199AD89200E6520F /* vpp.h */,
+ 94AD8A74199AD89200E6520F /* vpp_cset.c */,
+ 94AD8A75199AD89200E6520F /* vpp_cset.h */,
+ );
+ path = src;
+ sourceTree = SOURCE_ROOT;
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 8D5B49AC048680CD000E48DA /* O2EM */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 1DEB913A08733D840010E9CD /* Build configuration list for PBXNativeTarget "O2EM" */;
+ buildPhases = (
+ 8D5B49AF048680CD000E48DA /* Resources */,
+ 8D5B49B1048680CD000E48DA /* Sources */,
+ 8D5B49B3048680CD000E48DA /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = O2EM;
+ productInstallPath = "$(HOME)/Library/Bundles";
+ productName = VisualBoyAdvance;
+ productReference = 8D5B49B6048680CD000E48DA /* O2EM.oecoreplugin */;
+ productType = "com.apple.product-type.bundle";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 089C1669FE841209C02AAC07 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ BuildIndependentTargetsInParallel = YES;
+ LastUpgradeCheck = 0420;
+ };
+ buildConfigurationList = 1DEB913E08733D840010E9CD /* Build configuration list for PBXProject "O2EM" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 1;
+ knownRegions = (
+ en,
+ );
+ mainGroup = 089C166AFE841209C02AAC07 /* VisualBoyAdvance */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 8D5B49AC048680CD000E48DA /* O2EM */,
+ 82D815AB0F1D882B00EF8CF5 /* Build & Install O2EM */,
+ 82CAFD070FEDD57400CCDC7E /* Distribution */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 8D5B49AF048680CD000E48DA /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8D5B49B0048680CD000E48DA /* InfoPlist.strings in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ 82CAFD060FEDD57400CCDC7E /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = /usr/bin/openemu_rb_automation.rb;
+ };
+ 82D815AA0F1D882B00EF8CF5 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "mkdir -p \"$USER_LIBRARY_DIR/Application Support/OpenEmu/Cores\"\nrm -rf \"$USER_LIBRARY_DIR/Application Support/OpenEmu/Cores/$PROJECT_NAME.oecoreplugin\"{,.dSYM}\ncp -rf \"$BUILT_PRODUCTS_DIR/$PROJECT_NAME.oecoreplugin\"{,.dSYM} \"$USER_LIBRARY_DIR/Application Support/OpenEmu/Cores/\"\n";
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 8D5B49B1048680CD000E48DA /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 94AD8A95199AD89200E6520F /* table.c in Sources */,
+ 94AD8A9B199AD89200E6520F /* vpp_cset.c in Sources */,
+ 94AD8A82199AD89200E6520F /* debug.c in Sources */,
+ 94AD8A96199AD89200E6520F /* timefunc.c in Sources */,
+ 94AD8A99199AD89200E6520F /* voice.c in Sources */,
+ 94AD8A7F199AD89200E6520F /* cpu.c in Sources */,
+ 94AD8A93199AD89200E6520F /* score.c in Sources */,
+ 94AD8A81199AD89200E6520F /* cset.c in Sources */,
+ 94AD8A84199AD89200E6520F /* keyboard.c in Sources */,
+ 94AD8A97199AD89200E6520F /* vdc.c in Sources */,
+ 94AD8A80199AD89200E6520F /* crc32.c in Sources */,
+ 94AD8A9A199AD89200E6520F /* vpp.c in Sources */,
+ 94AD8A98199AD89200E6520F /* vmachine.c in Sources */,
+ 94AD8A7E199AD89200E6520F /* audio.c in Sources */,
+ 94AE2EFB17B0C16A0018DFBB /* OdysseyGameCore.m in Sources */,
+ 94AD8A76199AD89200E6520F /* wrapalleg.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ 82CAFD0B0FEDD57B00CCDC7E /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 8D5B49AC048680CD000E48DA /* O2EM */;
+ targetProxy = 82CAFD0A0FEDD57B00CCDC7E /* PBXContainerItemProxy */;
+ };
+ 82D815AF0F1D883500EF8CF5 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 8D5B49AC048680CD000E48DA /* O2EM */;
+ targetProxy = 82D815AE0F1D883500EF8CF5 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin PBXVariantGroup section */
+ 089C167DFE841241C02AAC07 /* InfoPlist.strings */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 089C167EFE841241C02AAC07 /* English */,
+ );
+ name = InfoPlist.strings;
+ sourceTree = "";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ 1DEB913B08733D840010E9CD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ EXPORTED_SYMBOLS_FILE = "";
+ FRAMEWORK_SEARCH_PATHS = "";
+ HEADER_SEARCH_PATHS = "\"$(SRCROOT)/src\"";
+ INFOPLIST_FILE = Info.plist;
+ INSTALL_PATH = "\"$(USER_LIBRARY_DIR)/Application Support/OpenEmu/Cores\"";
+ OTHER_CFLAGS = "-D__LIBRETRO__";
+ PRODUCT_NAME = O2EM;
+ SKIP_INSTALL = YES;
+ VALID_ARCHS = x86_64;
+ WRAPPER_EXTENSION = oecoreplugin;
+ };
+ name = Debug;
+ };
+ 1DEB913C08733D840010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ EXPORTED_SYMBOLS_FILE = "";
+ FRAMEWORK_SEARCH_PATHS = "";
+ HEADER_SEARCH_PATHS = "\"$(SRCROOT)/src\"";
+ INFOPLIST_FILE = Info.plist;
+ INSTALL_PATH = "\"$(USER_LIBRARY_DIR)/Application Support/OpenEmu/Cores\"";
+ OTHER_CFLAGS = "-D__LIBRETRO__";
+ PRODUCT_NAME = O2EM;
+ SKIP_INSTALL = YES;
+ VALID_ARCHS = x86_64;
+ WRAPPER_EXTENSION = oecoreplugin;
+ };
+ name = Release;
+ };
+ 1DEB913F08733D840010E9CD /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_64_BIT)";
+ CLANG_ENABLE_OBJC_EXPERIMENTAL = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+ GCC_INCREASE_PRECOMPILED_HEADER_SHARING = NO;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = "";
+ MACOSX_DEPLOYMENT_TARGET = 10.7;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = macosx;
+ VALID_ARCHS = x86_64;
+ };
+ name = Debug;
+ };
+ 1DEB914008733D840010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_64_BIT)";
+ CLANG_ENABLE_OBJC_EXPERIMENTAL = YES;
+ DEAD_CODE_STRIPPING = YES;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+ GCC_INCREASE_PRECOMPILED_HEADER_SHARING = NO;
+ GCC_OPTIMIZATION_LEVEL = 3;
+ GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = "";
+ MACOSX_DEPLOYMENT_TARGET = 10.7;
+ SDKROOT = macosx;
+ VALID_ARCHS = x86_64;
+ };
+ name = Release;
+ };
+ 82CAFD080FEDD57400CCDC7E /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ INSTALL_PATH = "\"$(USER_LIBRARY_DIR)/Application Support/OpenEmu/Cores\"";
+ PRODUCT_NAME = Distribution;
+ SKIP_INSTALL = YES;
+ };
+ name = Debug;
+ };
+ 82CAFD090FEDD57400CCDC7E /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ INSTALL_PATH = "\"$(USER_LIBRARY_DIR)/Application Support/OpenEmu/Cores\"";
+ PRODUCT_NAME = Distribution;
+ SKIP_INSTALL = YES;
+ };
+ name = Release;
+ };
+ 82D815AC0F1D882C00EF8CF5 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ INSTALL_PATH = "\"$(USER_LIBRARY_DIR)/Application Support/OpenEmu/Cores\"";
+ PRODUCT_NAME = "Build & Install";
+ SKIP_INSTALL = YES;
+ };
+ name = Debug;
+ };
+ 82D815AD0F1D882C00EF8CF5 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ INSTALL_PATH = "\"$(USER_LIBRARY_DIR)/Application Support/OpenEmu/Cores\"";
+ PRODUCT_NAME = "Build & Install";
+ SKIP_INSTALL = YES;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 1DEB913A08733D840010E9CD /* Build configuration list for PBXNativeTarget "O2EM" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DEB913B08733D840010E9CD /* Debug */,
+ 1DEB913C08733D840010E9CD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 1DEB913E08733D840010E9CD /* Build configuration list for PBXProject "O2EM" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DEB913F08733D840010E9CD /* Debug */,
+ 1DEB914008733D840010E9CD /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 82CAFD170FEDD58500CCDC7E /* Build configuration list for PBXAggregateTarget "Distribution" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 82CAFD080FEDD57400CCDC7E /* Debug */,
+ 82CAFD090FEDD57400CCDC7E /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 82D815B90F1D883D00EF8CF5 /* Build configuration list for PBXAggregateTarget "Build & Install O2EM" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 82D815AC0F1D882C00EF8CF5 /* Debug */,
+ 82D815AD0F1D882C00EF8CF5 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 089C1669FE841209C02AAC07 /* Project object */;
+}
diff --git a/OdysseyGameCore.h b/OdysseyGameCore.h
new file mode 100644
index 0000000..3b44eca
--- /dev/null
+++ b/OdysseyGameCore.h
@@ -0,0 +1,35 @@
+/*
+ Copyright (c) 2013, OpenEmu Team
+
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form 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.
+ * Neither the name of the OpenEmu Team nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY OpenEmu Team ''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 OpenEmu Team 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.
+ */
+
+#import
+#import
+
+@class OERingBuffer;
+
+OE_EXPORTED_CLASS
+@interface OdysseyGameCore : OEGameCore
+@end
diff --git a/OdysseyGameCore.m b/OdysseyGameCore.m
new file mode 100644
index 0000000..21bd071
--- /dev/null
+++ b/OdysseyGameCore.m
@@ -0,0 +1,630 @@
+/*
+ Copyright (c) 2014, OpenEmu Team
+
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form 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.
+ * Neither the name of the OpenEmu Team nor the
+ names of its contributors may be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY OpenEmu Team ''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 OpenEmu Team 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.
+ */
+
+#import "OdysseyGameCore.h"
+#import "OEOdyssey2SystemResponderClient.h"
+
+#import
+#import
+#include
+
+#include "crc32.h"
+#include "audio.h"
+#include "vmachine.h"
+#include "config.h"
+#include "vdc.h"
+#include "cpu.h"
+#include "debug.h"
+#include "keyboard.h"
+#include "voice.h"
+#include "vpp.h"
+
+#include "wrapalleg.h"
+
+#include "score.h"
+
+#include "libretro.h"
+
+@interface OdysseyGameCore ()
+{
+ NSDictionary *virtualPhysicalKeyMap;
+}
+@end
+
+//uint16_t mbmp[EMUWIDTH * EMUHEIGHT];
+//unsigned short int mbmp[TEX_WIDTH * TEX_HEIGHT];
+uint16_t mbmp[TEX_WIDTH * TEX_HEIGHT];
+//short signed int SNDBUF[1024*2];
+uint8_t soundBuffer[1056];
+int SND;
+int RLOOP=0;
+int joystick_data[2][5]={{0,0,0,0,0},{0,0,0,0,0}};
+
+void update_joy(void){
+}
+
+int contax, o2flag, g74flag, c52flag, jopflag, helpflag;
+
+unsigned long crcx = ~0;
+
+static char bios[MAXC], scshot[MAXC], xrom[MAXC], romdir[MAXC], xbios[MAXC],
+biosdir[MAXC], arkivo[MAXC][MAXC], biossux[MAXC], romssux[MAXC],
+odyssey2[MAXC], g7400[MAXC], c52[MAXC], jopac[MAXC], file_l[MAXC], bios_l[MAXC],
+file_v[MAXC],scorefile[MAXC], statefile[MAXC], path2[MAXC];
+
+static long filesize(FILE *stream){
+ long curpos, length;
+ curpos = ftell(stream);
+ fseek(stream, 0L, SEEK_END);
+ length = ftell(stream);
+ fseek(stream, curpos, SEEK_SET);
+ return length;
+}
+
+static void load_bios(const char *biosname){
+ FILE *fn;
+ static char s[MAXC+10];
+ unsigned long crc;
+ int i;
+
+ if ((biosname[strlen(biosname)-1]=='/') ||
+ (biosname[strlen(biosname)-1]=='\\') ||
+ (biosname[strlen(biosname)-1]==':')) {
+ strcpy(s,biosname);
+ strcat(s,odyssey2);
+ fn = fopen(s,"rb");
+
+ if (!fn) {
+ strcpy(s,biosname);
+ strcat(s,odyssey2);
+ fn = fopen(s,"rb");
+ }
+ } else {
+
+ strcpy(s,biosname);
+ fn = fopen(biosname,"rb");
+ }
+
+ if (!fn) {
+ fprintf(stderr,"Error loading bios ROM (%s)\n",s);
+ exit(EXIT_FAILURE);
+ }
+ if (fread(rom_table[0],1024,1,fn) != 1) {
+ fprintf(stderr,"Error loading bios ROM %s\n",odyssey2);
+ exit(EXIT_FAILURE);
+ }
+
+ strcpy(s,biosname);
+ fn = fopen(biosname,"rb");
+ if (!fn) {
+ fprintf(stderr,"Error loading bios ROM (%s)\n",s);
+ exit(EXIT_FAILURE);
+ }
+ if (fread(rom_table[0],1024,1,fn) != 1) {
+ fprintf(stderr,"Error loading bios ROM %s\n",odyssey2);
+ exit(EXIT_FAILURE);
+ }
+ fclose(fn);
+ for (i=1; i<8; i++) memcpy(rom_table[i],rom_table[0],1024);
+ crc = crc32_buf(rom_table[0],1024);
+ if (crc==0x8016A315) {
+ printf("Odyssey2 bios ROM loaded\n");
+ app_data.vpp = 0;
+ app_data.bios = ROM_O2;
+ } else if (crc==0xE20A9F41) {
+ printf("Videopac+ G7400 bios ROM loaded\n");
+ app_data.vpp = 1;
+ app_data.bios = ROM_G7400;
+ } else if (crc==0xA318E8D6) {
+ if (!((!o2flag)&&(c52flag))) printf("C52 bios ROM loaded\n"); else printf("Ok\n");
+ app_data.vpp = 0;
+ app_data.bios = ROM_C52;
+
+ } else if (crc==0x11647CA5) {
+ if (g74flag) printf("Jopac bios ROM loaded\n"); else printf(" Ok\n");
+ app_data.vpp = 1;
+ app_data.bios = ROM_JOPAC;
+ } else {
+ printf("Bios ROM loaded (unknown version)\n");
+ app_data.vpp = 0;
+ app_data.bios = ROM_UNKNOWN;
+ }
+}
+
+static void load_cart(const char *file){
+ FILE *fn;
+ long l;
+ int i, nb;
+
+ app_data.crc = crc32_file(file);
+ if (app_data.crc == 0xAFB23F89) app_data.exrom = 1; /* Musician */
+ if (app_data.crc == 0x3BFEF56B) app_data.exrom = 1; /* Four in 1 Row! */
+ if (app_data.crc == 0x9B5E9356) app_data.exrom = 1; /* Four in 1 Row! (french) */
+
+ if (((app_data.crc == 0x975AB8DA) || (app_data.crc == 0xE246A812)) && (!app_data.debug)) {
+ fprintf(stderr,"Error: file %s is an incomplete ROM dump\n",file_v);
+ exit(EXIT_FAILURE);
+ }
+
+ fn=fopen(file,"rb");
+ if (!fn) {
+ fprintf(stderr,"Error loading %s\n",file_v);
+ exit(EXIT_FAILURE);
+ }
+ printf("Loading: \"%s\" Size: ",file_v);
+ l = filesize(fn);
+
+ if ((l % 1024) != 0) {
+ fprintf(stderr,"Error: file %s is an invalid ROM dump\n",file_v);
+ exit(EXIT_FAILURE);
+ }
+
+ /* special MegaCART design by Soeren Gust */
+ if ((l == 32768) || (l == 65536) || (l == 131072) || (l == 262144) || (l == 524288) || (l == 1048576)) {
+ app_data.megaxrom = 1;
+ app_data.bank = 1;
+ megarom = malloc(1048576);
+ if (megarom == NULL) {
+ fprintf(stderr, "Out of memory loading %s\n", file);
+ exit(EXIT_FAILURE);
+ }
+ if (fread(megarom, l, 1, fn) != 1) {
+ fprintf(stderr,"Error loading %s\n",file);
+ exit(EXIT_FAILURE);
+ }
+
+ /* mirror shorter files into full megabyte */
+ if (l < 65536) memcpy(megarom+32768,megarom,32768);
+ if (l < 131072) memcpy(megarom+65536,megarom,65536);
+ if (l < 262144) memcpy(megarom+131072,megarom,131072);
+ if (l < 524288) memcpy(megarom+262144,megarom,262144);
+ if (l < 1048576) memcpy(megarom+524288,megarom,524288);
+ /* start in bank 0xff */
+ memcpy(&rom_table[0][1024], megarom + 4096*255 + 1024, 3072);
+ printf("MegaCart %ldK", l / 1024);
+ nb = 1;
+ } else if (((l % 3072) == 0))
+ {
+ app_data.three_k = 1;
+ nb = l/3072;
+
+ for (i=nb-1; i>=0; i--) {
+ if (fread(&rom_table[i][1024],3072,1,fn) != 1) {
+ fprintf(stderr,"Error loading %s\n",file);
+ exit(EXIT_FAILURE);
+ }
+ }
+ printf("%dK",nb*3);
+
+ } else {
+
+ nb = l/2048;
+
+ if ((nb == 2) && (app_data.exrom)) {
+
+ if (fread(&extROM[0], 1024,1,fn) != 1) {
+ fprintf(stderr,"Error loading %s\n",file);
+ exit(EXIT_FAILURE);
+ }
+ if (fread(&rom_table[0][1024],3072,1,fn) != 1) {
+ fprintf(stderr,"Error loading %s\n",file);
+ exit(EXIT_FAILURE);
+ }
+ printf("3K EXROM");
+
+ } else {
+
+ for (i=nb-1; i>=0; i--) {
+ if (fread(&rom_table[i][1024],2048,1,fn) != 1) {
+ fprintf(stderr,"Error loading %s\n",file);
+ exit(EXIT_FAILURE);
+ }
+ memcpy(&rom_table[i][3072],&rom_table[i][2048],1024); /* simulate missing A10 */
+ }
+ printf("%dK",nb*2);
+
+ }
+ }
+ fclose(fn);
+ rom = rom_table[0];
+ if (nb==1)
+ app_data.bank = 1;
+ else if (nb==2)
+ app_data.bank = app_data.exrom ? 1 : 2;
+ else if (nb==4)
+ app_data.bank = 3;
+ else
+ app_data.bank = 4;
+
+ if ((rom_table[nb-1][1024+12]=='O') && (rom_table[nb-1][1024+13]=='P') && (rom_table[nb-1][1024+14]=='N') && (rom_table[nb-1][1024+15]=='B')) app_data.openb=1;
+
+ printf(" CRC: %08lX\n",app_data.crc);
+}
+
+//int suck_bios()
+//{
+// int i;
+// for (i=0; i
+#include
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef __cplusplus
+#if defined(_MSC_VER) && !defined(SN_TARGET_PS3)
+/* Hack applied for MSVC when compiling in C89 mode as it isn't C99 compliant. */
+#define bool unsigned char
+#define true 1
+#define false 0
+#else
+#include
+#endif
+#endif
+
+// Used for checking API/ABI mismatches that can break libretro implementations.
+// It is not incremented for compatible changes to the API.
+#define RETRO_API_VERSION 1
+
+//
+// Libretros fundamental device abstractions.
+/////////
+//
+// Libretros input system consists of some standardized device types such as a joypad (with/without analog),
+// mouse, keyboard, lightgun and a pointer. The functionality of these devices are fixed, and individual cores map
+// their own concept of a controller to libretros abstractions.
+// This makes it possible for frontends to map the abstract types to a real input device,
+// and not having to worry about binding input correctly to arbitrary controller layouts.
+
+
+#define RETRO_DEVICE_TYPE_SHIFT 8
+#define RETRO_DEVICE_MASK ((1 << RETRO_DEVICE_TYPE_SHIFT) - 1)
+#define RETRO_DEVICE_SUBCLASS(base, id) (((id + 1) << RETRO_DEVICE_TYPE_SHIFT) | base)
+
+// Input disabled.
+#define RETRO_DEVICE_NONE 0
+
+// The JOYPAD is called RetroPad. It is essentially a Super Nintendo controller,
+// but with additional L2/R2/L3/R3 buttons, similar to a PS1 DualShock.
+#define RETRO_DEVICE_JOYPAD 1
+
+// The mouse is a simple mouse, similar to Super Nintendo's mouse.
+// X and Y coordinates are reported relatively to last poll (poll callback).
+// It is up to the libretro implementation to keep track of where the mouse pointer is supposed to be on the screen.
+// The frontend must make sure not to interfere with its own hardware mouse pointer.
+#define RETRO_DEVICE_MOUSE 2
+
+// KEYBOARD device lets one poll for raw key pressed.
+// It is poll based, so input callback will return with the current pressed state.
+// For event/text based keyboard input, see RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK.
+#define RETRO_DEVICE_KEYBOARD 3
+
+// Lightgun X/Y coordinates are reported relatively to last poll, similar to mouse.
+#define RETRO_DEVICE_LIGHTGUN 4
+
+// The ANALOG device is an extension to JOYPAD (RetroPad).
+// Similar to DualShock it adds two analog sticks.
+// This is treated as a separate device type as it returns values in the full analog range
+// of [-0x8000, 0x7fff]. Positive X axis is right. Positive Y axis is down.
+// Only use ANALOG type when polling for analog values of the axes.
+#define RETRO_DEVICE_ANALOG 5
+
+// Abstracts the concept of a pointing mechanism, e.g. touch.
+// This allows libretro to query in absolute coordinates where on the screen a mouse (or something similar) is being placed.
+// For a touch centric device, coordinates reported are the coordinates of the press.
+//
+// Coordinates in X and Y are reported as:
+// [-0x7fff, 0x7fff]: -0x7fff corresponds to the far left/top of the screen,
+// and 0x7fff corresponds to the far right/bottom of the screen.
+// The "screen" is here defined as area that is passed to the frontend and later displayed on the monitor.
+// The frontend is free to scale/resize this screen as it sees fit, however,
+// (X, Y) = (-0x7fff, -0x7fff) will correspond to the top-left pixel of the game image, etc.
+//
+// To check if the pointer coordinates are valid (e.g. a touch display actually being touched),
+// PRESSED returns 1 or 0.
+// If using a mouse on a desktop, PRESSED will usually correspond to the left mouse button, but this is a frontend decision.
+// PRESSED will only return 1 if the pointer is inside the game screen.
+//
+// For multi-touch, the index variable can be used to successively query more presses.
+// If index = 0 returns true for _PRESSED, coordinates can be extracted
+// with _X, _Y for index = 0. One can then query _PRESSED, _X, _Y with index = 1, and so on.
+// Eventually _PRESSED will return false for an index. No further presses are registered at this point.
+#define RETRO_DEVICE_POINTER 6
+
+// Buttons for the RetroPad (JOYPAD).
+// The placement of these is equivalent to placements on the Super Nintendo controller.
+// L2/R2/L3/R3 buttons correspond to the PS1 DualShock.
+#define RETRO_DEVICE_ID_JOYPAD_B 0
+#define RETRO_DEVICE_ID_JOYPAD_Y 1
+#define RETRO_DEVICE_ID_JOYPAD_SELECT 2
+#define RETRO_DEVICE_ID_JOYPAD_START 3
+#define RETRO_DEVICE_ID_JOYPAD_UP 4
+#define RETRO_DEVICE_ID_JOYPAD_DOWN 5
+#define RETRO_DEVICE_ID_JOYPAD_LEFT 6
+#define RETRO_DEVICE_ID_JOYPAD_RIGHT 7
+#define RETRO_DEVICE_ID_JOYPAD_A 8
+#define RETRO_DEVICE_ID_JOYPAD_X 9
+#define RETRO_DEVICE_ID_JOYPAD_L 10
+#define RETRO_DEVICE_ID_JOYPAD_R 11
+#define RETRO_DEVICE_ID_JOYPAD_L2 12
+#define RETRO_DEVICE_ID_JOYPAD_R2 13
+#define RETRO_DEVICE_ID_JOYPAD_L3 14
+#define RETRO_DEVICE_ID_JOYPAD_R3 15
+
+// Index / Id values for ANALOG device.
+#define RETRO_DEVICE_INDEX_ANALOG_LEFT 0
+#define RETRO_DEVICE_INDEX_ANALOG_RIGHT 1
+#define RETRO_DEVICE_ID_ANALOG_X 0
+#define RETRO_DEVICE_ID_ANALOG_Y 1
+
+// Id values for MOUSE.
+#define RETRO_DEVICE_ID_MOUSE_X 0
+#define RETRO_DEVICE_ID_MOUSE_Y 1
+#define RETRO_DEVICE_ID_MOUSE_LEFT 2
+#define RETRO_DEVICE_ID_MOUSE_RIGHT 3
+#define RETRO_DEVICE_ID_MOUSE_WHEELUP 4
+#define RETRO_DEVICE_ID_MOUSE_WHEELDOWN 5
+#define RETRO_DEVICE_ID_MOUSE_MIDDLE 6
+
+// Id values for LIGHTGUN types.
+#define RETRO_DEVICE_ID_LIGHTGUN_X 0
+#define RETRO_DEVICE_ID_LIGHTGUN_Y 1
+#define RETRO_DEVICE_ID_LIGHTGUN_TRIGGER 2
+#define RETRO_DEVICE_ID_LIGHTGUN_CURSOR 3
+#define RETRO_DEVICE_ID_LIGHTGUN_TURBO 4
+#define RETRO_DEVICE_ID_LIGHTGUN_PAUSE 5
+#define RETRO_DEVICE_ID_LIGHTGUN_START 6
+
+// Id values for POINTER.
+#define RETRO_DEVICE_ID_POINTER_X 0
+#define RETRO_DEVICE_ID_POINTER_Y 1
+#define RETRO_DEVICE_ID_POINTER_PRESSED 2
+
+// Returned from retro_get_region().
+#define RETRO_REGION_NTSC 0
+#define RETRO_REGION_PAL 1
+
+// Id values for LANGUAGE
+enum retro_language
+{
+ RETRO_LANGUAGE_ENGLISH = 0,
+ RETRO_LANGUAGE_JAPANESE = 1,
+ RETRO_LANGUAGE_FRENCH = 2,
+ RETRO_LANGUAGE_SPANISH = 3,
+ RETRO_LANGUAGE_GERMAN = 4,
+ RETRO_LANGUAGE_ITALIAN = 5,
+ RETRO_LANGUAGE_DUTCH = 6,
+ RETRO_LANGUAGE_PORTUGUESE = 7,
+ RETRO_LANGUAGE_RUSSIAN = 8,
+ RETRO_LANGUAGE_KOREAN = 9,
+ RETRO_LANGUAGE_CHINESE_TRADITIONAL = 10,
+ RETRO_LANGUAGE_CHINESE_SIMPLIFIED = 11,
+ RETRO_LANGUAGE_LAST,
+
+ RETRO_LANGUAGE_DUMMY = INT_MAX // Ensure sizeof(enum) == sizeof(int)
+};
+
+// Passed to retro_get_memory_data/size().
+// If the memory type doesn't apply to the implementation NULL/0 can be returned.
+#define RETRO_MEMORY_MASK 0xff
+
+// Regular save ram. This ram is usually found on a game cartridge, backed up by a battery.
+// If save game data is too complex for a single memory buffer,
+// the SAVE_DIRECTORY (preferably) or SYSTEM_DIRECTORY environment callback can be used.
+#define RETRO_MEMORY_SAVE_RAM 0
+
+// Some games have a built-in clock to keep track of time.
+// This memory is usually just a couple of bytes to keep track of time.
+#define RETRO_MEMORY_RTC 1
+
+// System ram lets a frontend peek into a game systems main RAM.
+#define RETRO_MEMORY_SYSTEM_RAM 2
+
+// Video ram lets a frontend peek into a game systems video RAM (VRAM).
+#define RETRO_MEMORY_VIDEO_RAM 3
+
+// Keysyms used for ID in input state callback when polling RETRO_KEYBOARD.
+enum retro_key
+{
+ RETROK_UNKNOWN = 0,
+ RETROK_FIRST = 0,
+ RETROK_BACKSPACE = 8,
+ RETROK_TAB = 9,
+ RETROK_CLEAR = 12,
+ RETROK_RETURN = 13,
+ RETROK_PAUSE = 19,
+ RETROK_ESCAPE = 27,
+ RETROK_SPACE = 32,
+ RETROK_EXCLAIM = 33,
+ RETROK_QUOTEDBL = 34,
+ RETROK_HASH = 35,
+ RETROK_DOLLAR = 36,
+ RETROK_AMPERSAND = 38,
+ RETROK_QUOTE = 39,
+ RETROK_LEFTPAREN = 40,
+ RETROK_RIGHTPAREN = 41,
+ RETROK_ASTERISK = 42,
+ RETROK_PLUS = 43,
+ RETROK_COMMA = 44,
+ RETROK_MINUS = 45,
+ RETROK_PERIOD = 46,
+ RETROK_SLASH = 47,
+ RETROK_0 = 48,
+ RETROK_1 = 49,
+ RETROK_2 = 50,
+ RETROK_3 = 51,
+ RETROK_4 = 52,
+ RETROK_5 = 53,
+ RETROK_6 = 54,
+ RETROK_7 = 55,
+ RETROK_8 = 56,
+ RETROK_9 = 57,
+ RETROK_COLON = 58,
+ RETROK_SEMICOLON = 59,
+ RETROK_LESS = 60,
+ RETROK_EQUALS = 61,
+ RETROK_GREATER = 62,
+ RETROK_QUESTION = 63,
+ RETROK_AT = 64,
+ RETROK_LEFTBRACKET = 91,
+ RETROK_BACKSLASH = 92,
+ RETROK_RIGHTBRACKET = 93,
+ RETROK_CARET = 94,
+ RETROK_UNDERSCORE = 95,
+ RETROK_BACKQUOTE = 96,
+ RETROK_a = 97,
+ RETROK_b = 98,
+ RETROK_c = 99,
+ RETROK_d = 100,
+ RETROK_e = 101,
+ RETROK_f = 102,
+ RETROK_g = 103,
+ RETROK_h = 104,
+ RETROK_i = 105,
+ RETROK_j = 106,
+ RETROK_k = 107,
+ RETROK_l = 108,
+ RETROK_m = 109,
+ RETROK_n = 110,
+ RETROK_o = 111,
+ RETROK_p = 112,
+ RETROK_q = 113,
+ RETROK_r = 114,
+ RETROK_s = 115,
+ RETROK_t = 116,
+ RETROK_u = 117,
+ RETROK_v = 118,
+ RETROK_w = 119,
+ RETROK_x = 120,
+ RETROK_y = 121,
+ RETROK_z = 122,
+ RETROK_DELETE = 127,
+
+ RETROK_KP0 = 256,
+ RETROK_KP1 = 257,
+ RETROK_KP2 = 258,
+ RETROK_KP3 = 259,
+ RETROK_KP4 = 260,
+ RETROK_KP5 = 261,
+ RETROK_KP6 = 262,
+ RETROK_KP7 = 263,
+ RETROK_KP8 = 264,
+ RETROK_KP9 = 265,
+ RETROK_KP_PERIOD = 266,
+ RETROK_KP_DIVIDE = 267,
+ RETROK_KP_MULTIPLY = 268,
+ RETROK_KP_MINUS = 269,
+ RETROK_KP_PLUS = 270,
+ RETROK_KP_ENTER = 271,
+ RETROK_KP_EQUALS = 272,
+
+ RETROK_UP = 273,
+ RETROK_DOWN = 274,
+ RETROK_RIGHT = 275,
+ RETROK_LEFT = 276,
+ RETROK_INSERT = 277,
+ RETROK_HOME = 278,
+ RETROK_END = 279,
+ RETROK_PAGEUP = 280,
+ RETROK_PAGEDOWN = 281,
+
+ RETROK_F1 = 282,
+ RETROK_F2 = 283,
+ RETROK_F3 = 284,
+ RETROK_F4 = 285,
+ RETROK_F5 = 286,
+ RETROK_F6 = 287,
+ RETROK_F7 = 288,
+ RETROK_F8 = 289,
+ RETROK_F9 = 290,
+ RETROK_F10 = 291,
+ RETROK_F11 = 292,
+ RETROK_F12 = 293,
+ RETROK_F13 = 294,
+ RETROK_F14 = 295,
+ RETROK_F15 = 296,
+
+ RETROK_NUMLOCK = 300,
+ RETROK_CAPSLOCK = 301,
+ RETROK_SCROLLOCK = 302,
+ RETROK_RSHIFT = 303,
+ RETROK_LSHIFT = 304,
+ RETROK_RCTRL = 305,
+ RETROK_LCTRL = 306,
+ RETROK_RALT = 307,
+ RETROK_LALT = 308,
+ RETROK_RMETA = 309,
+ RETROK_LMETA = 310,
+ RETROK_LSUPER = 311,
+ RETROK_RSUPER = 312,
+ RETROK_MODE = 313,
+ RETROK_COMPOSE = 314,
+
+ RETROK_HELP = 315,
+ RETROK_PRINT = 316,
+ RETROK_SYSREQ = 317,
+ RETROK_BREAK = 318,
+ RETROK_MENU = 319,
+ RETROK_POWER = 320,
+ RETROK_EURO = 321,
+ RETROK_UNDO = 322,
+
+ RETROK_LAST,
+
+ RETROK_DUMMY = INT_MAX // Ensure sizeof(enum) == sizeof(int)
+};
+
+enum retro_mod
+{
+ RETROKMOD_NONE = 0x0000,
+
+ RETROKMOD_SHIFT = 0x01,
+ RETROKMOD_CTRL = 0x02,
+ RETROKMOD_ALT = 0x04,
+ RETROKMOD_META = 0x08,
+
+ RETROKMOD_NUMLOCK = 0x10,
+ RETROKMOD_CAPSLOCK = 0x20,
+ RETROKMOD_SCROLLOCK = 0x40,
+
+ RETROKMOD_DUMMY = INT_MAX // Ensure sizeof(enum) == sizeof(int)
+};
+
+// If set, this call is not part of the public libretro API yet. It can change or be removed at any time.
+#define RETRO_ENVIRONMENT_EXPERIMENTAL 0x10000
+// Environment callback to be used internally in frontend.
+#define RETRO_ENVIRONMENT_PRIVATE 0x20000
+
+// Environment commands.
+#define RETRO_ENVIRONMENT_SET_ROTATION 1 // const unsigned * --
+ // Sets screen rotation of graphics.
+ // Is only implemented if rotation can be accelerated by hardware.
+ // Valid values are 0, 1, 2, 3, which rotates screen by 0, 90, 180, 270 degrees
+ // counter-clockwise respectively.
+ //
+#define RETRO_ENVIRONMENT_GET_OVERSCAN 2 // bool * --
+ // Boolean value whether or not the implementation should use overscan, or crop away overscan.
+ //
+#define RETRO_ENVIRONMENT_GET_CAN_DUPE 3 // bool * --
+ // Boolean value whether or not frontend supports frame duping,
+ // passing NULL to video frame callback.
+ //
+// Environ 4, 5 are no longer supported (GET_VARIABLE / SET_VARIABLES), and reserved to avoid possible ABI clash.
+#define RETRO_ENVIRONMENT_SET_MESSAGE 6 // const struct retro_message * --
+ // Sets a message to be displayed in implementation-specific manner for a certain amount of 'frames'.
+ // Should not be used for trivial messages, which should simply be logged via RETRO_ENVIRONMENT_GET_LOG_INTERFACE (or as a fallback, stderr).
+#define RETRO_ENVIRONMENT_SHUTDOWN 7 // N/A (NULL) --
+ // Requests the frontend to shutdown.
+ // Should only be used if game has a specific
+ // way to shutdown the game from a menu item or similar.
+ //
+#define RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL 8
+ // const unsigned * --
+ // Gives a hint to the frontend how demanding this implementation
+ // is on a system. E.g. reporting a level of 2 means
+ // this implementation should run decently on all frontends
+ // of level 2 and up.
+ //
+ // It can be used by the frontend to potentially warn
+ // about too demanding implementations.
+ //
+ // The levels are "floating".
+ //
+ // This function can be called on a per-game basis,
+ // as certain games an implementation can play might be
+ // particularly demanding.
+ // If called, it should be called in retro_load_game().
+ //
+#define RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY 9
+ // const char ** --
+ // Returns the "system" directory of the frontend.
+ // This directory can be used to store system specific content such as BIOSes, configuration data, etc.
+ // The returned value can be NULL.
+ // If so, no such directory is defined,
+ // and it's up to the implementation to find a suitable directory.
+ //
+ // NOTE: Some cores used this folder also for "save" data such as memory cards, etc, for lack of a better place to put it.
+ // This is now discouraged, and if possible, cores should try to use the new GET_SAVE_DIRECTORY.
+ //
+#define RETRO_ENVIRONMENT_SET_PIXEL_FORMAT 10
+ // const enum retro_pixel_format * --
+ // Sets the internal pixel format used by the implementation.
+ // The default pixel format is RETRO_PIXEL_FORMAT_0RGB1555.
+ // This pixel format however, is deprecated (see enum retro_pixel_format).
+ // If the call returns false, the frontend does not support this pixel format.
+ // This function should be called inside retro_load_game() or retro_get_system_av_info().
+ //
+#define RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS 11
+ // const struct retro_input_descriptor * --
+ // Sets an array of retro_input_descriptors.
+ // It is up to the frontend to present this in a usable way.
+ // The array is terminated by retro_input_descriptor::description being set to NULL.
+ // This function can be called at any time, but it is recommended to call it as early as possible.
+#define RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK 12
+ // const struct retro_keyboard_callback * --
+ // Sets a callback function used to notify core about keyboard events.
+ //
+#define RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE 13
+ // const struct retro_disk_control_callback * --
+ // Sets an interface which frontend can use to eject and insert disk images.
+ // This is used for games which consist of multiple images and must be manually
+ // swapped out by the user (e.g. PSX).
+#define RETRO_ENVIRONMENT_SET_HW_RENDER 14
+ // struct retro_hw_render_callback * --
+ // Sets an interface to let a libretro core render with hardware acceleration.
+ // Should be called in retro_load_game().
+ // If successful, libretro cores will be able to render to a frontend-provided framebuffer.
+ // The size of this framebuffer will be at least as large as max_width/max_height provided in get_av_info().
+ // If HW rendering is used, pass only RETRO_HW_FRAME_BUFFER_VALID or NULL to retro_video_refresh_t.
+#define RETRO_ENVIRONMENT_GET_VARIABLE 15
+ // struct retro_variable * --
+ // Interface to acquire user-defined information from environment
+ // that cannot feasibly be supported in a multi-system way.
+ // 'key' should be set to a key which has already been set by SET_VARIABLES.
+ // 'data' will be set to a value or NULL.
+ //
+#define RETRO_ENVIRONMENT_SET_VARIABLES 16
+ // const struct retro_variable * --
+ // Allows an implementation to signal the environment
+ // which variables it might want to check for later using GET_VARIABLE.
+ // This allows the frontend to present these variables to a user dynamically.
+ // This should be called as early as possible (ideally in retro_set_environment).
+ //
+ // 'data' points to an array of retro_variable structs terminated by a { NULL, NULL } element.
+ // retro_variable::key should be namespaced to not collide with other implementations' keys. E.g. A core called 'foo' should use keys named as 'foo_option'.
+ // retro_variable::value should contain a human readable description of the key as well as a '|' delimited list of expected values.
+ // The number of possible options should be very limited, i.e. it should be feasible to cycle through options without a keyboard.
+ // First entry should be treated as a default.
+ //
+ // Example entry:
+ // { "foo_option", "Speed hack coprocessor X; false|true" }
+ //
+ // Text before first ';' is description. This ';' must be followed by a space, and followed by a list of possible values split up with '|'.
+ // Only strings are operated on. The possible values will generally be displayed and stored as-is by the frontend.
+ //
+#define RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE 17
+ // bool * --
+ // Result is set to true if some variables are updated by
+ // frontend since last call to RETRO_ENVIRONMENT_GET_VARIABLE.
+ // Variables should be queried with GET_VARIABLE.
+ //
+#define RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME 18
+ // const bool * --
+ // If true, the libretro implementation supports calls to retro_load_game() with NULL as argument.
+ // Used by cores which can run without particular game data.
+ // This should be called within retro_set_environment() only.
+ //
+#define RETRO_ENVIRONMENT_GET_LIBRETRO_PATH 19
+ // const char ** --
+ // Retrieves the absolute path from where this libretro implementation was loaded.
+ // NULL is returned if the libretro was loaded statically (i.e. linked statically to frontend), or if the path cannot be determined.
+ // Mostly useful in cooperation with SET_SUPPORT_NO_GAME as assets can be loaded without ugly hacks.
+ //
+ //
+// Environment 20 was an obsolete version of SET_AUDIO_CALLBACK. It was not used by any known core at the time,
+// and was removed from the API.
+#define RETRO_ENVIRONMENT_SET_AUDIO_CALLBACK 22
+ // const struct retro_audio_callback * --
+ // Sets an interface which is used to notify a libretro core about audio being available for writing.
+ // The callback can be called from any thread, so a core using this must have a thread safe audio implementation.
+ // It is intended for games where audio and video are completely asynchronous and audio can be generated on the fly.
+ // This interface is not recommended for use with emulators which have highly synchronous audio.
+ //
+ // The callback only notifies about writability; the libretro core still has to call the normal audio callbacks
+ // to write audio. The audio callbacks must be called from within the notification callback.
+ // The amount of audio data to write is up to the implementation.
+ // Generally, the audio callback will be called continously in a loop.
+ //
+ // Due to thread safety guarantees and lack of sync between audio and video, a frontend
+ // can selectively disallow this interface based on internal configuration. A core using
+ // this interface must also implement the "normal" audio interface.
+ //
+ // A libretro core using SET_AUDIO_CALLBACK should also make use of SET_FRAME_TIME_CALLBACK.
+#define RETRO_ENVIRONMENT_SET_FRAME_TIME_CALLBACK 21
+ // const struct retro_frame_time_callback * --
+ // Lets the core know how much time has passed since last invocation of retro_run().
+ // The frontend can tamper with the timing to fake fast-forward, slow-motion, frame stepping, etc.
+ // In this case the delta time will use the reference value in frame_time_callback..
+ //
+#define RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE 23
+ // struct retro_rumble_interface * --
+ // Gets an interface which is used by a libretro core to set state of rumble motors in controllers.
+ // A strong and weak motor is supported, and they can be controlled indepedently.
+ //
+#define RETRO_ENVIRONMENT_GET_INPUT_DEVICE_CAPABILITIES 24
+ // uint64_t * --
+ // Gets a bitmask telling which device type are expected to be handled properly in a call to retro_input_state_t.
+ // Devices which are not handled or recognized always return 0 in retro_input_state_t.
+ // Example bitmask: caps = (1 << RETRO_DEVICE_JOYPAD) | (1 << RETRO_DEVICE_ANALOG).
+ // Should only be called in retro_run().
+ //
+#define RETRO_ENVIRONMENT_GET_SENSOR_INTERFACE (25 | RETRO_ENVIRONMENT_EXPERIMENTAL)
+ // struct retro_sensor_interface * --
+ // Gets access to the sensor interface.
+ // The purpose of this interface is to allow
+ // setting state related to sensors such as polling rate, enabling/disable it entirely, etc.
+ // Reading sensor state is done via the normal input_state_callback API.
+ //
+#define RETRO_ENVIRONMENT_GET_CAMERA_INTERFACE (26 | RETRO_ENVIRONMENT_EXPERIMENTAL)
+ // struct retro_camera_callback * --
+ // Gets an interface to a video camera driver.
+ // A libretro core can use this interface to get access to a video camera.
+ // New video frames are delivered in a callback in same thread as retro_run().
+ //
+ // GET_CAMERA_INTERFACE should be called in retro_load_game().
+ //
+ // Depending on the camera implementation used, camera frames will be delivered as a raw framebuffer,
+ // or as an OpenGL texture directly.
+ //
+ // The core has to tell the frontend here which types of buffers can be handled properly.
+ // An OpenGL texture can only be handled when using a libretro GL core (SET_HW_RENDER).
+ // It is recommended to use a libretro GL core when using camera interface.
+ //
+ // The camera is not started automatically. The retrieved start/stop functions must be used to explicitly
+ // start and stop the camera driver.
+ //
+#define RETRO_ENVIRONMENT_GET_LOG_INTERFACE 27
+ // struct retro_log_callback * --
+ // Gets an interface for logging. This is useful for logging in a cross-platform way
+ // as certain platforms cannot use use stderr for logging. It also allows the frontend to
+ // show logging information in a more suitable way.
+ // If this interface is not used, libretro cores should log to stderr as desired.
+#define RETRO_ENVIRONMENT_GET_PERF_INTERFACE 28
+ // struct retro_perf_callback * --
+ // Gets an interface for performance counters. This is useful for performance logging in a
+ // cross-platform way and for detecting architecture-specific features, such as SIMD support.
+#define RETRO_ENVIRONMENT_GET_LOCATION_INTERFACE 29
+ // struct retro_location_callback * --
+ // Gets access to the location interface.
+ // The purpose of this interface is to be able to retrieve location-based information from the host device,
+ // such as current latitude / longitude.
+ //
+#define RETRO_ENVIRONMENT_GET_CONTENT_DIRECTORY 30
+ // const char ** --
+ // Returns the "content" directory of the frontend.
+ // This directory can be used to store specific assets that the core relies upon, such as art assets,
+ // input data, etc etc.
+ // The returned value can be NULL.
+ // If so, no such directory is defined,
+ // and it's up to the implementation to find a suitable directory.
+ //
+#define RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY 31
+ // const char ** --
+ // Returns the "save" directory of the frontend.
+ // This directory can be used to store SRAM, memory cards, high scores, etc, if the libretro core
+ // cannot use the regular memory interface (retro_get_memory_data()).
+ //
+ // NOTE: libretro cores used to check GET_SYSTEM_DIRECTORY for similar things before.
+ // They should still check GET_SYSTEM_DIRECTORY if they want to be backwards compatible.
+ // The path here can be NULL. It should only be non-NULL if the frontend user has set a specific save path.
+ //
+#define RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO 32
+ // const struct retro_system_av_info * --
+ // Sets a new av_info structure. This can only be called from within retro_run().
+ // This should *only* be used if the core is completely altering the internal resolutions, aspect ratios, timings, sampling rate, etc.
+ // Calling this can require a full reinitialization of video/audio drivers in the frontend,
+ // so it is important to call it very sparingly, and usually only with the users explicit consent.
+ // An eventual driver reinitialize will happen so that video and audio callbacks
+ // happening after this call within the same retro_run() call will target the newly initialized driver.
+ //
+ // This callback makes it possible to support configurable resolutions in games, which can be useful to
+ // avoid setting the "worst case" in max_width/max_height.
+ //
+ // ***HIGHLY RECOMMENDED*** Do not call this callback every time resolution changes in an emulator core if it's
+ // expected to be a temporary change, for the reasons of possible driver reinitialization.
+ // This call is not a free pass for not trying to provide correct values in retro_get_system_av_info(). If you need to change things like aspect ratio or nominal width/height, use RETRO_ENVIRONMENT_SET_GEOMETRY, which is a softer variant of SET_SYSTEM_AV_INFO.
+ //
+ // If this returns false, the frontend does not acknowledge a changed av_info struct.
+#define RETRO_ENVIRONMENT_SET_PROC_ADDRESS_CALLBACK 33
+ // const struct retro_get_proc_address_interface * --
+ // Allows a libretro core to announce support for the get_proc_address() interface.
+ // This interface allows for a standard way to extend libretro where use of environment calls are too indirect,
+ // e.g. for cases where the frontend wants to call directly into the core.
+ //
+ // If a core wants to expose this interface, SET_PROC_ADDRESS_CALLBACK **MUST** be called from within retro_set_environment().
+ //
+#define RETRO_ENVIRONMENT_SET_SUBSYSTEM_INFO 34
+ // const struct retro_subsystem_info * --
+ // This environment call introduces the concept of libretro "subsystems".
+ // A subsystem is a variant of a libretro core which supports different kinds of games.
+ // The purpose of this is to support e.g. emulators which might have special needs, e.g. Super Nintendos Super GameBoy, Sufami Turbo.
+ // It can also be used to pick among subsystems in an explicit way if the libretro implementation is a multi-system emulator itself.
+ //
+ // Loading a game via a subsystem is done with retro_load_game_special(),
+ // and this environment call allows a libretro core to expose which subsystems are supported for use with retro_load_game_special().
+ // A core passes an array of retro_game_special_info which is terminated with a zeroed out retro_game_special_info struct.
+ //
+ // If a core wants to use this functionality, SET_SUBSYSTEM_INFO **MUST** be called from within retro_set_environment().
+ //
+#define RETRO_ENVIRONMENT_SET_CONTROLLER_INFO 35
+ // const struct retro_controller_info * --
+ // This environment call lets a libretro core tell the frontend which
+ // controller types are recognized in calls to retro_set_controller_port_device().
+ //
+ // Some emulators such as Super Nintendo
+ // support multiple lightgun types which must be specifically selected from.
+ // It is therefore sometimes necessary for a frontend to be able to tell
+ // the core about a special kind of input device which is not covered by the
+ // libretro input API.
+ //
+ // In order for a frontend to understand the workings of an input device,
+ // it must be a specialized type
+ // of the generic device types already defined in the libretro API.
+ //
+ // Which devices are supported can vary per input port.
+ // The core must pass an array of const struct retro_controller_info which is terminated with
+ // a blanked out struct. Each element of the struct corresponds to an ascending port index to retro_set_controller_port_device().
+ // Even if special device types are set in the libretro core, libretro should only poll input based on the base input device types.
+#define RETRO_ENVIRONMENT_SET_MEMORY_MAPS (36 | RETRO_ENVIRONMENT_EXPERIMENTAL)
+ // const struct retro_memory_map * --
+ // This environment call lets a libretro core tell the frontend about the memory maps this
+ // core emulates. This can be used to implement, for example, cheats in a core-agnostic way.
+ //
+ // Should only be used by emulators; it doesn't make much sense for anything else.
+ // It is recommended to expose all relevant pointers through retro_get_memory_* as well.
+ //
+ // Can be called from retro_init and retro_load_game.
+ //
+#define RETRO_ENVIRONMENT_SET_GEOMETRY 37
+ // const struct retro_game_geometry * --
+ // This environment call is similar to SET_SYSTEM_AV_INFO for changing video parameters,
+ // but provides a guarantee that drivers will not be reinitialized.
+ // This can only be called from within retro_run().
+ //
+ // The purpose of this call is to allow a core to alter nominal width/heights as well as aspect ratios on-the-fly,
+ // which can be useful for some emulators to change in run-time.
+ //
+ // max_width/max_height arguments are ignored and cannot be changed
+ // with this call as this could potentially require a reinitialization or a non-constant time operation.
+ // If max_width/max_height are to be changed, SET_SYSTEM_AV_INFO is required.
+ //
+ // A frontend must guarantee that this environment call completes in constant time.
+
+#define RETRO_ENVIRONMENT_GET_USERNAME 38
+ // const char **
+ // Returns the specified username of the frontend, if specified by the user.
+ // This username can be used as a nickname for a core that has online facilities or any other mode where personalization // of the user is desirable.
+ // The returned value can be NULL.
+ // If this environ callback is used by a core that requires a valid username, a default username should be specified
+ // by the core.
+ //
+ //
+#define RETRO_ENVIRONMENT_GET_LANGUAGE 39
+ // const unsigned * --
+ // Returns the specified language of the frontend, if specified by the user.
+ // It can be used by the core for localization purposes.
+ //
+
+#define RETRO_MEMDESC_CONST (1 << 0) // The frontend will never change this memory area once retro_load_game has returned.
+#define RETRO_MEMDESC_BIGENDIAN (1 << 1) // The memory area contains big endian data. Default is little endian.
+#define RETRO_MEMDESC_ALIGN_2 (1 << 16) // All memory access in this area is aligned to their own size, or 2, whichever is smaller.
+#define RETRO_MEMDESC_ALIGN_4 (2 << 16)
+#define RETRO_MEMDESC_ALIGN_8 (3 << 16)
+#define RETRO_MEMDESC_MINSIZE_2 (1 << 24) // All memory in this region is accessed at least 2 bytes at the time.
+#define RETRO_MEMDESC_MINSIZE_4 (2 << 24)
+#define RETRO_MEMDESC_MINSIZE_8 (3 << 24)
+struct retro_memory_descriptor
+{
+ uint64_t flags;
+
+ // Pointer to the start of the relevant ROM or RAM chip.
+ // It's strongly recommended to use 'offset' if possible, rather than doing math on the pointer.
+ // If the same byte is mapped my multiple descriptors, their descriptors must have the same pointer.
+ // If 'start' does not point to the first byte in the pointer, put the difference in 'offset' instead.
+ // May be NULL if there's nothing usable here (e.g. hardware registers and open bus). No flags should be set if the pointer is NULL.
+ // It's recommended to minimize the number of descriptors if possible, but not mandatory.
+ void *ptr;
+ size_t offset;
+
+ // This is the location in the emulated address space where the mapping starts.
+ size_t start;
+
+ // Which bits must be same as in 'start' for this mapping to apply.
+ // The first memory descriptor to claim a certain byte is the one that applies.
+ // A bit which is set in 'start' must also be set in this.
+ // Can be zero, in which case each byte is assumed mapped exactly once. In this case, 'len' must be a power of two.
+ size_t select;
+
+ // If this is nonzero, the set bits are assumed not connected to the memory chip's address pins.
+ size_t disconnect;
+
+ // This one tells the size of the current memory area.
+ // If, after start+disconnect are applied, the address is higher than this, the highest bit of the address is cleared.
+ // If the address is still too high, the next highest bit is cleared.
+ // Can be zero, in which case it's assumed to be infinite (as limited by 'select' and 'disconnect').
+ size_t len;
+
+ // To go from emulated address to physical address, the following order applies:
+ // Subtract 'start', pick off 'disconnect', apply 'len', add 'offset'.
+
+ // The address space name must consist of only a-zA-Z0-9_-, should be as short as feasible (maximum length is 8 plus the NUL),
+ // and may not be any other address space plus one or more 0-9A-F at the end.
+ // However, multiple memory descriptors for the same address space is allowed, and the address
+ // space name can be empty. NULL is treated as empty.
+ // Address space names are case sensitive, but avoid lowercase if possible.
+ // The same pointer may exist in multiple address spaces.
+ // Examples:
+ // blank+blank - valid (multiple things may be mapped in the same namespace)
+ // 'Sp'+'Sp' - valid (multiple things may be mapped in the same namespace)
+ // 'A'+'B' - valid (neither is a prefix of each other)
+ // 'S'+blank - valid ('S' is not in 0-9A-F)
+ // 'a'+blank - valid ('a' is not in 0-9A-F)
+ // 'a'+'A' - valid (neither is a prefix of each other)
+ // 'AR'+blank - valid ('R' is not in 0-9A-F)
+ // 'ARB'+blank - valid (the B can't be part of the address either, because there is no namespace 'AR')
+ // blank+'B' - not valid, because it's ambigous which address space B1234 would refer to.
+ // The length can't be used for that purpose; the frontend may want to append arbitrary data to an address, without a separator.
+ const char *addrspace;
+};
+// The frontend may use the largest value of 'start'+'select' in a certain namespace to infer the size of the address space.
+// If the address space is larger than that, a mapping with .ptr=NULL should be at the end of the array, with .select set to all ones for as long as the address space is big.
+// Sample descriptors (minus .ptr, and RETRO_MEMFLAG_ on the flags):
+// SNES WRAM:
+// .start=0x7E0000, .len=0x20000
+// (Note that this must be mapped before the ROM in most cases; some of the ROM mappers try to claim $7E0000, or at least $7E8000.)
+// SNES SPC700 RAM:
+// .addrspace="S", .len=0x10000
+// SNES WRAM mirrors:
+// .flags=MIRROR, .start=0x000000, .select=0xC0E000, .len=0x2000
+// .flags=MIRROR, .start=0x800000, .select=0xC0E000, .len=0x2000
+// SNES WRAM mirrors, alternate equivalent descriptor:
+// .flags=MIRROR, .select=0x40E000, .disconnect=~0x1FFF
+// (Various similar constructions can be created by combining parts of the above two.)
+// SNES LoROM (512KB, mirrored a couple of times):
+// .flags=CONST, .start=0x008000, .select=0x408000, .disconnect=0x8000, .len=512*1024
+// .flags=CONST, .start=0x400000, .select=0x400000, .disconnect=0x8000, .len=512*1024
+// SNES HiROM (4MB):
+// .flags=CONST, .start=0x400000, .select=0x400000, .len=4*1024*1024
+// .flags=CONST, .offset=0x8000, .start=0x008000, .select=0x408000, .len=4*1024*1024
+// SNES ExHiROM (8MB):
+// .flags=CONST, .offset=0, .start=0xC00000, .select=0xC00000, .len=4*1024*1024
+// .flags=CONST, .offset=4*1024*1024, .start=0x400000, .select=0xC00000, .len=4*1024*1024
+// .flags=CONST, .offset=0x8000, .start=0x808000, .select=0xC08000, .len=4*1024*1024
+// .flags=CONST, .offset=4*1024*1024+0x8000, .start=0x008000, .select=0xC08000, .len=4*1024*1024
+// Clarify the size of the address space:
+// .ptr=NULL, .select=0xFFFFFF
+// .len can be implied by .select in many of them, but was included for clarity.
+
+struct retro_memory_map
+{
+ const struct retro_memory_descriptor *descriptors;
+ unsigned num_descriptors;
+};
+
+struct retro_controller_description
+{
+ // Human-readable description of the controller. Even if using a generic input device type, this can be
+ // set to the particular device type the core uses.
+ const char *desc;
+
+ // Device type passed to retro_set_controller_port_device(). If the device type is a sub-class of a generic input device type,
+ // use the RETRO_DEVICE_SUBCLASS macro to create an ID. E.g. RETRO_DEVICE_SUBCLASS(RETRO_DEVICE_JOYPAD, 1).
+ unsigned id;
+};
+
+struct retro_controller_info
+{
+ const struct retro_controller_description *types;
+ unsigned num_types;
+};
+
+struct retro_subsystem_memory_info
+{
+ const char *extension; // The extension associated with a memory type, e.g. "psram".
+ unsigned type; // The memory type for retro_get_memory(). This should be at least 0x100 to avoid conflict with standardized libretro memory types.
+};
+
+struct retro_subsystem_rom_info
+{
+ const char *desc; // Describes what the content is (SGB bios, GB rom, etc).
+ const char *valid_extensions; // Same definition as retro_get_system_info().
+ bool need_fullpath; // Same definition as retro_get_system_info().
+ bool block_extract; // Same definition as retro_get_system_info().
+ bool required; // This is set if the content is required to load a game. If this is set to false, a zeroed-out retro_game_info can be passed.
+
+ // Content can have multiple associated persistent memory types (retro_get_memory()).
+ const struct retro_subsystem_memory_info *memory;
+ unsigned num_memory;
+};
+
+struct retro_subsystem_info
+{
+ const char *desc; // Human-readable string of the subsystem type, e.g. "Super GameBoy"
+ // A computer friendly short string identifier for the subsystem type.
+ // This name must be [a-z].
+ // E.g. if desc is "Super GameBoy", this can be "sgb".
+ // This identifier can be used for command-line interfaces, etc.
+ const char *ident;
+
+ // Infos for each content file. The first entry is assumed to be the "most significant" content for frontend purposes.
+ // E.g. with Super GameBoy, the first content should be the GameBoy ROM, as it is the most "significant" content to a user.
+ // If a frontend creates new file paths based on the content used (e.g. savestates), it should use the path for the first ROM to do so.
+ const struct retro_subsystem_rom_info *roms;
+
+ unsigned num_roms; // Number of content files associated with a subsystem.
+ unsigned id; // The type passed to retro_load_game_special().
+};
+
+typedef void (*retro_proc_address_t)(void);
+// libretro API extension functions:
+// (None here so far).
+//////
+
+// Get a symbol from a libretro core.
+// Cores should only return symbols which are actual extensions to the libretro API.
+// Frontends should not use this to obtain symbols to standard libretro entry points (static linking or dlsym).
+// The symbol name must be equal to the function name, e.g. if void retro_foo(void); exists, the symbol must be called "retro_foo".
+// The returned function pointer must be cast to the corresponding type.
+typedef retro_proc_address_t (*retro_get_proc_address_t)(const char *sym);
+struct retro_get_proc_address_interface
+{
+ retro_get_proc_address_t get_proc_address;
+};
+
+enum retro_log_level
+{
+ RETRO_LOG_DEBUG = 0,
+ RETRO_LOG_INFO,
+ RETRO_LOG_WARN,
+ RETRO_LOG_ERROR,
+
+ RETRO_LOG_DUMMY = INT_MAX
+};
+
+// Logging function. Takes log level argument as well.
+typedef void (*retro_log_printf_t)(enum retro_log_level level, const char *fmt, ...);
+
+struct retro_log_callback
+{
+ retro_log_printf_t log;
+};
+
+// Performance related functions
+//
+// ID values for SIMD CPU features
+#define RETRO_SIMD_SSE (1 << 0)
+#define RETRO_SIMD_SSE2 (1 << 1)
+#define RETRO_SIMD_VMX (1 << 2)
+#define RETRO_SIMD_VMX128 (1 << 3)
+#define RETRO_SIMD_AVX (1 << 4)
+#define RETRO_SIMD_NEON (1 << 5)
+#define RETRO_SIMD_SSE3 (1 << 6)
+#define RETRO_SIMD_SSSE3 (1 << 7)
+#define RETRO_SIMD_MMX (1 << 8)
+#define RETRO_SIMD_MMXEXT (1 << 9)
+#define RETRO_SIMD_SSE4 (1 << 10)
+#define RETRO_SIMD_SSE42 (1 << 11)
+#define RETRO_SIMD_AVX2 (1 << 12)
+#define RETRO_SIMD_VFPU (1 << 13)
+#define RETRO_SIMD_PS (1 << 14)
+
+typedef uint64_t retro_perf_tick_t;
+typedef int64_t retro_time_t;
+
+struct retro_perf_counter
+{
+ const char *ident;
+ retro_perf_tick_t start;
+ retro_perf_tick_t total;
+ retro_perf_tick_t call_cnt;
+
+ bool registered;
+};
+
+// Returns current time in microseconds. Tries to use the most accurate timer available.
+typedef retro_time_t (*retro_perf_get_time_usec_t)(void);
+// A simple counter. Usually nanoseconds, but can also be CPU cycles.
+// Can be used directly if desired (when creating a more sophisticated performance counter system).
+typedef retro_perf_tick_t (*retro_perf_get_counter_t)(void);
+// Returns a bit-mask of detected CPU features (RETRO_SIMD_*).
+typedef uint64_t (*retro_get_cpu_features_t)(void);
+// Asks frontend to log and/or display the state of performance counters.
+// Performance counters can always be poked into manually as well.
+typedef void (*retro_perf_log_t)(void);
+// Register a performance counter.
+// ident field must be set with a discrete value and other values in retro_perf_counter must be 0.
+// Registering can be called multiple times. To avoid calling to frontend redundantly, you can check registered field first.
+typedef void (*retro_perf_register_t)(struct retro_perf_counter *counter);
+// Starts and stops a registered counter.
+typedef void (*retro_perf_start_t)(struct retro_perf_counter *counter);
+typedef void (*retro_perf_stop_t)(struct retro_perf_counter *counter);
+
+// For convenience it can be useful to wrap register, start and stop in macros.
+// E.g.:
+// #ifdef LOG_PERFORMANCE
+// #define RETRO_PERFORMANCE_INIT(perf_cb, name) static struct retro_perf_counter name = {#name}; if (!name.registered) perf_cb.perf_register(&(name))
+// #define RETRO_PERFORMANCE_START(perf_cb, name) perf_cb.perf_start(&(name))
+// #define RETRO_PERFORMANCE_STOP(perf_cb, name) perf_cb.perf_stop(&(name))
+// #else
+// ... Blank macros ...
+// #endif
+// These can then be used mid-functions around code snippets.
+//
+// extern struct retro_perf_callback perf_cb; // Somewhere in the core.
+//
+// void do_some_heavy_work(void)
+// {
+// RETRO_PERFORMANCE_INIT(cb, work_1);
+// RETRO_PERFORMANCE_START(cb, work_1);
+// heavy_work_1();
+// RETRO_PERFORMANCE_STOP(cb, work_1);
+//
+// RETRO_PERFORMANCE_INIT(cb, work_2);
+// RETRO_PERFORMANCE_START(cb, work_2);
+// heavy_work_2();
+// RETRO_PERFORMANCE_STOP(cb, work_2);
+// }
+//
+// void retro_deinit(void)
+// {
+// perf_cb.perf_log(); // Log all perf counters here for example.
+// }
+
+struct retro_perf_callback
+{
+ retro_perf_get_time_usec_t get_time_usec;
+ retro_get_cpu_features_t get_cpu_features;
+
+ retro_perf_get_counter_t get_perf_counter;
+ retro_perf_register_t perf_register;
+ retro_perf_start_t perf_start;
+ retro_perf_stop_t perf_stop;
+ retro_perf_log_t perf_log;
+};
+
+// FIXME: Document the sensor API and work out behavior.
+// It will be marked as experimental until then.
+enum retro_sensor_action
+{
+ RETRO_SENSOR_ACCELEROMETER_ENABLE = 0,
+ RETRO_SENSOR_ACCELEROMETER_DISABLE,
+
+ RETRO_SENSOR_DUMMY = INT_MAX
+};
+
+// Id values for SENSOR types.
+#define RETRO_SENSOR_ACCELEROMETER_X 0
+#define RETRO_SENSOR_ACCELEROMETER_Y 1
+#define RETRO_SENSOR_ACCELEROMETER_Z 2
+
+typedef bool (*retro_set_sensor_state_t)(unsigned port, enum retro_sensor_action action, unsigned rate);
+typedef float (*retro_sensor_get_input_t)(unsigned port, unsigned id);
+struct retro_sensor_interface
+{
+ retro_set_sensor_state_t set_sensor_state;
+ retro_sensor_get_input_t get_sensor_input;
+};
+////
+
+enum retro_camera_buffer
+{
+ RETRO_CAMERA_BUFFER_OPENGL_TEXTURE = 0,
+ RETRO_CAMERA_BUFFER_RAW_FRAMEBUFFER,
+
+ RETRO_CAMERA_BUFFER_DUMMY = INT_MAX
+};
+
+// Starts the camera driver. Can only be called in retro_run().
+typedef bool (*retro_camera_start_t)(void);
+// Stops the camera driver. Can only be called in retro_run().
+typedef void (*retro_camera_stop_t)(void);
+// Callback which signals when the camera driver is initialized and/or deinitialized.
+// retro_camera_start_t can be called in initialized callback.
+typedef void (*retro_camera_lifetime_status_t)(void);
+// A callback for raw framebuffer data. buffer points to an XRGB8888 buffer.
+// Width, height and pitch are similar to retro_video_refresh_t.
+// First pixel is top-left origin.
+typedef void (*retro_camera_frame_raw_framebuffer_t)(const uint32_t *buffer, unsigned width, unsigned height, size_t pitch);
+// A callback for when OpenGL textures are used.
+//
+// texture_id is a texture owned by camera driver.
+// Its state or content should be considered immutable, except for things like texture filtering and clamping.
+//
+// texture_target is the texture target for the GL texture.
+// These can include e.g. GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE, and possibly more depending on extensions.
+//
+// affine points to a packed 3x3 column-major matrix used to apply an affine transform to texture coordinates. (affine_matrix * vec3(coord_x, coord_y, 1.0))
+// After transform, normalized texture coord (0, 0) should be bottom-left and (1, 1) should be top-right (or (width, height) for RECTANGLE).
+//
+// GL-specific typedefs are avoided here to avoid relying on gl.h in the API definition.
+typedef void (*retro_camera_frame_opengl_texture_t)(unsigned texture_id, unsigned texture_target, const float *affine);
+struct retro_camera_callback
+{
+ uint64_t caps; // Set by libretro core. Example bitmask: caps = (1 << RETRO_CAMERA_BUFFER_OPENGL_TEXTURE) | (1 << RETRO_CAMERA_BUFFER_RAW_FRAMEBUFFER).
+
+ unsigned width; // Desired resolution for camera. Is only used as a hint.
+ unsigned height;
+ retro_camera_start_t start; // Set by frontend.
+ retro_camera_stop_t stop; // Set by frontend.
+
+ retro_camera_frame_raw_framebuffer_t frame_raw_framebuffer; // Set by libretro core if raw framebuffer callbacks will be used.
+ retro_camera_frame_opengl_texture_t frame_opengl_texture; // Set by libretro core if OpenGL texture callbacks will be used.
+
+ // Set by libretro core. Called after camera driver is initialized and ready to be started.
+ // Can be NULL, in which this callback is not called.
+ retro_camera_lifetime_status_t initialized;
+
+ // Set by libretro core. Called right before camera driver is deinitialized.
+ // Can be NULL, in which this callback is not called.
+ retro_camera_lifetime_status_t deinitialized;
+};
+
+// Sets the interval of time and/or distance at which to update/poll location-based data.
+// To ensure compatibility with all location-based implementations, values for both
+// interval_ms and interval_distance should be provided.
+// interval_ms is the interval expressed in milliseconds.
+// interval_distance is the distance interval expressed in meters.
+typedef void (*retro_location_set_interval_t)(unsigned interval_ms, unsigned interval_distance);
+
+// Start location services. The device will start listening for changes to the
+// current location at regular intervals (which are defined with retro_location_set_interval_t).
+typedef bool (*retro_location_start_t)(void);
+
+// Stop location services. The device will stop listening for changes to the current
+// location.
+typedef void (*retro_location_stop_t)(void);
+
+// Get the position of the current location. Will set parameters to 0 if no new
+// location update has happened since the last time.
+typedef bool (*retro_location_get_position_t)(double *lat, double *lon, double *horiz_accuracy,
+ double *vert_accuracy);
+
+// Callback which signals when the location driver is initialized and/or deinitialized.
+// retro_location_start_t can be called in initialized callback.
+typedef void (*retro_location_lifetime_status_t)(void);
+
+struct retro_location_callback
+{
+ retro_location_start_t start;
+ retro_location_stop_t stop;
+ retro_location_get_position_t get_position;
+ retro_location_set_interval_t set_interval;
+
+ retro_location_lifetime_status_t initialized;
+ retro_location_lifetime_status_t deinitialized;
+};
+
+enum retro_rumble_effect
+{
+ RETRO_RUMBLE_STRONG = 0,
+ RETRO_RUMBLE_WEAK = 1,
+
+ RETRO_RUMBLE_DUMMY = INT_MAX
+};
+
+// Sets rumble state for joypad plugged in port 'port'. Rumble effects are controlled independently,
+// and setting e.g. strong rumble does not override weak rumble.
+// Strength has a range of [0, 0xffff].
+//
+// Returns true if rumble state request was honored. Calling this before first retro_run() is likely to return false.
+typedef bool (*retro_set_rumble_state_t)(unsigned port, enum retro_rumble_effect effect, uint16_t strength);
+struct retro_rumble_interface
+{
+ retro_set_rumble_state_t set_rumble_state;
+};
+
+// Notifies libretro that audio data should be written.
+typedef void (*retro_audio_callback_t)(void);
+
+// True: Audio driver in frontend is active, and callback is expected to be called regularily.
+// False: Audio driver in frontend is paused or inactive. Audio callback will not be called until set_state has been called with true.
+// Initial state is false (inactive).
+typedef void (*retro_audio_set_state_callback_t)(bool enabled);
+struct retro_audio_callback
+{
+ retro_audio_callback_t callback;
+ retro_audio_set_state_callback_t set_state;
+};
+
+// Notifies a libretro core of time spent since last invocation of retro_run() in microseconds.
+// It will be called right before retro_run() every frame.
+// The frontend can tamper with timing to support cases like fast-forward, slow-motion and framestepping.
+// In those scenarios the reference frame time value will be used.
+typedef int64_t retro_usec_t;
+typedef void (*retro_frame_time_callback_t)(retro_usec_t usec);
+struct retro_frame_time_callback
+{
+ retro_frame_time_callback_t callback;
+ retro_usec_t reference; // Represents the time of one frame. It is computed as 1000000 / fps, but the implementation will resolve the rounding to ensure that framestepping, etc is exact.
+};
+
+// Pass this to retro_video_refresh_t if rendering to hardware.
+// Passing NULL to retro_video_refresh_t is still a frame dupe as normal.
+#define RETRO_HW_FRAME_BUFFER_VALID ((void*)-1)
+
+// Invalidates the current HW context.
+// Any GL state is lost, and must not be deinitialized explicitly. If explicit deinitialization is desired by the libretro core,
+// it should implement context_destroy callback.
+// If called, all GPU resources must be reinitialized.
+// Usually called when frontend reinits video driver.
+// Also called first time video driver is initialized, allowing libretro core to initialize resources.
+typedef void (*retro_hw_context_reset_t)(void);
+// Gets current framebuffer which is to be rendered to. Could change every frame potentially.
+typedef uintptr_t (*retro_hw_get_current_framebuffer_t)(void);
+
+// Get a symbol from HW context.
+typedef retro_proc_address_t (*retro_hw_get_proc_address_t)(const char *sym);
+
+enum retro_hw_context_type
+{
+ RETRO_HW_CONTEXT_NONE = 0,
+ RETRO_HW_CONTEXT_OPENGL = 1, // OpenGL 2.x. Driver can choose to use latest compatibility context.
+ RETRO_HW_CONTEXT_OPENGLES2 = 2, // GLES 2.0
+ RETRO_HW_CONTEXT_OPENGL_CORE = 3, // Modern desktop core GL context. Use version_major/version_minor fields to set GL version.
+ RETRO_HW_CONTEXT_OPENGLES3 = 4, // GLES 3.0
+ RETRO_HW_CONTEXT_OPENGLES_VERSION = 5, // GLES 3.1+. Set version_major/version_minor. For GLES2 and GLES3, use the corresponding enums directly.
+
+ RETRO_HW_CONTEXT_DUMMY = INT_MAX
+};
+
+struct retro_hw_render_callback
+{
+ enum retro_hw_context_type context_type; // Which API to use. Set by libretro core.
+
+ // Called when a context has been created or when it has been reset.
+ // An OpenGL context is only valid after context_reset() has been called.
+ //
+ // When context_reset is called, OpenGL resources in the libretro implementation are guaranteed to be invalid.
+ // It is possible that context_reset is called multiple times during an application lifecycle.
+ // If context_reset is called without any notification (context_destroy),
+ // the OpenGL context was lost and resources should just be recreated
+ // without any attempt to "free" old resources.
+ retro_hw_context_reset_t context_reset;
+
+ retro_hw_get_current_framebuffer_t get_current_framebuffer; // Set by frontend.
+ retro_hw_get_proc_address_t get_proc_address; // Set by frontend.
+ bool depth; // Set if render buffers should have depth component attached.
+ bool stencil; // Set if stencil buffers should be attached.
+ // If depth and stencil are true, a packed 24/8 buffer will be added. Only attaching stencil is invalid and will be ignored.
+ bool bottom_left_origin; // Use conventional bottom-left origin convention. Is false, standard libretro top-left origin semantics are used.
+ unsigned version_major; // Major version number for core GL context or GLES 3.1+.
+ unsigned version_minor; // Minor version number for core GL context or GLES 3.1+.
+
+ bool cache_context; // If this is true, the frontend will go very far to avoid resetting context in scenarios like toggling fullscreen, etc.
+ // The reset callback might still be called in extreme situations such as if the context is lost beyond recovery.
+ // For optimal stability, set this to false, and allow context to be reset at any time.
+
+ retro_hw_context_reset_t context_destroy; // A callback to be called before the context is destroyed in a controlled way by the frontend.
+ // OpenGL resources can be deinitialized cleanly at this step.
+ // context_destroy can be set to NULL, in which resources will just be destroyed without any notification.
+ //
+ // Even when context_destroy is non-NULL, it is possible that context_reset is called without any destroy notification.
+ // This happens if context is lost by external factors (such as notified by GL_ARB_robustness).
+ // In this case, the context is assumed to be already dead,
+ // and the libretro implementation must not try to free any OpenGL resources in the subsequent context_reset.
+
+ bool debug_context; // Creates a debug context.
+};
+
+// Callback type passed in RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK. Called by the frontend in response to keyboard events.
+// down is set if the key is being pressed, or false if it is being released.
+// keycode is the RETROK value of the char.
+// character is the text character of the pressed key. (UTF-32).
+// key_modifiers is a set of RETROKMOD values or'ed together.
+//
+// The pressed/keycode state can be indepedent of the character.
+// It is also possible that multiple characters are generated from a single keypress.
+// Keycode events should be treated separately from character events.
+// However, when possible, the frontend should try to synchronize these.
+// If only a character is posted, keycode should be RETROK_UNKNOWN.
+// Similarily if only a keycode event is generated with no corresponding character, character should be 0.
+typedef void (*retro_keyboard_event_t)(bool down, unsigned keycode, uint32_t character, uint16_t key_modifiers);
+
+struct retro_keyboard_callback
+{
+ retro_keyboard_event_t callback;
+};
+
+// Callbacks for RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE.
+// Should be set for implementations which can swap out multiple disk images in runtime.
+// If the implementation can do this automatically, it should strive to do so.
+// However, there are cases where the user must manually do so.
+//
+// Overview: To swap a disk image, eject the disk image with set_eject_state(true).
+// Set the disk index with set_image_index(index). Insert the disk again with set_eject_state(false).
+
+// If ejected is true, "ejects" the virtual disk tray.
+// When ejected, the disk image index can be set.
+typedef bool (*retro_set_eject_state_t)(bool ejected);
+// Gets current eject state. The initial state is 'not ejected'.
+typedef bool (*retro_get_eject_state_t)(void);
+// Gets current disk index. First disk is index 0.
+// If return value is >= get_num_images(), no disk is currently inserted.
+typedef unsigned (*retro_get_image_index_t)(void);
+// Sets image index. Can only be called when disk is ejected.
+// The implementation supports setting "no disk" by using an index >= get_num_images().
+typedef bool (*retro_set_image_index_t)(unsigned index);
+// Gets total number of images which are available to use.
+typedef unsigned (*retro_get_num_images_t)(void);
+//
+// Replaces the disk image associated with index.
+// Arguments to pass in info have same requirements as retro_load_game().
+// Virtual disk tray must be ejected when calling this.
+// Replacing a disk image with info = NULL will remove the disk image from the internal list.
+// As a result, calls to get_image_index() can change.
+//
+// E.g. replace_image_index(1, NULL), and previous get_image_index() returned 4 before.
+// Index 1 will be removed, and the new index is 3.
+struct retro_game_info;
+typedef bool (*retro_replace_image_index_t)(unsigned index, const struct retro_game_info *info);
+// Adds a new valid index (get_num_images()) to the internal disk list.
+// This will increment subsequent return values from get_num_images() by 1.
+// This image index cannot be used until a disk image has been set with replace_image_index.
+typedef bool (*retro_add_image_index_t)(void);
+
+struct retro_disk_control_callback
+{
+ retro_set_eject_state_t set_eject_state;
+ retro_get_eject_state_t get_eject_state;
+
+ retro_get_image_index_t get_image_index;
+ retro_set_image_index_t set_image_index;
+ retro_get_num_images_t get_num_images;
+
+ retro_replace_image_index_t replace_image_index;
+ retro_add_image_index_t add_image_index;
+};
+
+enum retro_pixel_format
+{
+ // 0RGB1555, native endian. 0 bit must be set to 0.
+ // This pixel format is default for compatibility concerns only.
+ // If a 15/16-bit pixel format is desired, consider using RGB565.
+ RETRO_PIXEL_FORMAT_0RGB1555 = 0,
+
+ // XRGB8888, native endian. X bits are ignored.
+ RETRO_PIXEL_FORMAT_XRGB8888 = 1,
+
+ // RGB565, native endian. This pixel format is the recommended format to use if a 15/16-bit format is desired
+ // as it is the pixel format that is typically available on a wide range of low-power devices.
+ // It is also natively supported in APIs like OpenGL ES.
+ RETRO_PIXEL_FORMAT_RGB565 = 2,
+
+ // Ensure sizeof() == sizeof(int).
+ RETRO_PIXEL_FORMAT_UNKNOWN = INT_MAX
+};
+
+struct retro_message
+{
+ const char *msg; // Message to be displayed.
+ unsigned frames; // Duration in frames of message.
+};
+
+// Describes how the libretro implementation maps a libretro input bind
+// to its internal input system through a human readable string.
+// This string can be used to better let a user configure input.
+struct retro_input_descriptor
+{
+ // Associates given parameters with a description.
+ unsigned port;
+ unsigned device;
+ unsigned index;
+ unsigned id;
+
+ const char *description; // Human readable description for parameters.
+ // The pointer must remain valid until retro_unload_game() is called.
+};
+
+struct retro_system_info
+{
+ // All pointers are owned by libretro implementation, and pointers must remain valid until retro_deinit() is called.
+
+ const char *library_name; // Descriptive name of library. Should not contain any version numbers, etc.
+ const char *library_version; // Descriptive version of core.
+
+ const char *valid_extensions; // A string listing probably rom extensions the core will be able to load, separated with pipe.
+ // I.e. "bin|rom|iso".
+ // Typically used for a GUI to filter out extensions.
+
+ bool need_fullpath; // If true, retro_load_game() is guaranteed to provide a valid pathname in retro_game_info::path.
+ // ::data and ::size are both invalid.
+ // If false, ::data and ::size are guaranteed to be valid, but ::path might not be valid.
+ // This is typically set to true for libretro implementations that must load from file.
+ // Implementations should strive for setting this to false, as it allows the frontend to perform patching, etc.
+
+ bool block_extract; // If true, the frontend is not allowed to extract any archives before loading the real content.
+ // Necessary for certain libretro implementations that load games from zipped archives.
+};
+
+struct retro_game_geometry
+{
+ unsigned base_width; // Nominal video width of game.
+ unsigned base_height; // Nominal video height of game.
+ unsigned max_width; // Maximum possible width of game.
+ unsigned max_height; // Maximum possible height of game.
+
+ float aspect_ratio; // Nominal aspect ratio of game. If aspect_ratio is <= 0.0,
+ // an aspect ratio of base_width / base_height is assumed.
+ // A frontend could override this setting if desired.
+};
+
+struct retro_system_timing
+{
+ double fps; // FPS of video content.
+ double sample_rate; // Sampling rate of audio.
+};
+
+struct retro_system_av_info
+{
+ struct retro_game_geometry geometry;
+ struct retro_system_timing timing;
+};
+
+struct retro_variable
+{
+ const char *key; // Variable to query in RETRO_ENVIRONMENT_GET_VARIABLE.
+ // If NULL, obtains the complete environment string if more complex parsing is necessary.
+ // The environment string is formatted as key-value pairs delimited by semicolons as so:
+ // "key1=value1;key2=value2;..."
+ const char *value; // Value to be obtained. If key does not exist, it is set to NULL.
+};
+
+struct retro_game_info
+{
+ const char *path; // Path to game, UTF-8 encoded. Usually used as a reference.
+ // May be NULL if rom was loaded from stdin or similar.
+ // retro_system_info::need_fullpath guaranteed that this path is valid.
+ const void *data; // Memory buffer of loaded game. Will be NULL if need_fullpath was set.
+ size_t size; // Size of memory buffer.
+ const char *meta; // String of implementation specific meta-data.
+};
+
+// Callbacks
+//
+// Environment callback. Gives implementations a way of performing uncommon tasks. Extensible.
+typedef bool (*retro_environment_t)(unsigned cmd, void *data);
+
+// Render a frame. Pixel format is 15-bit 0RGB1555 native endian unless changed (see RETRO_ENVIRONMENT_SET_PIXEL_FORMAT).
+// Width and height specify dimensions of buffer.
+// Pitch specifices length in bytes between two lines in buffer.
+// For performance reasons, it is highly recommended to have a frame that is packed in memory, i.e. pitch == width * byte_per_pixel.
+// Certain graphic APIs, such as OpenGL ES, do not like textures that are not packed in memory.
+typedef void (*retro_video_refresh_t)(const void *data, unsigned width, unsigned height, size_t pitch);
+
+// Renders a single audio frame. Should only be used if implementation generates a single sample at a time.
+// Format is signed 16-bit native endian.
+typedef void (*retro_audio_sample_t)(int16_t left, int16_t right);
+// Renders multiple audio frames in one go. One frame is defined as a sample of left and right channels, interleaved.
+// I.e. int16_t buf[4] = { l, r, l, r }; would be 2 frames.
+// Only one of the audio callbacks must ever be used.
+typedef size_t (*retro_audio_sample_batch_t)(const int16_t *data, size_t frames);
+
+// Polls input.
+typedef void (*retro_input_poll_t)(void);
+// Queries for input for player 'port'. device will be masked with RETRO_DEVICE_MASK.
+// Specialization of devices such as RETRO_DEVICE_JOYPAD_MULTITAP that have been set with retro_set_controller_port_device()
+// will still use the higher level RETRO_DEVICE_JOYPAD to request input.
+typedef int16_t (*retro_input_state_t)(unsigned port, unsigned device, unsigned index, unsigned id);
+
+// Sets callbacks. retro_set_environment() is guaranteed to be called before retro_init().
+// The rest of the set_* functions are guaranteed to have been called before the first call to retro_run() is made.
+void retro_set_environment(retro_environment_t);
+void retro_set_video_refresh(retro_video_refresh_t);
+void retro_set_audio_sample(retro_audio_sample_t);
+void retro_set_audio_sample_batch(retro_audio_sample_batch_t);
+void retro_set_input_poll(retro_input_poll_t);
+void retro_set_input_state(retro_input_state_t);
+
+// Library global initialization/deinitialization.
+void retro_init(void);
+void retro_deinit(void);
+
+// Must return RETRO_API_VERSION. Used to validate ABI compatibility when the API is revised.
+unsigned retro_api_version(void);
+
+// Gets statically known system info. Pointers provided in *info must be statically allocated.
+// Can be called at any time, even before retro_init().
+void retro_get_system_info(struct retro_system_info *info);
+
+// Gets information about system audio/video timings and geometry.
+// Can be called only after retro_load_game() has successfully completed.
+// NOTE: The implementation of this function might not initialize every variable if needed.
+// E.g. geom.aspect_ratio might not be initialized if core doesn't desire a particular aspect ratio.
+void retro_get_system_av_info(struct retro_system_av_info *info);
+
+// Sets device to be used for player 'port'.
+// By default, RETRO_DEVICE_JOYPAD is assumed to be plugged into all available ports.
+// Setting a particular device type is not a guarantee that libretro cores will only poll input based on that particular device type. It is only a hint to the libretro core when a core cannot automatically detect the appropriate input device type on its own. It is also relevant when a core can change its behavior depending on device type.
+void retro_set_controller_port_device(unsigned port, unsigned device);
+
+// Resets the current game.
+void retro_reset(void);
+
+// Runs the game for one video frame.
+// During retro_run(), input_poll callback must be called at least once.
+//
+// If a frame is not rendered for reasons where a game "dropped" a frame,
+// this still counts as a frame, and retro_run() should explicitly dupe a frame if GET_CAN_DUPE returns true.
+// In this case, the video callback can take a NULL argument for data.
+void retro_run(void);
+
+// Returns the amount of data the implementation requires to serialize internal state (save states).
+// Beetween calls to retro_load_game() and retro_unload_game(), the returned size is never allowed to be larger than a previous returned value, to
+// ensure that the frontend can allocate a save state buffer once.
+size_t retro_serialize_size(void);
+
+// Serializes internal state. If failed, or size is lower than retro_serialize_size(), it should return false, true otherwise.
+bool retro_serialize(void *data, size_t size);
+bool retro_unserialize(const void *data, size_t size);
+
+void retro_cheat_reset(void);
+void retro_cheat_set(unsigned index, bool enabled, const char *code);
+
+// Loads a game.
+bool retro_load_game(const struct retro_game_info *game);
+
+// Loads a "special" kind of game. Should not be used except in extreme cases.
+bool retro_load_game_special(
+ unsigned game_type,
+ const struct retro_game_info *info, size_t num_info
+);
+
+// Unloads a currently loaded game.
+void retro_unload_game(void);
+
+// Gets region of game.
+unsigned retro_get_region(void);
+
+// Gets region of memory.
+void *retro_get_memory_data(unsigned id);
+size_t retro_get_memory_size(unsigned id);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/allegrowrapper/wrapalleg.c b/allegrowrapper/wrapalleg.c
new file mode 100755
index 0000000..68cd53c
--- /dev/null
+++ b/allegrowrapper/wrapalleg.c
@@ -0,0 +1,207 @@
+
+#include "wrapalleg.h"
+
+#include
+#include
+#include
+#define abs(a) miabs(a)
+
+int miabs(int a){
+ if((a)<0)a=-a;
+ return a;
+}
+
+void upcase(char *p)
+{
+ while(*p != '\0')
+ {
+ if(*p >= 97 && *p <= 122)
+ *p -= 32;
+ ++p;
+ }
+}
+void downcase(char *p)
+{
+ while(*p != '\0')
+ {
+ if(*p >= 97-32 && *p <= 122-32)
+ *p += 32;
+ ++p;
+ }
+}
+
+void clear(BITMAP *buff){
+
+ memset(&buff->line,0,buff->w*buff->h);
+}
+
+BITMAP *create_bitmap(int w,int h){
+
+ BITMAP *buff;
+
+ buff = malloc(sizeof (BITMAP));
+ buff->line=malloc(1*w*h);
+
+ buff->w=w;
+ buff->h=h;
+ buff->pitch=w;
+ buff->depth=1;
+
+ return buff;
+}
+
+int destroy_bitmap(BITMAP *buff){
+
+ if (buff->line) {
+ free(buff->line);
+ }
+ free(buff);
+
+ return 0;
+}
+
+
+void rect(BITMAP *buff,int x,int y,int x2,int y2,unsigned char color){
+
+// int i,j,idx;
+//
+// int dx= abs(x2-x);
+// int dy= abs(y2-y);
+// int V_WIDTH = buff->w;
+// unsigned char *buffer=buff->line[0];
+//
+// for(i=x;iw;
+// unsigned char *buffer=buff->line[0];
+//
+// for(i=x;iw;
+// unsigned char *buffer=buff->line[0];
+//
+// for(i=x;iw;
+// unsigned char *buffer=buff->line[0];
+//
+// for(j=y;jw;
+// unsigned char *buffer=buff->line[0];
+//
+// dx = x2 - x1;
+// dy = y2 - y1;
+// sx = (dx >= 0) ? 1 : -1;
+// sy = (dy >= 0) ? 1 : -1;
+//
+// if (dx==0) {
+// if (dy>0) {
+// DrawVline(buff, x1, y1,0, dy, color);
+// return;
+//
+// } else if (dy<0) {
+// DrawVline(buff, x1, y2,0, -dy, color);
+// return;
+//
+// } else {
+// idx=x1+y1*V_WIDTH;
+// buffer[idx]=color;
+// return ;
+// }
+// }
+// if (dy == 0) {
+// if (dx>0) {
+// DrawHline(buff, x1, y1, dx, 0, color);
+// return;
+//
+// } else if (dx<0) {
+// DrawHline(buff, x2, y1, -dx,0, color);
+// return;
+// }
+// }
+//
+// dx = sx * dx + 1;
+// dy = sy * dy + 1;
+//
+// pixx = 1;
+// pixy = V_WIDTH;
+//
+// pixx *= sx;
+// pixy *= sy;
+//
+// if (dx < dy) {
+// swaptmp = dx;
+// dx = dy;
+// dy = swaptmp;
+// swaptmp = pixx;
+// pixx = pixy;
+// pixy = swaptmp;
+// }
+//
+// x = 0;
+// y = 0;
+//
+// idx=x1+y1*V_WIDTH;
+//
+// for (; x < dx; x++, idx +=pixx) {
+// buffer[idx]=color;
+// y += dy;
+// if (y >= dx) {
+// y -= dx;
+// idx += pixy;
+// }
+// }
+
+}
diff --git a/allegrowrapper/wrapalleg.h b/allegrowrapper/wrapalleg.h
new file mode 100755
index 0000000..76258a5
--- /dev/null
+++ b/allegrowrapper/wrapalleg.h
@@ -0,0 +1,56 @@
+
+#ifndef WRAP_H
+#define WRAP_H 1
+
+#include
+#define INLINE static inline
+#define rest(a) usleep(a)
+#define strupr upcase
+#define strlwr downcase
+#define keypressed() 0
+#define poll_keyboard()
+#define yield_timeslice()
+
+typedef struct
+{
+ unsigned char *line;
+ int w;
+ int h;
+ int pitch;
+ int depth;
+
+}BITMAP;
+
+typedef struct
+{
+ unsigned char r;
+ unsigned char g;
+ unsigned char b;
+}APALETTE;
+
+
+BITMAP *create_bitmap(int w,int h);
+int destroy_bitmap(BITMAP *buff);
+void line(BITMAP *buff,int x1,int y1,int x2,int y2,unsigned char color);
+void rect(BITMAP *buff,int x,int y,int x2,int y2,unsigned char color);
+void rectfill(BITMAP *buff,int x,int y,int x2,int y2,unsigned char color);
+void upcase(char *p);
+void downcase(char *p);
+
+extern unsigned char key[256*2];
+
+extern void update_joy(void);
+
+#define INLINE static inline
+
+#define EMUWIDTH 340
+#define EMUHEIGHT 250
+
+#define TEX_WIDTH 400
+#define TEX_HEIGHT 300
+
+#define RGB565(r, g, b) (((r) << (5+6)) | ((g) << 6) | (b))
+
+
+#endif
+
diff --git a/clean/src/CHANGELOG b/clean/src/CHANGELOG
new file mode 100755
index 0000000..71dbb60
--- /dev/null
+++ b/clean/src/CHANGELOG
@@ -0,0 +1,316 @@
+v1.18: 01/15/2007
+
+ - added the option -biosdir to define bios directory path
+ - added the option -romdir to define rom directory path
+ - added the option -help to help display
+ - directory search fix : When you don't have the "roms/" and/or "bios/"
+ directory, the program will dump core (by Walter de Jong).
+ - O2Launcher works now, o2em ignore roms and bios path if o2Launcher
+ is running.
+ - quad display fix: changed the way quad chars are drawn, fixes problems
+ in KTAA as well as score display in Black Hole and Red Baron (Soeren Gust)
+ - support for Soerens MegaCART bank switching (Information about
+ how to use this will be included in the next verison of Soerens
+ Bios-Documentation) (Soeren Gust)
+ - new feature in debugger: savevpp to make an uncompressed dump of the VPP
+ screen and slide data (Soeren Gust)
+ - dis48: fix to work under linux again (Soeren Gust)
+ - init_sound volume is not set to maximum (By Gunter Wambaugh)
+ - added makefile and options for freeBSD (By Gunter Wambaugh)
+ - Other minor fixes.
+
+
+ all the next changes were implemented by Manopac:
+
+ - added the option -s0 to redefine the system keys (see o2em.txt for usage)
+ - bugfix: highscore-file is only written if scoretype is set
+ - changed Default Stick 1 key from right to "L" to enable Fire and
+ movement at the same time
+ - two joysticks can be used now: first stick in command-line is mapped to joystick 1,
+ second to joystick 2 (compatible to old command line options)
+ - changes in debugger: status of registers is now displayed after instructions
+ are executed
+ - new features in debugger: savedatah and savedatab to save data from memory
+ as sourcecode ("db xxx")
+ - changed Default Stick 1 key from right to "L" to enable Fire
+ and movement at the same time
+ - two joysticks can be used now: first stick in command-line is mapped to
+ joystick 1, second to joystick 2 (compatible to old command line options)
+ - changes in debugger: status of registers is now displayed after
+ instructions are executed
+ - new features in debugger: savedatah and savedatab to save data from memory
+ as sourcecode ("db xxx")
+ - removed the limit that KTAA was the only 3K enabled rom (every
+ rom divideable by 3K is allowed now)
+ - dis48: added option -bios to disassemble bios (start at address 0)
+ - dis48: empty line after each page
+ - new feature to save the highscore in games (F6 to set in game)
+ - new feature to save/load state (F2/F3) (with command line option savefile)
+ - new features in debugger: savevdc and saveext to save data from Extram and VDC
+ - new feature in debugger: viewsprite
+ - new feature in debugger: bp (breakpoint) - o2em runs with output until
+ breakpoint is reached (bpc to clear)
+ - new feature in debugger: so (step over) - runs to next instruction in memory
+ - more explicit register display (P1 & PSW)
+ - fixed the "double size sprites are shifted only 1 instead of 2 pixles" bug
+ - new features in debugger (load / save file, change values in memory,
+ assemble to memory)
+
+v1.17: 05/01/2005
+
+ - BIOS identified by CRC, to activate a specific BIOS type: -o2rom, or
+ -g7400, or -c52, or -jopac. The old form can be used. See O2EM.txt for more.
+
+ - Automatic identification of BIOS VP+ when the selected game is only VP+.
+
+ - Creation of the standard directories (ROMS, BIOS, VOICE) when uncompressing
+ O2EM archive.
+
+ - ATLANTIS, FROGGER, COMANDO NOTURNO and CATCH THE BALL now work without
+ graphic bugs. This correction is based on a specific patch for each game.
+ Thanks Rafael Cardoso for reports these bugs.
+
+
+V1.16: 12/28/2004
+
+ - Fixed a slowdown in Pick Axe Pete (based on a patch by Arlindo de
+ Oliveira).
+
+ - Reverted back to the old palette for O2 games, while using the new
+ palette for Videpac Plus games (selected based on bios version in use).
+
+
+V1.15: 12/12/2004
+
+ - Added support for 12kb and 16kb games. Trans American Rally+ works now.
+
+ - Added fixes to the VP+ gfx emulation made by Soeren Gust. Flashpoint
+ works properly now.
+
+ - Fixed a bug in the Windows-specific emulation timing code that caused
+ the emulator to crash when run on a Windows machine which was on for a
+ few days without a reboot.
+
+ - Fixed a bug in the emulation of the DAA instruction, which caused bugs
+ in the score of several games (Le Tresor Englouti, Cosmic Conflict, etc.).
+
+ - Fixed instruction timings (patch by Soeren)
+
+ - Modified the palette to use values calculated from the Videopac+ RGB
+ encoder specs by René van den Enden, instead of guessed values.
+
+ - Other minor fixes.
+
+
+
+V1.01: 10/23/2002
+
+ - Major speed optimization.
+
+ - Implemented VDC <-> VP+ collision detection.
+
+ - On the original machines it is possible to make all VDC
+ colors bright by clearing P17. This affects the background and
+ dark grid colors. Implemented. Now the Killer Bees! intro screen
+ works correctly.
+
+ - Fixed the wrong color order when mixing between VP+ and VDC graphics.
+ Jopac Moto Crash now works. Fixed by Soeren Gust.
+
+ - Now the VBLANK pulse is visible on the T1 input. This can be used
+ to differentiate between PAL and NTSC.
+
+ - Other minor fixes.
+
+
+
+V1.00: 09/12/2002
+
+ - Implemented complete Videopac+ G7400 emulation. Implemented it from
+ scratch, based on the EF9340/41 datasheet (sent by Simon Scudder), on
+ the technical docs made by Soeren Gust and disassembling the VP+ bios.
+ You will need a Videopac+ bios image file in order to use this feature.
+ You can use the -bios option to select it, rename the file to o2rom.bin,
+ or select it in O2EM Launcher settings. Please note that a few O2 games
+ do not work with the VP+ bios, so most likely you will need both bios
+ versions to be able to run all the games. For copyright reasons these
+ files are not included with O2EM, but you can find them in the Internet.
+
+ - Added a default configuration file. Now you can specify your preferred
+ options in a configuration file, instead of typing it every time you
+ execute the emulator. The command line options override the default
+ settings in the file. See O2EM.txt for more.
+
+ - Extended the -s1 and -s2 switches to allow customizable keys with the
+ joystick emulation. Based on a patch written by Zimmerman that
+ implemented customizable keys it in a different way. See O2EM.txt for
+ more.
+
+ - Added support to the Four in 1 Row game.
+
+ - Added the -exrom switch to enable the use of a special ROM mapping mode.
+ See O2EM.txt for more.
+
+ - Improved the sound with Frogger and Popeye.
+
+ - Minor fixes.
+
+
+
+V0.90: 08/07/2002
+
+ - Fixed the color palette, based on screen shots from a real O2 console.
+
+ - Fixed a bug in the sprite drawing priority. Now in several games the
+ sprites look better (Demon Attack, Turtles, Atlantis, Computer Golf,
+ Football, Helicopter Rescue, etc.).
+
+ - Modified the emulation of sprites and characters in the border region of
+ the screen. Fixed the bug of character wrapping to the other side of the
+ screen and other problems (Atlantis and others). Now the main characters of
+ P.T.Barnum's Acrobats! do not fall from the edge of screen.
+
+ - Fixed the audio pitch and implemented white noise emulation. Now
+ explosions sound much better!
+
+ - Fixed a background line blinking problem that used to affect lots of
+ games.
+
+ - Fixed the color bar at the left of the screen.
+
+ - Enhanced the support for European/Pal games. Now several games look and
+ play better. Shark Hunter intro works correctly. Frogger and Depth Charge
+ are fully playable !
+
+ - Implemented an audio filter that accurately emulates the behavior of the
+ low-pass filter present in the audio output of the real console. The sound
+ is better now. (Enable it with -filter).
+
+ - Fixed the screen size. Now you can see all the graphics in the game,
+ including the time in Labyrinth.
+
+ - Implemented Dot Grid emulation. Now Marksman is playable.
+
+ - Implemented a cached video emulation, to make it run faster with slow
+ machines / video cards.
+
+ - Implemented screen shots (use the F8 key and the -scshot option)
+
+ - Implemented the sprite shifted/smooth modes. Now the main character of
+ Q*bert looks hi-res.
+
+ - Several minor fixes.
+
+
+ The following fixes were made by Soeren Gust:
+
+
+ - Implemented the missing JNI instruction.
+
+ - Implemented the 1kb data ROM / 3kb program ROM addressing mode used by
+ Musician.
+
+ - Fixed the height of the grid lines.
+
+ - Added support for 3Kb per bank
+
+
+
+V0.87: 06/21/2002
+
+ - Fixed a collision bug introduced with version 0.86.
+ Now Cosmic Conflict runs again. Thanks to Dan Boris for reporting
+ this bug.
+
+ - Implemented the option to set the O2 bios file name/dir, as
+ requested by my friend Heitor, to enable him to support it with his
+ nice O2EMLauncher frontend for O2EM 0.8x, as requested by its users.
+ Get O2EMLauncher here: http://www.odyssey.com.br/o2emlauncher/
+
+
+
+Version 0.86:
+
+ - Fixed a bug in the drawing of quad characters. Now you can play
+ Q*Bert and Nimble Numbers Ned. Some other games will also have
+ improved graphics or text (Popeye, Super Cobra, etc.) .
+
+ - Fixed another bug in the collision detection. Now Demon Attack
+ works correctly.
+
+
+
+Version 0.85:
+
+ - Fixed the collision detection. Now you can play Killer Bees!
+
+ - Implemented partial support to mid-screen changes to the VDC
+ registers without interrupts. Now several games look better, and some
+ that didn't work can be played, including Power Lords and Super Cobra.
+
+ - Fixed a bug in the video emulation that made some games like Turtles
+ and Shark Hunter appear with some strange static characters.
+
+
+
+Version 0.80:
+
+The following changes were already implemented by Daniel Boris in version
+0.701. Implemented them again in the sources based on version v0.65:
+
+ - Fixed a bug in the CPU core related to the handling of branch
+ instructions near page boundaries. (Without it Sid the Spellbinder
+ crashed after the first level).
+
+ - CPU core now jumps to the correct address on an external interrupt.
+ Killer Bees runs again.
+
+ - Fixed shape of '$' character and added missing 64th character to
+ character set (ripped the correct character data from the v0.701
+ executable file).
+
+ - Fixed bug in drawing of bottom grid line.
+
+ - Added Voice support. Re implemented it from scratch, based on O2
+ technical specs released by Dan Boris and disassembling Smithereens
+ and Turtles (now it always work with Turtles).
+
+The following changes are new to version 0.80:
+
+ - Updated the code to compile with Allegro 4.0.x and to work
+ without changes under Windows, Linux and DOS, with optimizations
+ for each.
+
+ - Implemented the option of windowed or fullscreen video modes,
+ with scaling, centering and optional 50% scanlines.
+
+ - Cleaned the code to make it more portable and maintainable.
+
+ - Improved timing, using the most accurate way available for
+ each platform.
+
+ - Fixed the keyboard scan code translation table.
+
+ - Fixed and improved the built-in debugger.
+
+ - Fixed the reset. It now works with Turtles.
+
+ - Fixed joystick detection code.
+
+ - Implemented variable speed control relative to original O2.
+
+ - Implemented individual volume control for sounds and voice.
+
+ - Implemented Pause/Information (F1).
+
+ - Avoided collision of keyboard input with key joystick
+ emulation. Now Caps Lock enables/disables the W,D,S,A,Space keys
+ for keyboard input when they are used by joystick emulation.
+ Works well with games like K.C.'s Krazy Chase.
+
+ - It now releases more CPU time to the system (if possible).
+
+ - Other minor changes/fixes.
+
+
+
diff --git a/clean/src/COPYING b/clean/src/COPYING
new file mode 100755
index 0000000..255c6f4
--- /dev/null
+++ b/clean/src/COPYING
@@ -0,0 +1,138 @@
+
+ The Clarified Artistic License
+
+ Preamble
+
+The intent of this document is to state the conditions under which a
+Package may be copied, such that the Copyright Holder maintains some
+semblance of artistic control over the development of the package,
+while giving the users of the package the right to use and distribute
+the Package in a more-or-less customary fashion, plus the right to make
+reasonable modifications.
+
+Definitions:
+
+ "Package" refers to the collection of files distributed by the
+ Copyright Holder, and derivatives of that collection of files
+ created through textual modification.
+
+ "Standard Version" refers to such a Package if it has not been
+ modified, or has been modified in accordance with the wishes
+ of the Copyright Holder as specified below.
+
+ "Copyright Holder" is whoever is named in the copyright or
+ copyrights for the package.
+
+ "You" is you, if you're thinking about copying or distributing
+ this Package.
+
+ "Distribution fee" is a fee you charge for providing a copy
+ of this Package to another party.
+
+ "Freely Available" means that no fee is charged for the right to
+ use the item, though there may be fees involved in handling the
+ item. It also means that recipients of the item may redistribute
+ it under the same conditions they received it.
+
+1. You may make and give away verbatim copies of the source form of the
+Standard Version of this Package without restriction, provided that you
+duplicate all of the original copyright notices and associated disclaimers.
+
+2. You may apply bug fixes, portability fixes and other modifications
+derived from the Public Domain, or those made Freely Available, or from
+the Copyright Holder. A Package modified in such a way shall still be
+considered the Standard Version.
+
+3. You may otherwise modify your copy of this Package in any way, provided
+that you insert a prominent notice in each changed file stating how and
+when you changed that file, and provided that you do at least ONE of the
+following:
+
+ a) place your modifications in the Public Domain or otherwise make them
+ Freely Available, such as by posting said modifications to Usenet or an
+ equivalent medium, or placing the modifications on a major network
+ archive site allowing unrestricted access to them, or by allowing the
+ Copyright Holder to include your modifications in the Standard Version
+ of the Package.
+
+ b) use the modified Package only within your corporation or organization.
+
+ c) rename any non-standard executables so the names do not conflict
+ with standard executables, which must also be provided, and provide
+ a separate manual page for each non-standard executable that clearly
+ documents how it differs from the Standard Version.
+
+ d) make other distribution arrangements with the Copyright Holder.
+
+ e) permit and encourge anyone who receives a copy of the modified Package
+ permission to make your modifications Freely Available
+ in some specific way.
+
+
+4. You may distribute the programs of this Package in object code or
+executable form, provided that you do at least ONE of the following:
+
+ a) distribute a Standard Version of the executables and library files,
+ together with instructions (in the manual page or equivalent) on where
+ to get the Standard Version.
+
+ b) accompany the distribution with the machine-readable source of
+ the Package with your modifications.
+
+ c) give non-standard executables non-standard names, and clearly
+ document the differences in manual pages (or equivalent), together
+ with instructions on where to get the Standard Version.
+
+ d) make other distribution arrangements with the Copyright Holder.
+
+ e) offer the machine-readable source of the Package, with your
+ modifications, by mail order.
+
+5. You may charge a distribution fee for any distribution of this Package.
+If you offer support for this Package, you may charge any fee you choose
+for that support. You may not charge a license fee for the right to use
+this Package itself. You may distribute this Package in aggregate with
+other (possibly commercial and possibly nonfree) programs as part of a
+larger (possibly commercial and possibly nonfree) software distribution,
+and charge license fees for other parts of that software distribution,
+provided that you do not advertise this Package as a product of your own.
+If the Package includes an interpreter, You may embed this Package's
+interpreter within an executable of yours (by linking); this shall be
+construed as a mere form of aggregation, provided that the complete
+Standard Version of the interpreter is so embedded.
+
+6. The scripts and library files supplied as input to or produced as
+output from the programs of this Package do not automatically fall
+under the copyright of this Package, but belong to whoever generated
+them, and may be sold commercially, and may be aggregated with this
+Package. If such scripts or library files are aggregated with this
+Package via the so-called "undump" or "unexec" methods of producing a
+binary executable image, then distribution of such an image shall
+neither be construed as a distribution of this Package nor shall it
+fall under the restrictions of Paragraphs 3 and 4, provided that you do
+not represent such an executable image as a Standard Version of this
+Package.
+
+7. C subroutines (or comparably compiled subroutines in other
+languages) supplied by you and linked into this Package in order to
+emulate subroutines and variables of the language defined by this
+Package shall not be considered part of this Package, but are the
+equivalent of input as in Paragraph 6, provided these subroutines do
+not change the language in any way that would cause it to fail the
+regression tests for the language.
+
+8. Aggregation of the Standard Version of the Package with a commercial
+distribution is always permitted provided that the use of this Package
+is embedded; that is, when no overt attempt is made to make this Package's
+interfaces visible to the end user of the commercial distribution.
+Such use shall not be construed as a distribution of this Package.
+
+9. The name of the Copyright Holder may not be used to endorse or promote
+products derived from this software without specific prior written permission.
+
+10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+ The End
+
diff --git a/clean/src/Makefile b/clean/src/Makefile
new file mode 100755
index 0000000..2314944
--- /dev/null
+++ b/clean/src/Makefile
@@ -0,0 +1,81 @@
+CC = gcc
+
+CFLAGS = -O3 -Wall -fomit-frame-pointer -I/usr/include
+LFLAGS = -s
+#LIBALLEG = /usr/lib/liballeg.so.4.2 -lalleg_unsharable
+LIBS=`allegro-config --libs`
+VERSION='1.18'
+ARCH=`uname -i`
+
+
+all: o2em dis48
+
+clean:
+ rm -f audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o score.o dis48.o
+
+
+o2em: audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o score.o
+ $(CC) $(LFLAGS) audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o score.o -o o2em $(LIBS)
+
+dis48: dis48.o table.o
+ $(CC) $(LFLAGS) dis48.o table.o -o dis48
+
+
+audio.o: audio.c audio.h cpu.h types.h config.h vmachine.h
+ $(CC) $(CFLAGS) -c audio.c -o audio.o
+
+cpu.o: cpu.c cpu.h types.h vmachine.h keyboard.h voice.h vdc.h vpp.h
+ $(CC) $(CFLAGS) -c cpu.c -o cpu.o
+
+cset.o: cset.c cset.h types.h
+ $(CC) $(CFLAGS) -c cset.c -o cset.o
+
+debug.o: debug.c debug.h cpu.h keyboard.h vmachine.h audio.h vdc.h table.h
+ $(CC) $(CFLAGS) -c debug.c -o debug.o
+
+dis48.o: dis48.c types.h table.h
+ $(CC) $(CFLAGS) -c dis48.c -o dis48.o
+
+keyboard.o: keyboard.c keyboard.h types.h cpu.h vmachine.h vdc.h audio.h voice.h vpp.h
+ $(CC) $(CFLAGS) -c keyboard.c -o keyboard.o
+
+main.o: main.c crc32.h audio.h vmachine.h config.h vdc.h cpu.h debug.h keyboard.h voice.h
+ $(CC) $(CFLAGS) -c main.c -o main.o
+
+table.o: table.c table.h cpu.h
+ $(CC) $(CFLAGS) -c table.c -o table.o
+
+vdc.o: vdc.c vdc.h types.h vmachine.h config.h keyboard.h cset.h timefunc.h cpu.h vpp.h
+ $(CC) $(CFLAGS) -c vdc.c -o vdc.o
+
+vmachine.o: vmachine.c vmachine.h audio.h types.h cpu.h keyboard.h config.h debug.h vdc.h vpp.h timefunc.h voice.h
+ $(CC) $(CFLAGS) -c vmachine.c -o vmachine.o
+
+timefunc.o: timefunc.c timefunc.h
+ $(CC) $(CFLAGS) -c timefunc.c -o timefunc.o
+
+voice.o: voice.c voice.h vmachine.h cpu.h
+ $(CC) $(CFLAGS) -c voice.c -o voice.o
+
+crc32.o: crc32.c crc32.h
+ $(CC) $(CFLAGS) -c crc32.c -o crc32.o
+
+vpp_cset.o: vpp_cset.c vpp_cset.h
+ $(CC) $(CFLAGS) -c vpp_cset.c -o vpp_cset.o
+
+vpp.o: vpp.c vpp.h types.h vpp_cset.h vmachine.h vdc.h
+ $(CC) $(CFLAGS) -c vpp.c -o vpp.o
+
+score.o: score.c score.h vmachine.h types.h
+ $(CC) $(CFLAGS) -c score.c -o score.o
+
+dist: all
+ mkdir -p o2em-$(VERSION)
+ mv o2em o2em-$(VERSION)
+ mv dis48 o2em-$(VERSION)
+ cp o2em.png o2em-$(VERSION)
+ cp COPYING o2em-$(VERSION)
+ cp README o2em-$(VERSION)
+ mv o2em-$(VERSION) o2em
+ tar czf o2em-$(VERSION)-$(ARCH).tar.gz o2em
+ rm -r o2em
diff --git a/clean/src/Makefile.djgpp b/clean/src/Makefile.djgpp
new file mode 100755
index 0000000..12c7e4a
--- /dev/null
+++ b/clean/src/Makefile.djgpp
@@ -0,0 +1,71 @@
+CC = gcc
+
+CFLAGS = -O3 -Wall -fomit-frame-pointer
+LFLAGS = -s
+LIBALLEG = -lalleg
+
+
+all: o2em.exe dis48.exe
+
+clean:
+ del *.o
+
+
+o2em.exe: audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o o2em.res score.o
+ $(CC) $(LFLAGS) audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o score.o o2em.res -o o2em.exe $(LIBALLEG)
+
+dis48.exe: dis48.o table.o
+ $(CC) $(LFLAGS) dis48.o table.o -o dis48.exe
+
+
+audio.o: audio.c audio.h cpu.h types.h config.h vmachine.h
+ $(CC) $(CFLAGS) -c audio.c -o audio.o
+
+cpu.o: cpu.c cpu.h types.h vmachine.h keyboard.h voice.h vdc.h vpp.h
+ $(CC) $(CFLAGS) -c cpu.c -o cpu.o
+
+cset.o: cset.c cset.h types.h
+ $(CC) $(CFLAGS) -c cset.c -o cset.o
+
+debug.o: debug.c debug.h cpu.h keyboard.h vmachine.h audio.h vdc.h table.h
+ $(CC) $(CFLAGS) -c debug.c -o debug.o
+
+dis48.o: dis48.c types.h table.h
+ $(CC) $(CFLAGS) -c dis48.c -o dis48.o
+
+keyboard.o: keyboard.c keyboard.h types.h cpu.h vmachine.h vdc.h audio.h voice.h vpp.h score.h
+ $(CC) $(CFLAGS) -c keyboard.c -o keyboard.o
+
+main.o: main.c crc32.h audio.h vmachine.h config.h vdc.h cpu.h debug.h keyboard.h voice.h score.h
+ $(CC) $(CFLAGS) -c main.c -o main.o
+
+table.o: table.c table.h cpu.h
+ $(CC) $(CFLAGS) -c table.c -o table.o
+
+vdc.o: vdc.c vdc.h types.h vmachine.h config.h keyboard.h cset.h timefunc.h cpu.h vpp.h
+ $(CC) $(CFLAGS) -c vdc.c -o vdc.o
+
+vmachine.o: vmachine.c vmachine.h audio.h types.h cpu.h keyboard.h config.h debug.h vdc.h vpp.h timefunc.h voice.h
+ $(CC) $(CFLAGS) -c vmachine.c -o vmachine.o
+
+timefunc.o: timefunc.c timefunc.h
+ $(CC) $(CFLAGS) -c timefunc.c -o timefunc.o
+
+voice.o: voice.c voice.h vmachine.h cpu.h
+ $(CC) $(CFLAGS) -c voice.c -o voice.o
+
+crc32.o: crc32.c crc32.h
+ $(CC) $(CFLAGS) -c crc32.c -o crc32.o
+
+vpp_cset.o: vpp_cset.c vpp_cset.h
+ $(CC) $(CFLAGS) -c vpp_cset.c -o vpp_cset.o
+
+vpp.o: vpp.c vpp.h types.h vpp_cset.h vmachine.h vdc.h
+ $(CC) $(CFLAGS) -c vpp.c -o vpp.o
+
+score.o: score.c score.h vmachine.h
+ $(CC) $(CFLAGS) -c score.c -o score.o
+
+o2em.res: o2em.rc o2em.ico
+ $(WINDRES) -O coff -o o2em.res -i o2em.rc
+
diff --git a/clean/src/Makefile.freebsd b/clean/src/Makefile.freebsd
new file mode 100755
index 0000000..c47f8aa
--- /dev/null
+++ b/clean/src/Makefile.freebsd
@@ -0,0 +1,68 @@
+CC = gcc
+
+CFLAGS = -O3 -Wall -fomit-frame-pointer -I${PREFIX}/include -DFREEBSD -DPREFIX=\"${PREFIX}\"
+LFLAGS = -s
+LIBALLEG = -L${PREFIX}/lib -lalleg -lalleg_unsharable
+
+
+all: o2em dis48
+
+clean:
+ rm -f audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o score.o dis48.o
+
+
+o2em: audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o score.o
+ $(CC) $(LFLAGS) audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o score.o -o o2em $(LIBALLEG)
+
+dis48: dis48.o table.o
+ $(CC) $(LFLAGS) dis48.o table.o -o dis48
+
+
+audio.o: audio.c audio.h cpu.h types.h config.h vmachine.h
+ $(CC) $(CFLAGS) -c audio.c -o audio.o
+
+cpu.o: cpu.c cpu.h types.h vmachine.h keyboard.h voice.h vdc.h vpp.h
+ $(CC) $(CFLAGS) -c cpu.c -o cpu.o
+
+cset.o: cset.c cset.h types.h
+ $(CC) $(CFLAGS) -c cset.c -o cset.o
+
+debug.o: debug.c debug.h cpu.h keyboard.h vmachine.h audio.h vdc.h table.h
+ $(CC) $(CFLAGS) -c debug.c -o debug.o
+
+dis48.o: dis48.c types.h table.h
+ $(CC) $(CFLAGS) -c dis48.c -o dis48.o
+
+keyboard.o: keyboard.c keyboard.h types.h cpu.h vmachine.h vdc.h audio.h voice.h vpp.h
+ $(CC) $(CFLAGS) -c keyboard.c -o keyboard.o
+
+main.o: main.c crc32.h audio.h vmachine.h config.h vdc.h cpu.h debug.h keyboard.h voice.h
+ $(CC) $(CFLAGS) -c main.c -o main.o
+
+table.o: table.c table.h cpu.h
+ $(CC) $(CFLAGS) -c table.c -o table.o
+
+vdc.o: vdc.c vdc.h types.h vmachine.h config.h keyboard.h cset.h timefunc.h cpu.h vpp.h
+ $(CC) $(CFLAGS) -c vdc.c -o vdc.o
+
+vmachine.o: vmachine.c vmachine.h audio.h types.h cpu.h keyboard.h config.h debug.h vdc.h vpp.h timefunc.h voice.h
+ $(CC) $(CFLAGS) -c vmachine.c -o vmachine.o
+
+timefunc.o: timefunc.c timefunc.h
+ $(CC) $(CFLAGS) -c timefunc.c -o timefunc.o
+
+voice.o: voice.c voice.h vmachine.h cpu.h
+ $(CC) $(CFLAGS) -c voice.c -o voice.o
+
+crc32.o: crc32.c crc32.h
+ $(CC) $(CFLAGS) -c crc32.c -o crc32.o
+
+vpp_cset.o: vpp_cset.c vpp_cset.h
+ $(CC) $(CFLAGS) -c vpp_cset.c -o vpp_cset.o
+
+vpp.o: vpp.c vpp.h types.h vpp_cset.h vmachine.h vdc.h
+ $(CC) $(CFLAGS) -c vpp.c -o vpp.o
+
+score.o: score.c score.h vmachine.h types.h
+ $(CC) $(CFLAGS) -c score.c -o score.o
+
diff --git a/clean/src/Makefile.mingw b/clean/src/Makefile.mingw
new file mode 100755
index 0000000..c05f50f
--- /dev/null
+++ b/clean/src/Makefile.mingw
@@ -0,0 +1,72 @@
+CC = gcc
+WINDRES = windres
+
+CFLAGS = -mno-cygwin -O3 -fomit-frame-pointer -Wall -I/usr/local/include
+LFLAGS = -mno-cygwin -s
+LIBALLEG = -L/usr/local/lib -lalleg
+
+
+all: o2em.exe dis48.exe
+
+clean:
+ del -f audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o dis48.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o score.o o2em.res o2em.exe dis48.exe
+
+
+o2em.exe: audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o o2em.res score.o
+ $(CC) $(LFLAGS) audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o score.o o2em.res -o o2em.exe $(LIBALLEG)
+
+dis48.exe: dis48.o table.o
+ $(CC) $(LFLAGS) dis48.o table.o -o dis48.exe
+
+
+audio.o: audio.c audio.h cpu.h types.h config.h vmachine.h
+ $(CC) $(CFLAGS) -c audio.c -o audio.o
+
+cpu.o: cpu.c cpu.h types.h vmachine.h keyboard.h voice.h vdc.h vpp.h
+ $(CC) $(CFLAGS) -c cpu.c -o cpu.o
+
+cset.o: cset.c cset.h types.h
+ $(CC) $(CFLAGS) -c cset.c -o cset.o
+
+debug.o: debug.c debug.h cpu.h keyboard.h vmachine.h audio.h vdc.h table.h
+ $(CC) $(CFLAGS) -c debug.c -o debug.o
+
+dis48.o: dis48.c types.h table.h
+ $(CC) $(CFLAGS) -c dis48.c -o dis48.o
+
+keyboard.o: keyboard.c keyboard.h types.h cpu.h vmachine.h vdc.h audio.h voice.h vpp.h score.h
+ $(CC) $(CFLAGS) -c keyboard.c -o keyboard.o
+
+main.o: main.c crc32.h audio.h vmachine.h config.h vdc.h cpu.h debug.h keyboard.h voice.h score.h
+ $(CC) $(CFLAGS) -c main.c -o main.o
+
+table.o: table.c table.h cpu.h
+ $(CC) $(CFLAGS) -c table.c -o table.o
+
+vdc.o: vdc.c vdc.h types.h vmachine.h config.h keyboard.h cset.h timefunc.h cpu.h vpp.h
+ $(CC) $(CFLAGS) -c vdc.c -o vdc.o
+
+vmachine.o: vmachine.c vmachine.h audio.h types.h cpu.h keyboard.h config.h debug.h vdc.h vpp.h timefunc.h voice.h
+ $(CC) $(CFLAGS) -c vmachine.c -o vmachine.o
+
+timefunc.o: timefunc.c timefunc.h
+ $(CC) $(CFLAGS) -c timefunc.c -o timefunc.o
+
+voice.o: voice.c voice.h vmachine.h cpu.h
+ $(CC) $(CFLAGS) -c voice.c -o voice.o
+
+crc32.o: crc32.c crc32.h
+ $(CC) $(CFLAGS) -c crc32.c -o crc32.o
+
+vpp_cset.o: vpp_cset.c vpp_cset.h
+ $(CC) $(CFLAGS) -c vpp_cset.c -o vpp_cset.o
+
+vpp.o: vpp.c vpp.h types.h vpp_cset.h vmachine.h vdc.h
+ $(CC) $(CFLAGS) -c vpp.c -o vpp.o
+
+score.o: score.c score.h vmachine.h
+ $(CC) $(CFLAGS) -c score.c -o score.o
+
+o2em.res: o2em.rc o2em.ico
+ $(WINDRES) -O coff -o o2em.res -i o2em.rc
+
diff --git a/clean/src/Makefile.win b/clean/src/Makefile.win
new file mode 100755
index 0000000..c0e5a23
--- /dev/null
+++ b/clean/src/Makefile.win
@@ -0,0 +1,35 @@
+# Project: Project1
+# Makefile created by Dev-C++ 4.9.9.1
+
+CPP = g++.exe
+CC = gcc.exe
+WINDRES = windres.exe
+RES = ../OBJ/file_private.res
+OBJ = ../OBJ/get_file.o ../OBJ/crc32.o $(RES)
+LINKOBJ = ../OBJ/get_file.o ../OBJ/crc32.o $(RES)
+LIBS = -L"C:/Dev-Cpp/lib" -L"C:/Dev-Cpp/lib"
+INCS = -I"C:/Dev-Cpp/include" -I"C:/Dev-Cpp/include"
+CXXINCS = -I"C:/Dev-Cpp/include/c++/3.3.1" -I"C:/Dev-Cpp/include/c++/3.3.1/mingw32" -I"C:/Dev-Cpp/include/c++/3.3.1/backward" -I"C:/Dev-Cpp/lib/gcc-lib/mingw32/3.3.1/include" -I"C:/Dev-Cpp/include" -I"C:/Dev-Cpp/include"
+BIN = file.exe
+CXXFLAGS = $(CXXINCS)
+CFLAGS = $(INCS)
+
+.PHONY: all all-before all-after clean clean-custom
+
+all: all-before file.exe all-after
+
+
+clean: clean-custom
+ rm -f $(OBJ) $(BIN)
+
+$(BIN): $(OBJ)
+ $(CPP) $(LINKOBJ) -o "file.exe" $(LIBS)
+
+../OBJ/get_file.o: get_file.cpp
+ $(CPP) -c get_file.cpp -o ../OBJ/get_file.o $(CXXFLAGS)
+
+../OBJ/crc32.o: crc32.c
+ $(CPP) -c crc32.c -o ../OBJ/crc32.o $(CXXFLAGS)
+
+../OBJ/file_private.res: file_private.rc
+ $(WINDRES) -i file_private.rc --input-format=rc -o ../OBJ/file_private.res -O coff --include-dir C:/Dev-Cpp/Projetos/o2em-win
diff --git a/clean/src/O2EM.ICO b/clean/src/O2EM.ICO
new file mode 100755
index 0000000..f867aac
Binary files /dev/null and b/clean/src/O2EM.ICO differ
diff --git a/clean/src/O2EM116_private.h b/clean/src/O2EM116_private.h
new file mode 100755
index 0000000..0f11498
--- /dev/null
+++ b/clean/src/O2EM116_private.h
@@ -0,0 +1,23 @@
+/* THIS FILE WILL BE OVERWRITTEN BY DEV-C++ */
+/* DO NOT EDIT ! */
+
+#ifndef O2EM116_PRIVATE_H
+#define O2EM116_PRIVATE_H
+
+/* VERSION DEFINITIONS */
+#define VER_STRING "0.1.1.1"
+#define VER_MAJOR 0
+#define VER_MINOR 1
+#define VER_RELEASE 1
+#define VER_BUILD 1
+#define COMPANY_NAME ""
+#define FILE_VERSION ""
+#define FILE_DESCRIPTION "Developed using the Dev-C++ IDE"
+#define INTERNAL_NAME ""
+#define LEGAL_COPYRIGHT ""
+#define LEGAL_TRADEMARKS ""
+#define ORIGINAL_FILENAME ""
+#define PRODUCT_NAME ""
+#define PRODUCT_VERSION ""
+
+#endif /*O2EM116_PRIVATE_H*/
diff --git a/clean/src/O2EM116_private.rc b/clean/src/O2EM116_private.rc
new file mode 100755
index 0000000..4ad7aff
--- /dev/null
+++ b/clean/src/O2EM116_private.rc
@@ -0,0 +1,5 @@
+/* THIS FILE WILL BE OVERWRITTEN BY DEV-C++ */
+/* DO NOT EDIT! */
+
+#include "o2em.rc"
+
diff --git a/clean/src/README b/clean/src/README
new file mode 100755
index 0000000..8811fe8
--- /dev/null
+++ b/clean/src/README
@@ -0,0 +1,341 @@
+
+
+ O2EM v1.18 (Jan/2007)
+
+ an Odyssey 2 & Videopac+ emulator
+
+ copyright 1996/1998 by Daniel Boris
+
+ Developed by Daniel Boris, Andre de la Rocha and Arlindo Oliveira
+
+ This package is released under the
+ Clarified Artistic License (see COPYING)
+
+ Project Homepage
+ http://o2em.sourceforge.net
+
+---------------------------------------------------------------------------
+
+
+O2EM is an open source Odyssey2 / Videopac console emulator, created by
+Daniel Boris in 1996. Since version 0.80 it has been developed by André de
+la Rocha and since version 1.16 it has been developed by Arlindo M. de Oliveira.
+
+This release includes the source code for O2EM v1.18 and binaries for
+Windows. The sources probably can also be compiled under other platforms
+that support the Allegro game library. The binary version for Linux/X11 and
+DOS continues available just until the version 1.16.
+
+With the Windows binary, the latest stable version of the Allegro DLL is also
+included. To use the Linux version you must get the Allegro library for Linux
+yourself and install it as root. The DOS version does not need additional
+files.
+
+O2EM is a command line based program, but there are several Windows frontends
+you can use. The "official" one is O2EM Launcher, created by Heitor
+Barcellos.
+
+In order to build O2EM from its sources, you need either the MingW or Cygwin
+packages on Windows, DJGPP on DOS and GCC on Linux. See the links below.
+
+The latest version of O2EM can be found at http://o2em.sourceforge.net If you
+want to send bug reports, or be part of the O2EM development, go to the O2EM
+project page at SourceForge : http://sourceforge.net/projects/o2em/
+
+
+
+Useful links:
+
+Dan Boris' home page: http://www.atarihq.com/danb/
+Allegro library: http://alleg.sourceforge.net/
+MingW C/C++ compiler: http://sourceforge.net/projects/mingw/
+Soeren Gust page : http://soeren.informationstheater.de/
+Odyssey2 Home: http://www.classicgaming.com/o2home/
+Odysseymania the brazilian webpage : http://odysseymania.classicgaming.com.br
+OdysseyBR Group: http://gamesource.groups.yahoo.com/group/OdysseyBR/
+Videopac Forum: http://www.videopac.org
+
+Acknowledgments:
+
+
+We wish to thank the following people:
+
+ Keita Iida (Keita/Pooka/Fygar)
+ for his enthusiasm, for the O2EM beta testing, and general encouragement.
+
+ Marco Kerstens (MarcoK)
+ for providing Videopac schematics, and general support.
+
+ Matthew Pritchard
+ for sending some official O2 programming documents.
+
+ Bo Krogsgaard (Therion23)
+ for putting the idea of doing the emulator into my head to start with.
+
+ Jason F. Gohlke
+ for providing valuable Voice tech info as well as the voice samples.
+
+ Soeren Gust : For sending his patches to O2EM and for technical
+ information about the console. Part of his technical document was
+ used to implement VP+ emulation.
+
+ René van den Enden : for providing information about several
+ unsupported games and other help.
+
+ Simon Scudder : for sending technical information about the O2
+ (including the datasheet of the VP+ gfx chipset), sampled sounds and
+ his nice O2 disassembler.
+
+ Heitor Barcellos : for creating the O2EM Launcher frontend.
+
+ Marcelo Ribeiro : for the icon used with the windows version of O2EM,
+ bug reports, and for information about O2 games.
+
+ Rafael : for compiling a big list of bugs present in O2EM v0.87.
+
+ Zimmerman : for sending his patch to add key customization, on which
+ v1.00 customization was based.
+
+ Arlindo de Oliveira : for sending patches to fix bugs in O2EM and for
+ his interest in keeping the O2 emulation alive.
+
+ The members of the OdysseyBR user group: for several bug reports, as
+ well for support in general.
+
+-----------------------------------------------------------------------------
+
+Building:
+
+o2em depends on Allegro, for Ubuntu / Debian, run:
+
+sudo apt-get install liballegro4-dev
+
+-----------------------------------------------------------------------------
+
+Quick Setup:
+
+To get O2EM up and running quickly follow these steps:
+
+1. Unzip the O2EM archive on your hard drive, that will create the necessary
+ standard directories: ROMS, BIOS and VOICE into the main directory O2EM118.
+2. Download the bios ROM O2ROM.BIN (or G7400.BIN, or C52.BIN, or JOPAC.BIN)
+ and put it into BIOS directory.
+3. Download one or more game ROMs, for example KCMUNCH.BIN for KC Munchkin and
+ put the ROM in ROMS directory.
+4. From the O2EM118 directory type: o2em KCMUNCH.BIN to start the game.If wants
+ to play KC Munchkin with BIOS VP+, type: o2em KCMUNCH.BIN -g7400
+
+---------------------------------------------------------------------------
+Setup:
+
+ Before you can run O2EM you need a copy of the Odyssey2 or Videopac bios
+ROM. For copyright reasons, this ROM image can not be included in this
+archive. This ROM image is stored inside the 8048 processor and can be read
+out with the appropriate equipment. The image should be 1024 bytes long and
+should be in the BIOS directory into the main directory O2EM118.
+
+ You will also need cartridge images, but again for copyright reasons
+these can not be provided. PLEASE DO NOT E-mail us asking for ROM images! All
+messages asking for ROM images will be promptly deleted.
+
+ If you wish to use Voice emulation for games like KC's Krazy Chase.
+Download the voice samples and unzip them into the VOICE directory
+into the main directory O2EM118. There are two sets of voice samples,
+mainsamp.zip which is the main voice samples and sidsamp.zip which are the
+samples used by the game Sid the Spellbinder. You only need the Sid samples
+if you want voice in that game.
+
+---------------------------------------------------------------------------
+
+
+Usage:
+
+
+o2em [options]
+
+ = file to load with extension
+
+
+options:
+
+-help Help display
+
+-wsize=n Window size used by the emulator (1=original, 2=double size, etc.)
+
+-fullscreen Use full screen mode
+
+-scanlines Enable scanlines use by the video emulation. Scanlines are a
+ feature that makes your display look like a TV screen.
+
+-nosound Turn off sound emulation
+
+-novoice Turn off voice emulation
+
+-svolume=n Set sound volume (0-100)
+
+-vvolume=n Set voice volume (0-100)
+
+-debug Start the emulator in debug mode
+
+-speed=n Relative speed (100 = original speed)
+
+-nolimit Turn off speed limiter
+
+-bios=file Set the file name and directory to find the console
+ bios. By default it looks for a file named o2rom.bin.
+ You can use a bios file from an Odyssey2, Videopac or
+ Videopac+ console. If you want to run VP+ games (in
+ VP+ mode) then you need a VP+ bios.
+
+-romdir=path Set the directory to find the game rom. By default it
+ looks for path named .../roms
+
+-biosdir=path Set the directory to find the console bios. By default it
+ looks for path named .../bios
+
+-o2rom Start the emulator with Odyssey 2 bios (default for most games).
+
+-c52 Start the emulator with french Odyssey 2 bios.
+
+-g7400 Start the emulator with VP+ bios (default for detected VP+ only games).
+
+-jopac Start the emulator with french VP+ bios.
+
+-euro This option enables the use of European timing / 50Hz mode.
+ This option is usually not needed as most of the games that
+ really require this mode will be auto-detected.
+
+-filter Enable the low-pass audio filter.
+
+-scshot=file Set the screen shot file name or template. The screen shot
+ will be saved when you press the F8 key in the emulator.
+ The extension of the file you give will set the file type.
+ supported file types are bmp, pcx and tga. You can also give
+ a template to save several files, using the @ character.
+ Using an option like -scshot=dump@.bmp will save files with
+ names like dump00.bmp, dump01.bmp, etc. The pictures will
+ have a resolution of (320x240)*wsize.
+
+-exrom Enable the use of an alternative ROM mapping for 4Kb games, to
+ support some games that use a special 3kb program rom/1kb data
+ ROM mode. The only known that use it are Four in 1 Row and
+ Musician and both are detected by their CRC and set correctly.
+ So this option is to be used only with games that are currently
+ unknown to O2EM. Do not enable it as default, as it will make
+ all the 4kb games that do not use this special mode crash.
+
+-s0=QUIT,PAUSE,DEBUG,RESET,SCREENCAP,SAVE,LOAD,INJECT_HIGH
+ These option defines which keys are used for some of the system
+ keys, if you use this option, you have to enter all 8 keys, to
+ override the original keys (ESC,F1,F4,F5,F8,F2,F3,F6)
+
+-s1=mode/keys Define stick 1 mode/keys
+-s2=mode/keys Define stick 2 mode/keys
+
+ These options define how the console joysticks are emulated.
+ You can use a joystick connected to your computer or use
+ the keyboard. You can specify a mode number (compatible with
+ previous versions of O2EM) to disable the joystick emulation,
+ to select an actual joystick or to set a default keyboard
+ emulation mode :
+ 0=Disable,
+ 1=Default Right keys (arrows keys and right shift)
+ 2=Default Left keys (W,S,A,D,SPACE)
+ 3=Joystick
+ Example: -s1=1 -s2=3
+
+ You can also specify a list of 5 keyboard codes that will
+ be used to emulate the joystick, separated by comas
+ (without spaces), using this order : UP,DOWN,LEFT,RIGHT,FIRE.
+ The following codes are accepted (not case sensitive):
+ A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 0_PAD,1_PAD,2_PAD,3_PAD,4_PAD,5_PAD,6_PAD,7_PAD,8_PAD,9_PAD,
+ TILDE, MINUS, EQUALS, BACKSPACE, TAB, OPENBRACE, CLOSEBRACE,
+ ENTER, COLON, QUOTE, BACKSLASH, BACKSLASH2, COMMA, STOP,
+ SLASH, SPACE, INSERT, DEL, HOME, END, PGUP, PGDN, LEFT,
+ RIGHT, UP, DOWN, SLASH_PAD, ASTERISK, MINUS_PAD, PLUS_PAD,
+ DEL_PAD, ENTER_PAD, PRTSCR, PAUSE, ABNT_C1, YEN, KANA, AT,
+ CIRCUMFLEX, COLON2, KANJI, LSHIFT, RSHIFT, LCONTROL,
+ RCONTROL, ALT, ALTGR, LWIN, RWIN, MENU, SCRLOCK, NUMLOCK
+ Example: -s1=y,h,g,j,lcontrol -s2=8_PAD,5_PAD,4_PAD,6_PAD,RCONTROL
+
+-scoreadr=address where the high-score is saved for specific rom
+-scoretype=type how the high-score is saved for specific rom
+-score=highscore default highscore on launch ("inject" with F6)
+-scorefile=file file where the highscore is saved on exit
+
+-savefile=file filename for save/load state
+
+
+
+
+----------------------------------------------------------------------------
+
+Default configuration file:
+
+O2EM now can use a configuration file to set the default options, so you can
+specify your preferred options in this file, instead of typing it every time
+you execute the emulator. The command line options override the default
+settings in the file. This file must be called o2em_def.cfg and be in the
+same directory of O2EM118. This configuration file is a text file where you can
+put the same options you would use when calling O2EM by the command line, but
+each option must be in a different line and you should not precede it with
+the - character. You can also put comment lines in the file, starting the
+line with the # character. Example configuration file:
+
+ # My config
+ wsize=3
+ Euro
+ scanlines
+ filter
+ g7400
+ s1=8_pad,5_pad,4_pad,6_pad,rcontrol
+
+
+You disable any option set in this file when you call O2EM in the command
+line, passing the =0 parameter to the option. For this example configuration,
+you could disable the filter option set in the file putting -filter=0 when
+you call O2EM.
+
+
+----------------------------------------------------------------------------
+
+Controls:
+
+ Arrow keys + L = Default joystick 1 emulation
+
+ W,D,S,A + Space = Default joystick 2 emulation
+
+ ESC/F12 = Leave the emulator
+
+ F1 = Pause/Information
+
+ F2 = Save State-File
+
+ F3 = Load State-File
+
+ F4 = Enter debugger
+
+ F5 = Reset emulator (same as pressing the reset on the O2 keyboard)
+
+ F6 = Inject Highscore
+
+ F8 = Make a screen shot
+
+ Caps Lock = Enables/Disables the O2 keyboard input of the keys used by
+ joystick emulation
+
+----------------------------------------------------------------------------
+
+Debugger:
+
+The emulator comes with a built in debugger that was used for development.
+The debugger is not very polished and fairly incomplete but it can be useful
+for single stepping through programs and watching their behavior.
+
+H = display help
+
+----------------------------------------------------------------------------
+
+
diff --git a/clean/src/audio.c b/clean/src/audio.c
new file mode 100755
index 0000000..d1f2c27
--- /dev/null
+++ b/clean/src/audio.c
@@ -0,0 +1,188 @@
+
+/*
+ * O2EM Free Odyssey2 / Videopac+ Emulator
+ *
+ * Created by Daniel Boris (c) 1997,1998
+ *
+ * Developed by Andre de la Rocha
+ * Arlindo M. de Oliveira
+ *
+ * http://o2em.sourceforge.net
+ *
+ *
+ *
+ * O2 audio emulation
+ */
+
+
+#include
+#include
+#include
+#include "cpu.h"
+#include "types.h"
+#include "config.h"
+#include "vmachine.h"
+#include "audio.h"
+#include "allegro.h"
+
+#define SAMPLE_RATE 44100
+#define PERIOD1 11
+#define PERIOD2 44
+
+#define SOUND_BUFFER_LEN 1056
+
+#define AUD_CTRL 0xAA
+#define AUD_D0 0xA7
+#define AUD_D1 0xA8
+#define AUD_D2 0xA9
+
+
+int sound_IRQ;
+static AUDIOSTREAM *stream=NULL;
+FILE *sndlog=NULL;
+
+static double flt_a=0.0, flt_b=0.0;
+static unsigned char flt_prv = 0;
+
+
+static void filter(unsigned char *buf, unsigned long len);
+
+
+void audio_process(unsigned char *buffer){
+ unsigned long aud_data;
+ int volume, re_circ, noise, enabled, intena, period, pnt, cnt, rndbit, pos;
+
+ aud_data = (VDCwrite[AUD_D2] | (VDCwrite[AUD_D1] << 8) | (VDCwrite[AUD_D0] << 16));
+
+ intena = VDCwrite[0xA0] & 0x04;
+
+ pnt = cnt = 0;
+
+ noise = VDCwrite[AUD_CTRL] & 0x10;
+ enabled = VDCwrite[AUD_CTRL] & 0x80;
+ rndbit = (enabled && noise) ? (rand()%2) : 0;
+
+ while (pnt < SOUND_BUFFER_LEN) {
+ pos = (tweakedaudio) ? (pnt/3) : (MAXLINES-1);
+ volume = AudioVector[pos] & 0x0F;
+ enabled = AudioVector[pos] & 0x80;
+ period = (AudioVector[pos] & 0x20) ? PERIOD1 : PERIOD2;
+ re_circ = AudioVector[pos] & 0x40;
+
+ buffer[pnt++] = (enabled) ? ((aud_data & 0x01)^rndbit) * (0x10 * volume) : 0;
+ cnt++;
+
+ if (cnt >= period) {
+ cnt=0;
+ aud_data = (re_circ) ? ((aud_data >> 1) | ((aud_data & 1) << 23)) : (aud_data >> 1);
+ rndbit = (enabled && noise) ? (rand()%2) : 0;
+
+ if (enabled && intena && (!sound_IRQ)) {
+ sound_IRQ = 1;
+ ext_IRQ();
+ }
+ }
+ }
+
+ if (app_data.filter) filter(buffer, SOUND_BUFFER_LEN);
+}
+
+
+void update_audio(void) {
+ unsigned char *p;
+ if (app_data.sound_en) {
+ p = (unsigned char *)get_audio_stream_buffer(stream);
+ if (p) {
+ audio_process(p);
+ if (sndlog) fwrite(p,1,SOUND_BUFFER_LEN,sndlog);
+ free_audio_stream_buffer(stream);
+ }
+ }
+}
+
+
+void init_audio(void) {
+ int i;
+#ifdef OPENEMU
+ sound_IRQ=0;
+ if ((app_data.sound_en) || (app_data.voice)) {
+ printf("Initializing sound system...\n");
+ i = install_sound(DIGI_AUTODETECT, MIDI_NONE, NULL);
+ if (i != 0) {
+ printf(" ERROR: could not initialize sound card\n %s\n",allegro_error);
+ printf(" Sound system disabled\n");
+ app_data.sound_en = 0;
+ app_data.voice = 0;
+ }
+ else {
+ if (digi_driver->name && (strlen(digi_driver->name)>0)){
+ printf(" Sound system initialized ok\n");
+ printf(" Sound driver [%s] detected\n",digi_driver->name);
+ set_volume(-1,-1);
+ init_sound_stream();
+ } else {
+ printf(" ERROR: could not initialize sound card\n");
+ printf(" Sound system disabled\n");
+ app_data.sound_en = 0;
+ app_data.voice = 0;
+ }
+ }
+ }
+#endif
+ sndlog = NULL;
+}
+
+
+void init_sound_stream(void){
+ int vol;
+ if (app_data.sound_en){
+ if (app_data.filter)
+ vol = (255*app_data.svolume)/100;
+ else
+ vol = (255*app_data.svolume)/200;
+ stream = play_audio_stream(SOUND_BUFFER_LEN,8,0,SAMPLE_RATE,vol,128);
+ if (!stream) {
+ printf("Error creating audio stream!\n");
+ app_data.sound_en=0;
+ }
+ flt_a = flt_b = 0.0;
+ flt_prv = 0;
+ }
+}
+
+
+void mute_audio(void){
+ if (app_data.sound_en && stream){
+ stop_audio_stream(stream);
+ stream=NULL;
+ }
+}
+
+
+void close_audio(void) {
+ if (app_data.sound_en && stream) {
+ stop_audio_stream(stream);
+ }
+ if (sndlog) fclose(sndlog);
+ app_data.sound_en=0;
+}
+
+
+static void filter(unsigned char *buffer, unsigned long len){
+ static unsigned char buf[SOUND_BUFFER_LEN];
+ int t;
+ unsigned long i;
+ if (len>SOUND_BUFFER_LEN) return;
+ memcpy(buf,buffer,len);
+ for (i=0; i255.0)||(flt_a<-255.0)) flt_a=0.0;
+ buffer[i] = (unsigned char)((flt_a+255.0)/2.0);
+ }
+ flt_prv = buf[len-1];
+}
+
+
diff --git a/clean/src/audio.h b/clean/src/audio.h
new file mode 100755
index 0000000..47d971c
--- /dev/null
+++ b/clean/src/audio.h
@@ -0,0 +1,17 @@
+#ifndef __AUDIO_H
+#define __AUDIO_H
+
+void update_audio(void);
+void init_audio(void);
+void close_audio(void);
+void init_sound_stream(void);
+void mute_audio(void);
+
+
+extern int sound_IRQ;
+extern FILE *sndlog;
+
+
+#endif
+
+
diff --git a/clean/src/config.h b/clean/src/config.h
new file mode 100755
index 0000000..715a373
--- /dev/null
+++ b/clean/src/config.h
@@ -0,0 +1,14 @@
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#define O2EM_VERSION "1.18"
+#define RELEASE_DATE "(Jan/2007)"
+
+#define ROM_O2 1
+#define ROM_G7400 2
+#define ROM_C52 3
+#define ROM_JOPAC 4
+#define ROM_UNKNOWN 99
+
+#endif
+
diff --git a/clean/src/cpu.c b/clean/src/cpu.c
new file mode 100755
index 0000000..9d36f46
--- /dev/null
+++ b/clean/src/cpu.c
@@ -0,0 +1,1572 @@
+
+/*
+ * O2EM Free Odyssey2 / Videopac+ Emulator
+ *
+ * Created by Daniel Boris (c) 1997,1998
+ *
+ ** Developed by Andre de la Rocha
+ * Arlindo M. de Oliveira
+ *
+ * http://o2em.sourceforge.net
+ *
+ *
+ *
+ * 8048 microcontroller emulation
+ */
+
+
+#include
+#include "types.h"
+#include "vmachine.h"
+#include "keyboard.h"
+#include "voice.h"
+#include "vdc.h"
+#include "vpp.h"
+#include "cpu.h"
+
+#define push(d) {intRAM[sp++] = (d); if (sp > 23) sp = 8;}
+#define pull() (sp--, (sp < 8)?(sp=23):0, intRAM[sp])
+#define make_psw() {psw = (cy << 7) | ac | f0 | bs | 0x08; psw = psw | ((sp - 8) >> 1);}
+#define illegal(o) {}
+#define undef(i) {printf("** unimplemented instruction %x, %x**\n",i,pc);}
+#define ROM(adr) (rom[(adr) & 0xfff])
+
+
+void init_cpu(void){
+ pc=0;
+ sp=8;
+ bs=0;
+ p1=p2=0xFF;
+ ac=cy=f0=0;
+ A11=A11ff=0;
+ timer_on=0;
+ count_on=0;
+ reg_pnt=0;
+ tirq_en=xirq_en=irq_ex=xirq_pend=tirq_pend=0;
+}
+
+
+void ext_IRQ(void){
+ int_clk = 5; /* length of pulse on /INT */
+ if (xirq_en && !irq_ex) {
+ irq_ex=1;
+ xirq_pend=0;
+ clk+=2;
+ make_psw();
+ push(pc & 0xFF);
+ push(((pc & 0xF00) >> 8) | (psw & 0xF0));
+ pc = 0x03;
+ A11ff=A11;
+ A11=0;
+ }
+ if (pendirq && (!xirq_en)) xirq_pend=1;
+}
+
+
+void tim_IRQ(void){
+ if (tirq_en && !irq_ex) {
+ irq_ex=2;
+ tirq_pend=0;
+ clk+=2;
+ make_psw();
+ push(pc & 0xFF);
+ push(((pc & 0xF00) >> 8) | (psw & 0xF0));
+ pc = 0x07;
+ A11ff=A11;
+ A11=0;
+ }
+ if (pendirq && (!tirq_en)) tirq_pend=1;
+}
+
+
+void make_psw_debug(void){
+ make_psw();
+}
+
+
+
+void cpu_exec(void) {
+ Byte op;
+ ADDRESS adr;
+ Byte dat;
+ int temp;
+
+ for (;;) {
+
+ clk=0;
+
+ lastpc=pc;
+ op=ROM(pc++);
+ switch (op) {
+ case 0x00: /* NOP */
+ clk++;
+ break;
+ case 0x01: /* ILL */
+ illegal(op);
+ clk++;
+ break;
+ case 0x02: /* OUTL BUS,A */
+ clk+=2;
+ undef(0x02);
+ break;
+ case 0x03: /* ADD A,#data */
+ clk+=2;
+ cy=ac=0;
+ dat=ROM(pc++);
+ if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40;
+ temp=acc+dat;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+ case 0x04: /* JMP */
+ pc=ROM(pc) | A11;
+ clk+=2;
+ break;
+ case 0x05: /* EN I */
+ xirq_en=1;
+ clk++;
+ break;
+ case 0x06: /* ILL */
+ clk++;
+ illegal(op);
+ break;
+ case 0x07: /* DEC A */
+ acc--;
+ clk++;
+ break;
+ case 0x08: /* INS A,BUS*/
+ clk+=2;
+ acc=in_bus();
+ break;
+ case 0x09: /* IN A,Pp */
+ acc=p1;
+ clk+=2;
+ break;
+ case 0x0A: /* IN A,Pp */
+ acc=read_P2();
+ clk+=2;
+ break;
+ case 0x0B: /* ILL */
+ clk++;
+ illegal(op);
+ break;
+ case 0x0C: /* MOVD A,P4 */
+ clk+=2;
+ acc=read_PB(0);
+ break;
+ case 0x0D: /* MOVD A,P5 */
+ clk+=2;
+ acc=read_PB(1);
+ break;
+ case 0x0E: /* MOVD A,P6 */
+ clk+=2;
+ acc=read_PB(2);
+ break;
+ case 0x0F: /* MOVD A,P7 */
+ clk+=2;
+ acc=read_PB(3);
+ break;
+ case 0x10: /* INC @Ri */
+ intRAM[intRAM[reg_pnt] & 0x3F]++;
+ clk++;
+ break;
+ case 0x11: /* INC @Ri */
+ intRAM[intRAM[reg_pnt+1] & 0x3F]++;
+ clk++;
+ break;
+ case 0x12: /* JBb address */
+ clk+=2;
+ dat = ROM(pc);
+ if (acc & 0x01)
+ pc=(pc & 0xF00) | dat;
+ else
+ pc++;
+ break;
+ case 0x13: /* ADDC A,#data */
+ clk+=2;
+ dat=ROM(pc++);
+ ac=0;
+ if (((acc & 0x0f) + (dat & 0x0f) + cy) > 0x0f) ac=0x40;
+ temp=acc+dat+cy;
+ cy=0;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+
+ case 0x14: /* CALL */
+ make_psw();
+ adr = ROM(pc) | A11;
+ pc++;
+ clk+=2;
+ push(pc & 0xFF);
+ push(((pc & 0xF00) >> 8) | (psw & 0xF0));
+ pc = adr;
+ break;
+ case 0x15: /* DIS I */
+ xirq_en=0;
+ clk++;
+ break;
+ case 0x16: /* JTF */
+ clk+=2;
+ dat = ROM(pc);
+ if (t_flag)
+ pc=(pc & 0xF00) | dat;
+ else
+ pc++;
+ t_flag=0;
+ break;
+ case 0x17: /* INC A */
+ acc++;
+ clk++;
+ break;
+ case 0x18: /* INC Rr */
+ intRAM[reg_pnt]++;
+ clk++;
+ break;
+ case 0x19: /* INC Rr */
+ intRAM[reg_pnt+1]++;
+ clk++;
+ break;
+ case 0x1A: /* INC Rr */
+ intRAM[reg_pnt+2]++;
+ clk++;
+ break;
+ case 0x1B: /* INC Rr */
+ intRAM[reg_pnt+3]++;
+ clk++;
+ break;
+ case 0x1C: /* INC Rr */
+ intRAM[reg_pnt+4]++;
+ clk++;
+ break;
+ case 0x1D: /* INC Rr */
+ intRAM[reg_pnt+5]++;
+ clk++;
+ break;
+ case 0x1E: /* INC Rr */
+ intRAM[reg_pnt+6]++;
+ clk++;
+ break;
+ case 0x1F: /* INC Rr */
+ intRAM[reg_pnt+7]++;
+ clk++;
+ break;
+ case 0x20: /* XCH A,@Ri */
+ clk++;
+ dat=acc;
+ acc=intRAM[intRAM[reg_pnt] & 0x3F];
+ intRAM[intRAM[reg_pnt] & 0x3F] = dat;
+ break;
+ case 0x21: /* XCH A,@Ri */
+ clk++;
+ dat=acc;
+ acc=intRAM[intRAM[reg_pnt+1] & 0x3F];
+ intRAM[intRAM[reg_pnt+1] & 0x3F] = dat;
+ break;
+ case 0x22: /* ILL */
+ clk++;
+ illegal(op);
+ break;
+ case 0x23: /* MOV a,#data */
+ clk+=2;
+ acc = ROM(pc++);
+ break;
+
+ case 0x24: /* JMP */
+ pc=ROM(pc) | 0x100 | A11;
+ clk+=2;
+ break;
+ case 0x25: /* EN TCNTI */
+ tirq_en=1;
+ clk++;
+ break;
+ case 0x26: /* JNT0 */
+ clk+=2;
+ dat = ROM(pc);
+ if (!get_voice_status())
+ pc=(pc & 0xF00) | dat;
+ else
+ pc++;
+ break;
+ case 0x27: /* CLR A */
+ clk++;
+ acc=0;
+ break;
+ case 0x28: /* XCH A,Rr */
+ dat=acc;
+ acc=intRAM[reg_pnt];
+ intRAM[reg_pnt]=dat;
+ clk++;
+ break;
+ case 0x29: /* XCH A,Rr */
+ dat=acc;
+ acc=intRAM[reg_pnt+1];
+ intRAM[reg_pnt+1]=dat;
+ clk++;
+ break;
+ case 0x2A: /* XCH A,Rr */
+ dat=acc;
+ acc=intRAM[reg_pnt+2];
+ intRAM[reg_pnt+2]=dat;
+ clk++;
+ break;
+ case 0x2B: /* XCH A,Rr */
+ dat=acc;
+ acc=intRAM[reg_pnt+3];
+ intRAM[reg_pnt+3]=dat;
+ clk++;
+ break;
+ case 0x2C: /* XCH A,Rr */
+ dat=acc;
+ acc=intRAM[reg_pnt+4];
+ intRAM[reg_pnt+4]=dat;
+ clk++;
+ break;
+ case 0x2D: /* XCH A,Rr */
+ dat=acc;
+ acc=intRAM[reg_pnt+5];
+ intRAM[reg_pnt+5]=dat;
+ clk++;
+ break;
+ case 0x2E: /* XCH A,Rr */
+ dat=acc;
+ acc=intRAM[reg_pnt+6];
+ intRAM[reg_pnt+6]=dat;
+ clk++;
+ break;
+ case 0x2F: /* XCH A,Rr */
+ dat=acc;
+ acc=intRAM[reg_pnt+7];
+ intRAM[reg_pnt+7]=dat;
+ clk++;
+ break;
+ case 0x30: /* XCHD A,@Ri */
+ clk++;
+ adr=intRAM[reg_pnt] & 0x3F;
+ dat=acc & 0x0F;
+ acc=acc & 0xF0;
+ acc=acc | (intRAM[adr] & 0x0F);
+ intRAM[adr] &= 0xF0;
+ intRAM[adr] |= dat;
+ break;
+ case 0x31: /* XCHD A,@Ri */
+ clk++;
+ adr=intRAM[reg_pnt+1] & 0x3F;
+ dat=acc & 0x0F;
+ acc=acc & 0xF0;
+ acc=acc | (intRAM[adr] & 0x0F);
+ intRAM[adr] &= 0xF0;
+ intRAM[adr] |= dat;
+ break;
+ case 0x32: /* JBb address */
+ clk+=2;
+ dat=ROM(pc);
+ if (acc & 0x02)
+ pc=(pc & 0xF00) | dat;
+ else
+ pc++;
+ break;
+ case 0x33: /* ILL */
+ clk++;
+ illegal(op);
+ break;
+ case 0x34: /* CALL */
+ make_psw();
+ adr = ROM(pc) | 0x100 | A11;
+ pc++;
+ clk+=2;
+ push(pc & 0xFF);
+ push(((pc & 0xF00) >> 8) | (psw & 0xF0));
+ pc = adr;
+ break;
+ case 0x35: /* DIS TCNTI */
+ tirq_en=0;
+ tirq_pend=0;
+ clk++;
+ break;
+ case 0x36: /* JT0 */
+ clk+=2;
+ dat=ROM(pc);
+ if (get_voice_status())
+ pc=(pc & 0xF00) | dat;
+ else
+ pc++;
+ break;
+ case 0x37: /* CPL A */
+ acc = acc ^ 0xFF;
+ clk++;
+ break;
+ case 0x38: /* ILL */
+ clk++;
+ illegal(op);
+ break;
+ case 0x39: /* OUTL P1,A */
+ clk+=2;
+ write_p1(acc);
+ break;
+ case 0x3A: /* OUTL P2,A */
+ clk+=2;
+ p2=acc;
+ break;
+ case 0x3B: /* ILL */
+ clk++;
+ illegal(op);
+ break;
+ case 0x3C: /* MOVD P4,A */
+ clk+=2;
+ write_PB(0,acc);
+ break;
+ case 0x3D: /* MOVD P5,A */
+ clk+=2;
+ write_PB(1,acc);
+ break;
+ case 0x3E: /* MOVD P6,A */
+ clk+=2;
+ write_PB(2,acc);
+ break;
+ case 0x3F: /* MOVD P7,A */
+ clk+=2;
+ write_PB(3,acc);
+ break;
+ case 0x40: /* ORL A,@Ri */
+ clk++;
+ acc = acc | intRAM[intRAM[reg_pnt] & 0x3F];
+ break;
+ case 0x41: /* ORL A,@Ri */
+ clk++;
+ acc = acc | intRAM[intRAM[reg_pnt+1] & 0x3F];
+ break;
+ case 0x42: /* MOV A,T */
+ clk++;
+ acc = itimer;
+ break;
+ case 0x43: /* ORL A,#data */
+ clk+=2;
+ acc = acc | ROM(pc++);
+ break;
+ case 0x44: /* JMP */
+ pc=ROM(pc) | 0x200 | A11;
+ clk+=2;
+ break;
+ case 0x45: /* STRT CNT */
+ /* printf("START: %d=%d\n",master_clk/22,itimer); */
+ count_on=1;
+ clk++;
+ break;
+ case 0x46: /* JNT1 */
+ clk+=2;
+ dat = ROM(pc);
+ if (!read_t1())
+ pc=(pc & 0xF00) | dat;
+ else
+ pc++;
+ break;
+ case 0x47: /* SWAP A */
+ clk++;
+ dat=(acc & 0xF0) >> 4;
+ acc = acc << 4;
+ acc = acc | dat;
+ break;
+ case 0x48: /* ORL A,Rr */
+ clk++;
+ acc = acc | intRAM[reg_pnt];
+ break;
+ case 0x49: /* ORL A,Rr */
+ clk++;
+ acc = acc | intRAM[reg_pnt+1];
+ break;
+ case 0x4A: /* ORL A,Rr */
+ clk++;
+ acc = acc | intRAM[reg_pnt+2];
+ break;
+ case 0x4B: /* ORL A,Rr */
+ clk++;
+ acc = acc | intRAM[reg_pnt+3];
+ break;
+ case 0x4C: /* ORL A,Rr */
+ clk++;
+ acc = acc | intRAM[reg_pnt+4];
+ break;
+ case 0x4D: /* ORL A,Rr */
+ clk++;
+ acc = acc | intRAM[reg_pnt+5];
+ break;
+ case 0x4E: /* ORL A,Rr */
+ clk++;
+ acc = acc | intRAM[reg_pnt+6];
+ break;
+ case 0x4F: /* ORL A,Rr */
+ clk++;
+ acc = acc | intRAM[reg_pnt+7];
+ break;
+
+ case 0x50: /* ANL A,@Ri */
+ acc = acc & intRAM[intRAM[reg_pnt] & 0x3F];
+ clk++;
+ break;
+ case 0x51: /* ANL A,@Ri */
+ acc = acc & intRAM[intRAM[reg_pnt+1] & 0x3F];
+ clk++;
+ break;
+ case 0x52: /* JBb address */
+ clk+=2;
+ dat=ROM(pc);
+ if (acc & 0x04)
+ pc=(pc & 0xF00) | dat;
+ else
+ pc++;
+ break;
+ case 0x53: /* ANL A,#data */
+ clk+=2;
+ acc = acc & ROM(pc++);
+ break;
+ case 0x54: /* CALL */
+ make_psw();
+ adr = ROM(pc) | 0x200 | A11;
+ pc++;
+ clk+=2;
+ push(pc & 0xFF);
+ push(((pc & 0xF00) >> 8) | (psw & 0xF0));
+ pc = adr;
+ break;
+ case 0x55: /* STRT T */
+ timer_on=1;
+ clk++;
+ break;
+ case 0x56: /* JT1 */
+ clk+=2;
+ dat = ROM(pc);
+ if (read_t1())
+ pc=(pc & 0xF00) | dat;
+ else
+ pc++;
+ break;
+ case 0x57: /* DA A */
+ clk++;
+ if (((acc & 0x0F) > 0x09) || ac) {
+ if (acc>0xf9) cy=1;
+ acc += 6;
+ }
+ dat = (acc & 0xF0) >> 4;
+ if ((dat > 9) || cy) {
+ dat+=6;
+ cy=1;
+ }
+ acc = (acc & 0x0F) | (dat << 4);
+ break;
+ case 0x58: /* ANL A,Rr */
+ clk++;
+ acc = acc & intRAM[reg_pnt];
+ break;
+ case 0x59: /* ANL A,Rr */
+ clk++;
+ acc = acc & intRAM[reg_pnt+1];
+ break;
+ case 0x5A: /* ANL A,Rr */
+ clk++;
+ acc = acc & intRAM[reg_pnt+2];
+ break;
+ case 0x5B: /* ANL A,Rr */
+ clk++;
+ acc = acc & intRAM[reg_pnt+3];
+ break;
+ case 0x5C: /* ANL A,Rr */
+ clk++;
+ acc = acc & intRAM[reg_pnt+4];
+ break;
+ case 0x5D: /* ANL A,Rr */
+ clk++;
+ acc = acc & intRAM[reg_pnt+5];
+ break;
+ case 0x5E: /* ANL A,Rr */
+ clk++;
+ acc = acc & intRAM[reg_pnt+6];
+ break;
+ case 0x5F: /* ANL A,Rr */
+ clk++;
+ acc = acc & intRAM[reg_pnt+7];
+ break;
+
+ case 0x60: /* ADD A,@Ri */
+ clk++;
+ cy=ac=0;
+ dat=intRAM[intRAM[reg_pnt] & 0x3F];
+ if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40;
+ temp=acc+dat;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+ case 0x61: /* ADD A,@Ri */
+ clk++;
+ cy=ac=0;
+ dat=intRAM[intRAM[reg_pnt+1] & 0x3F];
+ if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40;
+ temp=acc+dat;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+ case 0x62: /* MOV T,A */
+ clk++;
+ itimer=acc;
+ break;
+ case 0x63: /* ILL */
+ clk++;
+ illegal(op);
+ break;
+ case 0x64: /* JMP */
+ pc=ROM(pc) | 0x300 | A11;
+ clk+=2;
+ break;
+ case 0x65: /* STOP TCNT */
+ clk++;
+ /* printf("STOP %d\n",master_clk/22); */
+ count_on=timer_on=0;
+ break;
+ case 0x66: /* ILL */
+ clk++;
+ illegal(op);
+ break;
+ case 0x67: /* RRC A */
+ dat=cy;
+ cy=acc & 0x01;
+ acc = acc >> 1;
+ if (dat)
+ acc = acc | 0x80;
+ else
+ acc = acc & 0x7F;
+ clk++;
+ break;
+ case 0x68: /* ADD A,Rr */
+ clk++;
+ cy=ac=0;
+ dat=intRAM[reg_pnt];
+ if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40;
+ temp=acc+dat;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+ case 0x69: /* ADD A,Rr */
+ clk++;
+ cy=ac=0;
+ dat=intRAM[reg_pnt+1];
+ if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40;
+ temp=acc+dat;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+ case 0x6A: /* ADD A,Rr */
+ clk++;
+ cy=ac=0;
+ dat=intRAM[reg_pnt+2];
+ if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40;
+ temp=acc+dat;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+ case 0x6B: /* ADD A,Rr */
+ clk++;
+ cy=ac=0;
+ dat=intRAM[reg_pnt+3];
+ if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40;
+ temp=acc+dat;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+ case 0x6C: /* ADD A,Rr */
+ clk++;
+ cy=ac=0;
+ dat=intRAM[reg_pnt+4];
+ if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40;
+ temp=acc+dat;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+ case 0x6D: /* ADD A,Rr */
+ clk++;
+ cy=ac=0;
+ dat=intRAM[reg_pnt+5];
+ if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40;
+ temp=acc+dat;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+ case 0x6E: /* ADD A,Rr */
+ clk++;
+ cy=ac=0;
+ dat=intRAM[reg_pnt+6];
+ if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40;
+ temp=acc+dat;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+ case 0x6F: /* ADD A,Rr */
+ clk++;
+ cy=ac=0;
+ dat=intRAM[reg_pnt+7];
+ if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40;
+ temp=acc+dat;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+ case 0x70: /* ADDC A,@Ri */
+ clk++;
+ ac=0;
+ dat=intRAM[intRAM[reg_pnt] & 0x3F];
+ if (((acc & 0x0f) + (dat & 0x0f) + cy) > 0x0f) ac=0x40;
+ temp=acc+dat+cy;
+ cy=0;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+ case 0x71: /* ADDC A,@Ri */
+ clk++;
+ ac=0;
+ dat=intRAM[intRAM[reg_pnt+1] & 0x3F];
+ if (((acc & 0x0f) + (dat & 0x0f) + cy) > 0x0f) ac=0x40;
+ temp=acc+dat+cy;
+ cy=0;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+
+ case 0x72: /* JBb address */
+ clk+=2;
+ dat=ROM(pc);
+ if (acc & 0x08)
+ pc=(pc & 0xF00) | dat;
+ else
+ pc++;
+ break;
+ case 0x73: /* ILL */
+ clk++;
+ illegal(op);
+ break;
+ case 0x74: /* CALL */
+ make_psw();
+ adr = ROM(pc) | 0x300 | A11;
+ pc++;
+ clk+=2;
+ push(pc & 0xFF);
+ push(((pc & 0xF00) >> 8) | (psw & 0xF0));
+ pc = adr;
+ break;
+ case 0x75: /* EN CLK */
+ clk++;
+ undef(op);
+ break;
+ case 0x76: /* JF1 address */
+ clk+=2;
+ dat=ROM(pc);
+ if (f1)
+ pc=(pc & 0xF00) | dat;
+ else
+ pc++;
+ break;
+ case 0x77: /* RR A */
+ clk++;
+ dat=acc & 0x01;
+ acc = acc >> 1;
+ if (dat)
+ acc = acc | 0x80;
+ else
+ acc = acc & 0x7f;
+ break;
+
+ case 0x78: /* ADDC A,Rr */
+ clk++;
+ ac=0;
+ dat=intRAM[reg_pnt];
+ if (((acc & 0x0f) + (dat & 0x0f)+cy) > 0x0f) ac=0x40;
+ temp=acc+dat+cy;
+ cy=0;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+ case 0x79: /* ADDC A,Rr */
+ clk++;
+ ac=0;
+ dat=intRAM[reg_pnt+1];
+ if (((acc & 0x0f) + (dat & 0x0f)+cy) > 0x0f) ac=0x40;
+ temp=acc+dat+cy;
+ cy=0;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+ case 0x7A: /* ADDC A,Rr */
+ clk++;
+ ac=0;
+ dat=intRAM[reg_pnt+2];
+ if (((acc & 0x0f) + (dat & 0x0f)+cy) > 0x0f) ac=0x40;
+ temp=acc+dat+cy;
+ cy=0;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+ case 0x7B: /* ADDC A,Rr */
+ clk++;
+ ac=0;
+ dat=intRAM[reg_pnt+3];
+ if (((acc & 0x0f) + (dat & 0x0f)+cy) > 0x0f) ac=0x40;
+ temp=acc+dat+cy;
+ cy=0;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+ case 0x7C: /* ADDC A,Rr */
+ clk++;
+ ac=0;
+ dat=intRAM[reg_pnt+4];
+ if (((acc & 0x0f) + (dat & 0x0f)+cy) > 0x0f) ac=0x40;
+ temp=acc+dat+cy;
+ cy=0;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+ case 0x7D: /* ADDC A,Rr */
+ clk++;
+ ac=0;
+ dat=intRAM[reg_pnt+5];
+ if (((acc & 0x0f) + (dat & 0x0f)+cy) > 0x0f) ac=0x40;
+ temp=acc+dat+cy;
+ cy=0;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+ case 0x7E: /* ADDC A,Rr */
+ clk++;
+ ac=0;
+ dat=intRAM[reg_pnt+6];
+ if (((acc & 0x0f) + (dat & 0x0f)+cy) > 0x0f) ac=0x40;
+ temp=acc+dat+cy;
+ cy=0;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+ case 0x7F: /* ADDC A,Rr */
+ clk++;
+ ac=0;
+ dat=intRAM[reg_pnt+7];
+ if (((acc & 0x0f) + (dat & 0x0f)+cy) > 0x0f) ac=0x40;
+ temp=acc+dat+cy;
+ cy=0;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+
+ case 0x80: /* MOVX A,@Ri */
+ acc=ext_read(intRAM[reg_pnt]);
+ clk+=2;
+ break;
+ case 0x81: /* MOVX A,@Ri */
+ acc=ext_read(intRAM[reg_pnt+1]);
+ clk+=2;
+ break;
+ case 0x82: /* ILL */
+ clk++;
+ illegal(op);
+ break;
+ case 0x83: /* RET */
+ clk+=2;
+ pc = ((pull() & 0x0F) << 8);
+ pc = pc | pull();
+ break;
+ case 0x84: /* JMP */
+ pc=ROM(pc) | 0x400 | A11;
+ clk+=2;
+ break;
+ case 0x85: /* CLR F0 */
+ clk++;
+ f0=0;
+ break;
+ case 0x86: /* JNI address */
+ clk+=2;
+ dat=ROM(pc);
+ if (int_clk > 0)
+ pc=(pc & 0xF00) | dat;
+ else
+ pc++;
+ break;
+ case 0x87: /* ILL */
+ illegal(op);
+ clk++;
+ break;
+ case 0x88: /* BUS,#data */
+ clk+=2;
+ undef(op);
+ break;
+ case 0x89: /* ORL Pp,#data */
+ write_p1(p1 | ROM(pc++));
+ clk+=2;
+ break;
+ case 0x8A: /* ORL Pp,#data */
+ p2 = p2 | ROM(pc++);
+ clk+=2;
+ break;
+ case 0x8B: /* ILL */
+ illegal(op);
+ clk++;
+ break;
+ case 0x8C: /* ORLD P4,A */
+ write_PB(0,read_PB(0)|acc);
+ clk+=2;
+ break;
+ case 0x8D: /* ORLD P5,A */
+ write_PB(1,read_PB(1)|acc);
+ clk+=2;
+ break;
+ case 0x8E: /* ORLD P6,A */
+ write_PB(2,read_PB(2)|acc);
+ clk+=2;
+ break;
+ case 0x8F: /* ORLD P7,A */
+ write_PB(3,read_PB(3)|acc);
+ clk+=2;
+ break;
+ case 0x90: /* MOVX @Ri,A */
+ ext_write(acc,intRAM[reg_pnt]);
+ clk+=2;
+ break;
+ case 0x91: /* MOVX @Ri,A */
+ ext_write(acc,intRAM[reg_pnt+1]);
+ clk+=2;
+ break;
+ case 0x92: /* JBb address */
+ clk+=2;
+ dat=ROM(pc);
+ if (acc & 0x10)
+ pc=(pc & 0xF00) | dat;
+ else
+ pc++;
+ break;
+ case 0x93: /* RETR*/
+ /* printf("RETR %d\n",master_clk/22); */
+ clk+=2;
+ dat=pull();
+ pc = (dat & 0x0F) << 8;
+ cy = (dat & 0x80) >> 7;
+ ac = dat & 0x40;
+ f0 = dat & 0x20;
+ bs = dat & 0x10;
+ if (bs)
+ reg_pnt=24;
+ else
+ reg_pnt=0;
+ pc = pc | pull();
+ irq_ex=0;
+ A11=A11ff;
+ break;
+ case 0x94: /* CALL */
+ make_psw();
+ adr = ROM(pc) | 0x400 | A11;
+ pc++;
+ clk+=2;
+ push(pc & 0xFF);
+ push(((pc & 0xF00) >> 8) | (psw & 0xF0));
+ pc = adr;
+ break;
+ case 0x95: /* CPL F0 */
+ f0 = f0 ^ 0x20;
+ clk++;
+ break;
+ case 0x96: /* JNZ address */
+ clk+=2;
+ dat=ROM(pc);
+ if (acc != 0)
+ pc=(pc & 0xF00) | dat;
+ else
+ pc++;
+ break;
+ case 0x97: /* CLR C */
+ cy=0;
+ clk++;
+ break;
+ case 0x98: /* ANL BUS,#data */
+ clk+=2;
+ undef(op);
+ break;
+ case 0x99: /* ANL Pp,#data */
+ write_p1(p1 & ROM(pc++));
+ clk+=2;
+ break;
+ case 0x9A: /* ANL Pp,#data */
+ p2 = p2 & ROM(pc++);
+ clk+=2;
+ break;
+ case 0x9B: /* ILL */
+ illegal(op);
+ clk++;
+ break;
+ case 0x9C: /* ANLD P4,A */
+ write_PB(0,read_PB(0)&acc);
+ clk+=2;
+ break;
+ case 0x9D: /* ANLD P5,A */
+ write_PB(1,read_PB(1)&acc);
+ clk+=2;
+ break;
+ case 0x9E: /* ANLD P6,A */
+ write_PB(2,read_PB(2)&acc);
+ clk+=2;
+ break;
+ case 0x9F: /* ANLD P7,A */
+ write_PB(3,read_PB(3)&acc);
+ clk+=2;
+ break;
+ case 0xA0: /* MOV @Ri,A */
+ intRAM[intRAM[reg_pnt] & 0x3F]=acc;
+ clk++;
+ break;
+ case 0xA1: /* MOV @Ri,A */
+ intRAM[intRAM[reg_pnt+1] & 0x3F]=acc;
+ clk++;
+ break;
+ case 0xA2: /* ILL */
+ clk++;
+ illegal(op);
+ break;
+ case 0xA3: /* MOVP A,@A */
+ acc=ROM((pc & 0xF00) | acc);
+ clk+=2;
+ break;
+ case 0xA4: /* JMP */
+ pc=ROM(pc) | 0x500 | A11;
+ clk+=2;
+ break;
+ case 0xA5: /* CLR F1 */
+ clk++;
+ f1=0;
+ break;
+ case 0xA6: /* ILL */
+ illegal(op);
+ clk++;
+ break;
+ case 0xA7: /* CPL C */
+ cy = cy ^ 0x01;
+ clk++;
+ break;
+ case 0xA8: /* MOV Rr,A */
+ intRAM[reg_pnt] = acc;
+ clk++;
+ break;
+ case 0xA9: /* MOV Rr,A */
+ intRAM[reg_pnt+1] = acc;
+ clk++;
+ break;
+ case 0xAA: /* MOV Rr,A */
+ intRAM[reg_pnt+2] = acc;
+ clk++;
+ break;
+ case 0xAB: /* MOV Rr,A */
+ intRAM[reg_pnt+3] = acc;
+ clk++;
+ break;
+ case 0xAC: /* MOV Rr,A */
+ intRAM[reg_pnt+4] = acc;
+ clk++;
+ break;
+ case 0xAD: /* MOV Rr,A */
+ intRAM[reg_pnt+5] = acc;
+ clk++;
+ break;
+ case 0xAE: /* MOV Rr,A */
+ intRAM[reg_pnt+6] = acc;
+ clk++;
+ break;
+ case 0xAF: /* MOV Rr,A */
+ intRAM[reg_pnt+7] = acc;
+ clk++;
+ break;
+ case 0xB0: /* MOV @Ri,#data */
+ intRAM[intRAM[reg_pnt] & 0x3F]=ROM(pc++);
+ clk+=2;
+ break;
+ case 0xB1: /* MOV @Ri,#data */
+ intRAM[intRAM[reg_pnt+1] & 0x3F]=ROM(pc++);
+ clk+=2;
+ break;
+ case 0xB2: /* JBb address */
+ clk+=2;
+ dat=ROM(pc);
+ if (acc & 0x20)
+ pc=(pc & 0xF00) | dat;
+ else
+ pc++;
+ break;
+ case 0xB3: /* JMPP @A */
+ adr = (pc & 0xF00) | acc;
+ pc=(pc & 0xF00) | ROM(adr);
+ clk+=2;
+ break;
+ case 0xB4: /* CALL */
+ make_psw();
+ adr = ROM(pc) | 0x500 | A11;
+ pc++;
+ clk+=2;
+ push(pc & 0xFF);
+ push(((pc & 0xF00) >> 8) | (psw & 0xF0));
+ pc = adr;
+ break;
+ case 0xB5: /* CPL F1 */
+ f1 = f1 ^ 0x01;
+ clk++;
+ break;
+ case 0xB6: /* JF0 address */
+ clk+=2;
+ dat=ROM(pc);
+ if (f0)
+ pc=(pc & 0xF00) | dat;
+ else
+ pc++;
+ break;
+ case 0xB7: /* ILL */
+ clk++;
+ illegal(op);
+ break;
+ case 0xB8: /* MOV Rr,#data */
+ intRAM[reg_pnt]=ROM(pc++);
+ clk+=2;
+ break;
+ case 0xB9: /* MOV Rr,#data */
+ intRAM[reg_pnt+1]=ROM(pc++);
+ clk+=2;
+ break;
+ case 0xBA: /* MOV Rr,#data */
+ intRAM[reg_pnt+2]=ROM(pc++);
+ clk+=2;
+ break;
+ case 0xBB: /* MOV Rr,#data */
+ intRAM[reg_pnt+3]=ROM(pc++);
+ clk+=2;
+ break;
+ case 0xBC: /* MOV Rr,#data */
+ intRAM[reg_pnt+4]=ROM(pc++);
+ clk+=2;
+ break;
+ case 0xBD: /* MOV Rr,#data */
+ intRAM[reg_pnt+5]=ROM(pc++);
+ clk+=2;
+ break;
+ case 0xBE: /* MOV Rr,#data */
+ intRAM[reg_pnt+6]=ROM(pc++);
+ clk+=2;
+ break;
+ case 0xBF: /* MOV Rr,#data */
+ intRAM[reg_pnt+7]=ROM(pc++);
+ clk+=2;
+ break;
+ case 0xC0: /* ILL */
+ illegal(op);
+ clk++;
+ break;
+ case 0xC1: /* ILL */
+ illegal(op);
+ clk++;
+ break;
+ case 0xC2: /* ILL */
+ illegal(op);
+ clk++;
+ break;
+ case 0xC3: /* ILL */
+ illegal(op);
+ clk++;
+ break;
+ case 0xC4: /* JMP */
+ pc=ROM(pc) | 0x600 | A11;
+ clk+=2;
+ break;
+ case 0xC5: /* SEL RB0 */
+ bs=reg_pnt=0;
+ clk++;
+ break;
+ case 0xC6: /* JZ address */
+ clk+=2;
+ dat=ROM(pc);
+ if (acc == 0)
+ pc=(pc & 0xF00) | dat;
+ else
+ pc++;
+ break;
+ case 0xC7: /* MOV A,PSW */
+ clk++;
+ make_psw();
+ acc=psw;
+ break;
+ case 0xC8: /* DEC Rr */
+ intRAM[reg_pnt]--;
+ clk++;
+ break;
+ case 0xC9: /* DEC Rr */
+ intRAM[reg_pnt+1]--;
+ clk++;
+ break;
+ case 0xCA: /* DEC Rr */
+ intRAM[reg_pnt+2]--;
+ clk++;
+ break;
+ case 0xCB: /* DEC Rr */
+ intRAM[reg_pnt+3]--;
+ clk++;
+ break;
+ case 0xCC: /* DEC Rr */
+ intRAM[reg_pnt+4]--;
+ clk++;
+ break;
+ case 0xCD: /* DEC Rr */
+ intRAM[reg_pnt+5]--;
+ clk++;
+ break;
+ case 0xCE: /* DEC Rr */
+ intRAM[reg_pnt+6]--;
+ clk++;
+ break;
+ case 0xCF: /* DEC Rr */
+ intRAM[reg_pnt+7]--;
+ clk++;
+ break;
+ case 0xD0: /* XRL A,@Ri */
+ acc = acc ^ intRAM[intRAM[reg_pnt] & 0x3F];
+ clk++;
+ break;
+ case 0xD1: /* XRL A,@Ri */
+ acc = acc ^ intRAM[intRAM[reg_pnt+1] & 0x3F];
+ clk++;
+ break;
+ case 0xD2: /* JBb address */
+ clk+=2;
+ dat = ROM(pc);
+ if (acc & 0x40)
+ pc=(pc & 0xF00) | dat;
+ else
+ pc++;
+ break;
+ case 0xD3: /* XRL A,#data */
+ clk+=2;
+ acc = acc ^ ROM(pc++);
+ break;
+ case 0xD4: /* CALL */
+ make_psw();
+ adr = ROM(pc) | 0x600 | A11;
+ pc++;
+ clk+=2;
+ push(pc & 0xFF);
+ push(((pc & 0xF00) >> 8) | (psw & 0xF0));
+ pc = adr;
+ break;
+ case 0xD5: /* SEL RB1 */
+ bs=0x10;
+ reg_pnt=24;
+ clk++;
+ break;
+ case 0xD6: /* ILL */
+ illegal(op);
+ clk++;
+ break;
+ case 0xD7: /* MOV PSW,A */
+ psw=acc;
+ clk++;
+ cy = (psw & 0x80) >> 7;
+ ac = psw & 0x40;
+ f0 = psw & 0x20;
+ bs = psw & 0x10;
+ if (bs)
+ reg_pnt = 24;
+ else
+ reg_pnt = 0;
+ sp = (psw & 0x07) << 1;
+ sp+=8;
+ break;
+ case 0xD8: /* XRL A,Rr */
+ acc = acc ^ intRAM[reg_pnt];
+ clk++;
+ break;
+ case 0xD9: /* XRL A,Rr */
+ acc = acc ^ intRAM[reg_pnt+1];
+ clk++;
+ break;
+ case 0xDA: /* XRL A,Rr */
+ acc = acc ^ intRAM[reg_pnt+2];
+ clk++;
+ break;
+ case 0xDB: /* XRL A,Rr */
+ acc = acc ^ intRAM[reg_pnt+3];
+ clk++;
+ break;
+ case 0xDC: /* XRL A,Rr */
+ acc = acc ^ intRAM[reg_pnt+4];
+ clk++;
+ break;
+ case 0xDD: /* XRL A,Rr */
+ acc = acc ^ intRAM[reg_pnt+5];
+ clk++;
+ break;
+ case 0xDE: /* XRL A,Rr */
+ acc = acc ^ intRAM[reg_pnt+6];
+ clk++;
+ break;
+ case 0xDF: /* XRL A,Rr */
+ acc = acc ^ intRAM[reg_pnt+7];
+ clk++;
+ break;
+ case 0xE0: /* ILL */
+ clk++;
+ illegal(op);
+ break;
+ case 0xE1: /* ILL */
+ clk++;
+ illegal(op);
+ break;
+ case 0xE2: /* ILL */
+ clk++;
+ illegal(op);
+ break;
+ case 0xE3: /* MOVP3 A,@A */
+
+ adr = 0x300 | acc;
+ acc=ROM(adr);
+ clk+=2;
+ break;
+ case 0xE4: /* JMP */
+ pc=ROM(pc) | 0x700 | A11;
+ clk+=2;
+ break;
+ case 0xE5: /* SEL MB0 */
+ A11=0;
+ A11ff = 0;
+ clk++;
+ break;
+ case 0xE6: /* JNC address */
+ clk+=2;
+ dat=ROM(pc);
+ if (!cy)
+ pc=(pc & 0xF00) | dat;
+ else
+ pc++;
+ break;
+ case 0xE7: /* RL A */
+ clk++;
+ dat=acc & 0x80;
+ acc = acc << 1;
+ if (dat)
+ acc = acc | 0x01;
+ else
+ acc = acc & 0xFE;
+ break;
+ case 0xE8: /* DJNZ Rr,address */
+ clk+=2;
+ intRAM[reg_pnt]--;
+ dat=ROM(pc);
+ if (intRAM[reg_pnt] != 0) {
+ pc = pc & 0xF00;
+ pc = pc | dat;
+ } else pc++;
+ break;
+ case 0xE9: /* DJNZ Rr,address */
+ clk+=2;
+ intRAM[reg_pnt+1]--;
+ dat=ROM(pc);
+ if (intRAM[reg_pnt+1] != 0) {
+ pc = pc & 0xF00;
+ pc = pc | dat;
+ } else pc++;
+ break;
+ case 0xEA: /* DJNZ Rr,address */
+ clk+=2;
+ intRAM[reg_pnt+2]--;
+ dat=ROM(pc);
+ if (intRAM[reg_pnt+2] != 0) {
+ pc = pc & 0xF00;
+ pc = pc | dat;
+ } else pc++;
+ break;
+ case 0xEB: /* DJNZ Rr,address */
+ clk+=2;
+ intRAM[reg_pnt+3]--;
+ dat=ROM(pc);
+ if (intRAM[reg_pnt+3] != 0) {
+ pc = pc & 0xF00;
+ pc = pc | dat;
+ } else pc++;
+ break;
+ case 0xEC: /* DJNZ Rr,address */
+ clk+=2;
+ intRAM[reg_pnt+4]--;
+ dat=ROM(pc);
+ if (intRAM[reg_pnt+4] != 0) {
+ pc = pc & 0xF00;
+ pc = pc | dat;
+ } else pc++;
+ break;
+ case 0xED: /* DJNZ Rr,address */
+ clk+=2;
+ intRAM[reg_pnt+5]--;
+ dat=ROM(pc);
+ if (intRAM[reg_pnt+5] != 0) {
+ pc = pc & 0xF00;
+ pc = pc | dat;
+ } else pc++;
+ break;
+ case 0xEE: /* DJNZ Rr,address */
+ clk+=2;
+ intRAM[reg_pnt+6]--;
+ dat=ROM(pc);
+ if (intRAM[reg_pnt+6] != 0) {
+ pc = pc & 0xF00;
+ pc = pc | dat;
+ } else pc++;
+ break;
+ case 0xEF: /* DJNZ Rr,address */
+ clk+=2;
+ intRAM[reg_pnt+7]--;
+ dat=ROM(pc);
+ if (intRAM[reg_pnt+7] != 0) {
+ pc = pc & 0xF00;
+ pc = pc | dat;
+ } else pc++;
+ break;
+ case 0xF0: /* MOV A,@Ri */
+ clk++;
+ acc=intRAM[intRAM[reg_pnt] & 0x3F];
+ break;
+ case 0xF1: /* MOV A,@Ri */
+ clk++;
+ acc=intRAM[intRAM[reg_pnt + 1] & 0x3F];
+ break;
+ case 0xF2: /* JBb address */
+ clk+=2;
+ dat=ROM(pc);
+ if (acc & 0x80)
+ pc=(pc & 0xF00) | dat;
+ else
+ pc++;
+ break;
+ case 0xF3: /* ILL */
+ illegal(op);
+ clk++;
+ break;
+ case 0xF4: /* CALL */
+ clk+=2;
+ make_psw();
+ adr = ROM(pc) | 0x700 | A11;
+ pc++;
+ push(pc & 0xFF);
+ push(((pc & 0xF00) >> 8) | (psw & 0xF0));
+ pc = adr;
+ break;
+ case 0xF5: /* SEL MB1 */
+ if (irq_ex) {
+ A11ff = 0x800;
+ }
+ else
+ {
+ A11=0x800;
+ A11ff = 0x800;
+ }
+ clk++;
+ break;
+ case 0xF6: /* JC address */
+ clk+=2;
+ dat=ROM(pc);
+ if (cy)
+ pc=(pc & 0xF00) | dat;
+ else
+ pc++;
+ break;
+ case 0xF7: /* RLC A */
+ dat=cy;
+ cy=(acc & 0x80) >> 7;
+ acc = acc << 1;
+ if (dat)
+ acc = acc | 0x01;
+ else
+ acc = acc & 0xFE;
+ clk++;
+ break;
+ case 0xF8: /* MOV A,Rr */
+ clk++;
+ acc = intRAM[reg_pnt];
+ break;
+ case 0xF9: /* MOV A,Rr */
+ clk++;
+ acc = intRAM[reg_pnt + 1];
+ break;
+ case 0xFA: /* MOV A,Rr */
+ clk++;
+ acc = intRAM[reg_pnt + 2];
+ break;
+ case 0xFB: /* MOV A,Rr */
+ clk++;
+ acc = intRAM[reg_pnt + 3];
+ break;
+ case 0xFC: /* MOV A,Rr */
+ clk++;
+ acc = intRAM[reg_pnt + 4];
+ break;
+ case 0xFD: /* MOV A,Rr */
+ clk++;
+ acc = intRAM[reg_pnt + 5];
+ break;
+ case 0xFE: /* MOV A,Rr */
+ clk++;
+ acc = intRAM[reg_pnt + 6];
+ break;
+ case 0xFF: /* MOV A,Rr */
+ clk++;
+ acc = intRAM[reg_pnt + 7];
+ break;
+ }
+
+
+ master_clk+=clk;
+ h_clk+=clk;
+ clk_counter+=clk;
+
+ /* flag for JNI */
+ if (int_clk > clk)
+ int_clk -= clk;
+ else
+ int_clk = 0;
+
+ /* pending IRQs */
+ if (xirq_pend) ext_IRQ();
+ if (tirq_pend) tim_IRQ();
+
+ if (h_clk > LINECNT-1) {
+ h_clk-=LINECNT;
+ if (enahirq && (VDCwrite[0xA0] & 0x01)) ext_IRQ();
+ if (count_on && mstate == 0) {
+ itimer++;
+ if (itimer == 0) {
+ t_flag=1;
+ tim_IRQ();
+ draw_region();
+ }
+ }
+ }
+
+ if (timer_on) {
+ master_count+=clk;
+ if (master_count > 31) {
+ master_count-=31;
+ itimer++;
+ if (itimer == 0) {
+ t_flag=1;
+ tim_IRQ();
+ }
+ }
+ }
+
+ if ((mstate==0) && (master_clk > VBLCLK)) handle_vbl();
+
+ if ((mstate==1) && (master_clk > evblclk)) {
+ handle_evbl();
+ if (app_data.crc == 0xA7344D1F) handle_evbll(); /* Atlantis */
+ break;
+ }
+
+ if (app_data.debug) break;
+
+ if (pc==app_data.breakpoint) break;
+ }
+
+}
+
diff --git a/clean/src/cpu.h b/clean/src/cpu.h
new file mode 100755
index 0000000..042fee2
--- /dev/null
+++ b/clean/src/cpu.h
@@ -0,0 +1,65 @@
+#ifndef CPU_H
+#define CPU_H
+
+#include "types.h"
+
+extern Byte acc; /* Accumulator */
+extern ADDRESS pc; /* Program counter */
+extern long clk; /* clock */
+
+extern Byte itimer; /* Internal timer */
+extern Byte reg_pnt; /* pointer to register bank */
+extern Byte timer_on; /* 0=timer off/1=timer on */
+extern Byte count_on; /* 0=count off/1=count on */
+
+extern Byte t_flag; /* Timer flag */
+
+extern Byte psw; /* Processor status word */
+extern Byte sp; /* Stack pointer (part of psw) */
+
+extern Byte p1; /* I/O port 1 */
+extern Byte p2; /* I/O port 2 */
+
+extern Byte xirq_pend;
+extern Byte tirq_pend;
+
+void init_cpu(void);
+void cpu_exec(void);
+void ext_IRQ(void);
+void tim_IRQ(void);
+void make_psw_debug(void);
+
+Byte acc; /* Accumulator */
+ADDRESS pc; /* Program counter */
+long clk; /* clock */
+
+Byte itimer; /* Internal timer */
+Byte reg_pnt; /* pointer to register bank */
+Byte timer_on; /* 0=timer off/1=timer on */
+Byte count_on; /* 0=count off/1=count on */
+Byte psw; /* Processor status word */
+Byte sp; /* Stack pointer (part of psw) */
+
+Byte p1; /* I/O port 1 */
+Byte p2; /* I/O port 2 */
+Byte xirq_pend; /* external IRQ pending */
+Byte tirq_pend; /* timer IRQ pending */
+Byte t_flag; /* Timer flag */
+
+ADDRESS lastpc;
+ADDRESS A11; /* PC bit 11 */
+ADDRESS A11ff;
+Byte bs; /* Register Bank (part of psw) */
+Byte f0; /* Flag Bit (part of psw) */
+Byte f1; /* Flag Bit 1 */
+Byte ac; /* Aux Carry (part of psw) */
+Byte cy; /* Carry flag (part of psw) */
+Byte xirq_en; /* external IRQ's enabled */
+Byte tirq_en; /* Timer IRQ enabled */
+Byte irq_ex; /* IRQ executing */
+
+int master_count;
+
+
+#endif /* CPU_H */
+
diff --git a/clean/src/crc32.c b/clean/src/crc32.c
new file mode 100755
index 0000000..40e2c99
--- /dev/null
+++ b/clean/src/crc32.c
@@ -0,0 +1,116 @@
+
+/*
+ * O2EM Free Odyssey2 / Videopac+ Emulator
+ *
+ * Created by Daniel Boris (c) 1997,1998
+ *
+ * Developed by Andre de la Rocha
+ * Arlindo M. de Oliveira
+ *
+ * http://o2em.sourceforge.net
+ *
+ *
+ *
+ * CRC32 functions used to identify files
+ */
+
+// Some stuff ported from here:
+// http://www.opensource.apple.com/source/xnu/xnu-1504.7.4/bsd/libkern/crc32.c
+
+#include
+#include
+#include
+#include "crc32.h"
+
+
+static uint32_t crc32tab[256] = {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
+ 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+ 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+ 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+ 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+ 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
+ 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
+ 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+ 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+ 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
+ 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
+ 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+ 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
+ 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+ 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+ 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
+ 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
+ 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+ 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+ 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
+ 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+ 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
+ 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
+ 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+ 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+ 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
+ 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+ 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+ 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
+ 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+ 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+ 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
+ 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
+ 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+ 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
+};
+
+uint32_t crc32_buf(const void *buf, size_t size)
+{
+ uint32_t crc = ~0;
+ const uint8_t *p = buf;
+
+ while (size--) crc = (crc >> 8) ^ crc32tab[(crc ^ (*p++)) & 0xFF];
+ return ~crc;
+}
+
+uint32_t crc32_file(const char *filename)
+{
+ uint32_t crc = ~0;
+ FILE *f;
+ int c;
+ f = fopen(filename,"rb");
+ if (f) {
+ while ((c=fgetc(f)) != EOF) {
+ crc = (crc >> 8) ^ crc32tab[(crc ^ c) & 0xFF];
+ }
+ fclose(f);
+ }
+ return ~crc;
+}
+
diff --git a/clean/src/crc32.h b/clean/src/crc32.h
new file mode 100755
index 0000000..5e66e75
--- /dev/null
+++ b/clean/src/crc32.h
@@ -0,0 +1,8 @@
+#include
+#ifndef __CRC32_H
+#define __CRC32_H
+
+uint32_t crc32_buf(const void *buf, size_t len);
+uint32_t crc32_file(const char *filename);
+
+#endif
diff --git a/clean/src/cset.c b/clean/src/cset.c
new file mode 100755
index 0000000..7d6b6e9
--- /dev/null
+++ b/clean/src/cset.c
@@ -0,0 +1,86 @@
+/*
+ * O2EM Free Odyssey2 / Videopac+ Emulator
+ *
+ * Created by Daniel Boris (c) 1997,1998
+ *
+ * Developed by Andre de la Rocha
+ * Arlindo M. de Oliveira
+ *
+ * http://o2em.sourceforge.net
+ *
+ *
+ *
+ * O2 character table
+ */
+
+
+#include "types.h"
+#include "cset.h"
+
+
+Byte cset[512]= {
+0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,
+0x18,0x38,0x18,0x18,0x18,0x18,0x3C,0x00,
+0x3C,0x66,0x0C,0x18,0x30,0x60,0x7E,0x00,
+0x7C,0xC6,0x06,0x3C,0x06,0xC6,0x7C,0x00,
+0xCC,0xCC,0xCC,0xFE,0x0C,0x0C,0x0C,0x00,
+0xFE,0xC0,0xC0,0x7C,0x06,0xC6,0x7C,0x00,
+0x7C,0xC6,0xC0,0xFC,0xC6,0xC6,0x7C,0x00,
+0xFE,0x06,0x0C,0x18,0x30,0x60,0xC0,0x00,
+0x7C,0xC6,0xC6,0x7C,0xC6,0xC6,0x7C,0x00,
+0x7C,0xC6,0xC6,0x7E,0x06,0xC6,0x7C,0x00,
+0x00,0x18,0x18,0x00,0x18,0x18,0x00,0x00,
+0x18,0x7E,0x58,0x7E,0x1A,0x7E,0x18,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x3C,0x66,0x0C,0x18,0x18,0x00,0x18,0x00,
+0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xFE,0x00,
+0xFC,0xC6,0xC6,0xFC,0xC0,0xC0,0xC0,0x00,
+0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,
+0xC6,0xC6,0xC6,0xD6,0xFE,0xEE,0xC6,0x00,
+0xFE,0xC0,0xC0,0xF8,0xC0,0xC0,0xFE,0x00,
+0xFC,0xC6,0xC6,0xFC,0xD8,0xCC,0xC6,0x00,
+0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x00,
+0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,
+0x3C,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,
+0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,
+0x7C,0xC6,0xC6,0xC6,0xDE,0xCC,0x76,0x00,
+0x7C,0xC6,0xC0,0x7C,0x06,0xC6,0x7C,0x00,
+0xFC,0xC6,0xC6,0xC6,0xC6,0xC6,0xFC,0x00,
+0xFE,0xC0,0xC0,0xF8,0xC0,0xC0,0xC0,0x00,
+0x7C,0xC6,0xC0,0xC0,0xCE,0xC6,0x7E,0x00,
+0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,
+0x06,0x06,0x06,0x06,0x06,0xC6,0x7C,0x00,
+0xC6,0xCC,0xD8,0xF0,0xD8,0xCC,0xC6,0x00,
+0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0x00,
+0x7E,0x06,0x0C,0x18,0x30,0x60,0x7E,0x00,
+0xC6,0xC6,0x6C,0x38,0x6C,0xC6,0xC6,0x00,
+0x7C,0xC6,0xC0,0xC0,0xC0,0xC6,0x7C,0x00,
+0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x00,
+0xFC,0xC6,0xC6,0xFC,0xC6,0xC6,0xFC,0x00,
+0xC6,0xEE,0xFE,0xD6,0xC6,0xC6,0xC6,0x00,
+0x00,0x00,0x00,0x00,0x00,0x38,0x38,0x00,
+0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,
+0x00,0x66,0x3C,0x18,0x3C,0x66,0x00,0x00,
+0x00,0x18,0x00,0x7E,0x00,0x18,0x00,0x00,
+0x00,0x00,0x7C,0x00,0x7C,0x00,0x00,0x00,
+0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x00,
+0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0x00,
+0x03,0x06,0x0C,0x18,0x30,0x60,0xC0,0x00,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,
+0xCE,0xDB,0xDB,0xDB,0xDB,0xDB,0xCE,0x00,
+0x00,0x00,0x3C,0x7E,0x7E,0x7E,0x3C,0x00,
+0x1C,0x1C,0x18,0x1E,0x18,0x18,0x1C,0x00,
+0x1C,0x1C,0x18,0x1E,0x18,0x34,0x26,0x00,
+0x38,0x38,0x18,0x78,0x18,0x2C,0x64,0x00,
+0x38,0x38,0x18,0x78,0x18,0x18,0x38,0x00,
+0x00,0x18,0x0C,0xFE,0x0C,0x18,0x00,0x00,
+0x18,0x3C,0x7E,0xFF,0xFF,0x18,0x18,0x00,
+0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,0x00,
+0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF,0x00,
+0x38,0x38,0x12,0xFE,0xB8,0x28,0x6C,0x00,
+0xC0,0x60,0x30,0x18,0x0C,0x06,0x03,0x00,
+0x00,0x00,0x0C,0x08,0x08,0xFF,0x7E,0x00,
+0x00,0x03,0x63,0xFF,0xFF,0x18,0x08,0x00,
+0x00,0x00,0x00,0x10,0x38,0xFF,0x7E,0x00,
+0x00,0x00,0x00,0x06,0x6E,0xFF,0x7E,0x00};
+
diff --git a/clean/src/cset.h b/clean/src/cset.h
new file mode 100755
index 0000000..6c61d51
--- /dev/null
+++ b/clean/src/cset.h
@@ -0,0 +1,6 @@
+#ifndef __CSET_H
+#define __CSET_H
+
+extern Byte cset[512];
+
+#endif
diff --git a/clean/src/debug.c b/clean/src/debug.c
new file mode 100755
index 0000000..ec3bf69
--- /dev/null
+++ b/clean/src/debug.c
@@ -0,0 +1,1052 @@
+/*
+ * O2EM Free Odyssey2 / Videopac+ Emulator
+ *
+ * Created by Daniel Boris (c) 1997,1998
+ *
+ * Developed by Andre de la Rocha
+ * Arlindo M. de Oliveira
+ *
+ * http://o2em.sourceforge.net
+ *
+ *
+ *
+ * O2EM built-in debugger
+ */
+
+#include
+#include
+#include "cpu.h"
+#include "keyboard.h"
+#include "vmachine.h"
+#include "audio.h"
+#include "vdc.h"
+#include "table.h"
+#include "debug.h"
+#include "allegro.h"
+#include "vpp.h"
+#include "score.h"
+
+#if defined(ALLEGRO_WINDOWS)
+#include "winalleg.h"
+#include
+#define KBHIT _kbhit
+#elif defined(ALLEGRO_DOS)
+#include
+#define KBHIT kbhit
+#else
+#define KBHIT() 0
+#endif
+
+static int assemble(char *opcode, int p);
+static int disasm(ADDRESS p);
+static int spriteprint(ADDRESS p);
+static void show_reg(void);
+int nMemDump;
+int nDisAsm;
+int nSprite;
+void decimal2binary(int decimal_value, char binary_value[32], short digits);
+
+void debug(void)
+{
+ int done, i, go, j;
+ char *result;
+ char inp[80];
+ char *tok;
+ ADDRESS ad, run_to;
+ char cr[2], ff[2];
+ Byte d, a;
+
+ dbstick1 = dbstick2 = 0;
+ cr[0] = 13;
+ cr[1] = 0;
+ ff[0] = 0x0c;
+ ff[1] = 0;
+
+ done = go = 0;
+ set_display_switch_mode(SWITCH_BACKGROUND);
+
+ if (sndlog)
+ fclose(sndlog);
+
+#ifdef ALLEGRO_WINDOWS
+ FreeConsole();
+ AllocConsole();
+#endif
+
+ printf("\nDebug mode\n\n");
+
+ if (pc == app_data.breakpoint) {
+ printf("Breakpoint reached at %x\n", pc);
+ }
+
+ nMemDump = pc;
+ nDisAsm = pc;
+ nSprite = 0;
+ show_reg();
+
+ while (!done) {
+ while (go > 0) {
+ disasm(pc);
+ cpu_exec();
+ go--;
+ if (KBHIT()) {
+ go = 0;
+ cpu_exec();
+ show_reg();
+ }
+ }
+ printf("> ");
+ result = fgets(inp, 76, stdin);
+ if (result != NULL && strlen(inp) > 0 && inp[strlen(inp) - 1] == '\n')
+ inp[strlen(inp) - 1] = 0;
+ strlwr(inp);
+ strcat(inp, " \n");
+ tok = strtok(inp, " ");
+ if (!tok)
+ tok = "";
+ if (!strcmp(tok, "h") || !strcmp(tok, "?") || !strcmp(tok, "help")) {
+ printf("display - show display\n");
+ printf("viewsprite # - show memory # as sprite\n");
+// printf("editsprite # - edit memory # as sprite\n");
+ printf("showfps - display the number of frames per second\n");
+
+#ifdef ALLEGRO_DOS
+ printf("cls - clear screen\n");
+#endif
+
+ printf("clrkey - clear keypresses\n");
+ printf("setkey n - set key n pressed\n");
+ printf("stick1 # - set stick1 to #\n");
+ printf("stick2 # - set stick2 to #\n");
+
+ printf("reg - display registers\n");
+ printf("stack - display stack\n");
+ printf("col - display collision table\n");
+ printf(
+ "video (a d) - display VDC registers (or write data d to a)\n");
+ printf(
+ "extram (a d) - display external RAM (or write data d to a)\n");
+ printf(
+ "intram (a d) - display internal ram (or write data d to a)\n");
+
+ printf("s - step\n");
+ printf("so - step over\n");
+ printf("go # - execute # instructions\n");
+ printf("run # - run to address #\n");
+ printf("runvb - run to VBL\n");
+ printf("runnvb - run to no VBL\n");
+ printf("bp # - breakpoint at address #\n");
+ printf("bpc - clear breakpoint\n");
+ printf("reset - reset the machine\n");
+
+ printf("load file a - load file to memory to address\n");
+ printf("save file a n - save memory to file from address n Bytes\n");
+ printf("savedatah file a n - save memory to file from address a n Bytes format hex\n");
+ printf("savedatab file a n - save memory to file from address a n Bytes format binary\n");
+ printf("savevdc file a n - save VDC to file from address a n Bytes format hex\n");
+ printf("saveext file a n - save ExtRam to file from address a n Bytes format hex\n");
+ printf("savevpp file - save the VPP to file\n");
+
+ printf("as # - assemble memory #\n");
+ printf("di # - disassemble memory #\n");
+ printf("md # - display memory #\n");
+ printf("c # - change memory from location #\n");
+
+ printf("sndlog [file] - log raw sound to file\n");
+ printf("ss [file] - save state [to file]\n");
+ printf("ls [file] - load state [from file]\n");
+
+ printf("q - quit debugger and return to emulation\n");
+ printf("\n");
+ } else if (!strcmp(tok, "display")) {
+ grmode();
+ clip_low = 0;
+ clip_high = 85000;
+ draw_display();
+ finish_display();
+ init_keyboard();
+ do {
+ rest(1);
+ } while ((key_done == 0) && (!keypressed()));
+ set_textmode();
+ set_display_switch_mode(SWITCH_BACKGROUND);
+ } else if (!strcmp(tok, "viewsprite")) {
+ if (tok) {
+ tok = strtok(NULL, " ");
+ ad = 65535;
+ sscanf(tok, "%hx", &ad);
+ if (ad == 65535)
+ ad = nSprite;
+
+ for (i = 0; i < 8; i++) {
+ if (ad < 32768)
+ ad = ad + spriteprint(ad);
+ else
+ ad = 0;
+ }
+ nSprite = ad;
+ printf("\n");
+ }
+//TODO !!!! ----------------------------------------------------------------------------------------------------
+ } else if (!strcmp(tok, "editsprite")) {
+ if (tok) {
+ tok = strtok(NULL, " ");
+ ad = 65535;
+ sscanf(tok, "%hx", &ad);
+ if (ad != 65535) {
+ for (i = 0; i < 8; i++) {
+ if (ad < 32768)
+ ad = ad + spriteprint(ad);
+ else
+ ad = 0;
+ }
+ printf("\n");
+ }
+ }
+//----------------------------------------------------------------------------------------------------
+ } else if (!strcmp(tok, "cls")) {
+#ifdef ALLEGRO_DOS
+ clrscr();
+#endif
+ } else if (!strcmp(tok, "clrkey")) {
+ for (i = 0; i < 128; i++)
+ key2[i] = 0;
+ } else if (!strcmp(tok, "setkey")) {
+ tok = strtok(NULL, " ");
+ if (tok) {
+ sscanf(tok, "%d", &i);
+ if ((i > 0) && (i < 128)) {
+ printf("Key %d set to pressed\n", i);
+ key2[i] = 1;
+ }
+ key2vcnt = 0;
+ }
+ } else if (!strcmp(tok, "stick1")) {
+ tok = strtok(NULL, " ");
+ if (tok) {
+ i = 0;
+ sscanf(tok, "%x", &i);
+ printf("Stick 1 set to %d\n", i);
+ dbstick1 = i;
+ key2vcnt = 0;
+ }
+ } else if (!strcmp(tok, "stick2")) {
+ tok = strtok(NULL, " ");
+ if (tok) {
+ i = 0;
+ sscanf(tok, "%x", &i);
+ printf("Stick 2 set to %d\n", i);
+ dbstick2 = i;
+ key2vcnt = 0;
+ }
+ } else if (!strcmp(tok, "s")) {
+ cpu_exec();
+ show_reg();
+ } else if (!strcmp(tok, "so")) {
+ run_to = pc + lookup[rom[pc]].bytes;
+ printf("%hx\n", run_to);
+ while (pc != run_to) {
+ cpu_exec();
+ if (KBHIT())
+ break;
+ }
+ show_reg();
+ } else if (!strcmp(tok, "reset")) {
+ init_cpu();
+ init_roms();
+ init_vpp();
+ } else if (!strcmp(tok, "reg")) {
+ show_reg();
+ } else if (!strcmp(tok, "stack")) {
+ for (i = 8; i < 24; i += 2) {
+ ad = intRAM[i];
+ d = intRAM[i + 1];
+ ad = ad | ((d & 0x0F) << 8);
+ printf("%x: PC=%x PSW=%x", i, ad, d);
+ if (i == sp)
+ printf(" < 0) {
+ tok = strtok(NULL, " ");
+ if (tok) {
+ sscanf(tok, "%x", &adr);
+ tok = strtok(NULL, " ");
+ if (tok) {
+ sscanf(tok, "%i", &t);
+ fn = fopen(file, "wb");
+ if (fn == NULL) {
+ fprintf(stderr,
+ "Error opening save-file %s: %i\n",
+ file, errno);
+ } else {
+ fwrite((rom + adr), t, 1, fn);
+ fclose(fn);
+ printf(
+ "File %s saved: %i bytes from address:%x\n",
+ file, t, adr);
+ }
+ }
+ }
+
+ }
+ }
+ } else if (!strcmp(tok, "savedatah")) {
+ int t;
+ int adr;
+ FILE *fn;
+ tok = strtok(NULL, " ");
+ if (tok) {
+ char file[80] = "";
+ sscanf(tok, "%79s", file);
+ if (strlen(file) > 0) {
+ tok = strtok(NULL, " ");
+ if (tok) {
+ sscanf(tok, "%x", &adr);
+ tok = strtok(NULL, " ");
+ if (tok) {
+ sscanf(tok, "%i", &t);
+ fn = fopen(file, "wt");
+ if (fn == NULL) {
+ fprintf(stderr,
+ "Error opening save-data file %s: %i\n",
+ file, errno);
+ } else {
+ // write format "db 0XXh[,0XXh]" 8 Zeichen pro Zeile
+ int j = 0;
+ for (i = 0; i < ((int) ((t - 1) / 8)) + 1;
+ i++) {
+ fprintf(fn, "db ");
+ for (j = 0; j < 8 && i * 8 + j < t; j++) {
+ fprintf(fn, "0%02Xh",
+ rom[adr + i * 8 + j]);
+ if (j < 7 && i * 8 + j + 1 < t)
+ fprintf(fn, ",");
+ }
+ fprintf(fn, "\n");
+ }
+
+ fclose(fn);
+ printf(
+ "File %s saved: %i bytes from address:%x\n",
+ file, t, adr);
+ }
+ }
+ }
+ }
+ }
+ } else if (!strcmp(tok, "savevdc")) {
+ int t;
+ int adr;
+ FILE *fn;
+ tok = strtok(NULL, " ");
+ if (tok) {
+ char file[80] = "";
+ sscanf(tok, "%79s", file);
+ if (strlen(file) > 0) {
+ tok = strtok(NULL, " ");
+ if (tok) {
+ sscanf(tok, "%x", &adr);
+ tok = strtok(NULL, " ");
+ if (tok) {
+ sscanf(tok, "%i", &t);
+ fn = fopen(file, "wt");
+ if (fn == NULL) {
+ fprintf(stderr,
+ "Error opening save-data file %s: %i\n",
+ file, errno);
+ } else {
+ // write format "db 0XXh[,0XXh]" 8 Zeichen pro Zeile
+ int j = 0;
+ for (i = 0; i < ((int) ((t - 1) / 8)) + 1;
+ i++) {
+ fprintf(fn, "db ");
+ for (j = 0; j < 8 && i * 8 + j < t; j++) {
+ fprintf(fn, "0%02Xh",
+ VDCwrite[adr + i * 8 + j]);
+ if (j < 7 && i * 8 + j + 1 < t)
+ fprintf(fn, ",");
+ }
+ fprintf(fn, "\n");
+ }
+
+ fclose(fn);
+ printf(
+ "File %s saved: %i bytes from address:%x\n",
+ file, t, adr);
+ }
+ }
+ }
+ }
+ }
+ } else if (!strcmp(tok, "saveext")) {
+ int t;
+ int adr;
+ FILE *fn;
+ tok = strtok(NULL, " ");
+ if (tok) {
+ char file[80] = "";
+ sscanf(tok, "%79s", file);
+ if (strlen(file) > 0) {
+ tok = strtok(NULL, " ");
+ if (tok) {
+ sscanf(tok, "%x", &adr);
+ tok = strtok(NULL, " ");
+ if (tok) {
+ sscanf(tok, "%i", &t);
+ fn = fopen(file, "wt");
+ if (fn == NULL) {
+ fprintf(stderr,
+ "Error opening save-data file %s: %i\n",
+ file, errno);
+ } else {
+ // write format "db 0XXh[,0XXh]" 8 Zeichen pro Zeile
+ int j = 0;
+ for (i = 0; i < ((int) ((t - 1) / 8)) + 1;
+ i++) {
+ fprintf(fn, "db ");
+ for (j = 0; j < 8 && i * 8 + j < t; j++) {
+ fprintf(fn, "0%02Xh",
+ extRAM[adr + i * 8 + j]);
+ if (j < 7 && i * 8 + j + 1 < t)
+ fprintf(fn, ",");
+ }
+ fprintf(fn, "\n");
+ }
+
+ fclose(fn);
+ printf(
+ "File %s saved: %i bytes from address:%x\n",
+ file, t, adr);
+ }
+ }
+ }
+ }
+ }
+ } else if (!strcmp(tok, "savedatab")) {
+ int t;
+ int adr;
+ FILE *fn;
+ tok = strtok(NULL, " ");
+ if (tok) {
+ char file[80] = "";
+ sscanf(tok, "%79s", file);
+ if (strlen(file) > 0) {
+ tok = strtok(NULL, " ");
+ if (tok) {
+ sscanf(tok, "%x", &adr);
+ tok = strtok(NULL, " ");
+ if (tok) {
+ sscanf(tok, "%i", &t);
+ fn = fopen(file, "wt");
+ if (fn == NULL) {
+ fprintf(stderr,
+ "Error opening save-data file %s: %i\n",
+ file, errno);
+ } else {
+ char binary_value[32];
+ // write format "db xxxxxxxxb" 1 Zeichen pro Zeile
+ for (i = 0; i < t; i++) {
+ decimal2binary(rom[adr + i], binary_value,
+ 8);
+ fprintf(fn, "db %sb\n", binary_value);
+ }
+
+ fclose(fn);
+ printf(
+ "File %s saved: %i bytes from address:%x\n",
+ file, t, adr);
+ }
+ }
+ }
+ }
+ }
+ } else if (!strcmp(tok, "savevpp")) {
+ extern Byte vpp_mem[40][32][4];
+ extern Byte dchars[2][960];
+ Byte mchars[2][960]; /* bit-mirrored dchars */
+ FILE *fn;
+ char file[80] = "";
+ int i, j;
+
+ tok = strtok(NULL, " ");
+ if (tok) {
+ sscanf(tok, "%79s", file);
+ if (strlen(file) > 0) {
+ fn = fopen(file, "wt");
+ if (fn == NULL) {
+ fprintf(stderr, "Error opening vpp data file %s: %i\n",
+ file, errno);
+ } else {
+ /* write char/attribute data */
+ for (i = 0; i < 25; i++) {
+ /* service row is 24 in file, 31 in memory */
+ if (i == 24)
+ i = 31;
+ for (j = 0; j < 40; j++) {
+ if (fwrite(&vpp_mem[j][i][0], 1, 1, fn) != 1) {
+ fprintf(
+ stderr,
+ "Error writing vpp data file %s: %i\n",
+ file, errno);
+ break;
+ }
+ if (fwrite(&vpp_mem[j][i][1], 1, 1, fn) != 1) {
+ fprintf(
+ stderr,
+ "Error writing vpp data file %s: %i\n",
+ file, errno);
+ break;
+ }
+ }
+ /* mirror slice bits */
+ for (i = 0; i < 2; i++)
+ for (j = 0; j < 960; j++) {
+ mchars[i][j] = ((dchars[i][j] & 0x80) >> 7)
+ | ((dchars[i][j] & 0x40) >> 5)
+ | ((dchars[i][j] & 0x20) >> 3)
+ | ((dchars[i][j] & 0x10) >> 1)
+ | ((dchars[i][j] & 0x08) << 1)
+ | ((dchars[i][j] & 0x04) << 3)
+ | ((dchars[i][j] & 0x02) << 5)
+ | ((dchars[i][j] & 0x01) << 7);
+ }
+ /* write slice data */
+ if (fwrite(mchars, 960, 2, fn) != 2) {
+ fprintf(stderr,
+ "Error Writing vpp data file %s: %i\n",
+ file, errno);
+ break;
+ }
+ fclose(fn);
+ }
+ }
+ }
+ }
+ } else if (!strcmp(tok, "load")) {
+ int adr;
+ FILE *fn;
+ tok = strtok(NULL, " ");
+ if (tok) {
+ char file[80] = "";
+ sscanf(tok, "%79s", file);
+ if (strlen(file) > 0) {
+ tok = strtok(NULL, " ");
+ if (tok) {
+ sscanf(tok, "%x", &adr);
+ fn = fopen(file, "rb");
+ if (fn == NULL) {
+ fprintf(stderr, "Error opening load-file %s: %i\n",
+ file, errno);
+ } else {
+ int length;
+ int ret;
+ fseek(fn, 0L, SEEK_END);
+ length = ftell(fn);
+ rewind(fn);
+ ret = fread((rom + adr), length, 1, fn);
+ if (ret == 0) {
+ printf("Problem reading file\n");
+ }
+ fclose(fn);
+ printf("File %s loaded to address:%x (%i bytes)\n",
+ file, adr, length);
+ }
+ }
+ }
+ }
+ } else if (!strcmp(tok, "keys")) {
+ j = 0;
+ printf("%02x:", 0);
+ for (i = 0; i < 128; i++) {
+ printf("%02x,", key2[i]);
+ j++;
+ if (j == 16) {
+ printf("\n");
+ printf("%02x:", i + 1);
+
+ j = 0;
+ }
+ }
+ printf("\n");
+ } else if (!strcmp(tok, "col")) {
+ j = 0;
+ printf("%02x:", 0);
+ for (i = 0; i < 256; i++) {
+ printf("%02x,", coltab[i]);
+ j++;
+ if (j == 16) {
+ printf("\n");
+ printf("%02x:", i + 1);
+ j = 0;
+ }
+ }
+ printf("\n");
+ printf("Colreg: %x\n ", ext_read(0xA2));
+ } else if (!strcmp(tok, "extram")) {
+ int t;
+ tok = strtok(NULL, " ");
+ if (tok) {
+ sscanf(tok, "%x", &t);
+ a = (Byte) t;
+ tok = strtok(NULL, " ");
+ if (tok) {
+ sscanf(tok, "%x", &t);
+ d = (Byte) t;
+ extRAM[a] = d;
+ } else {
+ j = 0;
+ printf("%02x:", 0);
+ for (i = 0; i < 256; i++) {
+ printf("%02x", extRAM[i]);
+ if (j < 15)
+ printf(",");
+ j++;
+ if (j == 16 && i != 255) {
+ printf("\n");
+ printf("%02x:", i + 1);
+
+ j = 0;
+ }
+ }
+ }
+ }
+ printf("\n\n");
+ } else if (!strcmp(tok, "intram")) {
+ int t;
+ tok = strtok(NULL, " ");
+ if (tok) {
+ sscanf(tok, "%x", &t);
+ a = (Byte) t;
+ tok = strtok(NULL, " ");
+ if (tok) {
+ sscanf(tok, "%x", &t);
+ d = (Byte) t;
+ intRAM[a] = d;
+ } else {
+ j = 0;
+ printf("%02x:", 0);
+ for (i = 0; i < 64; i++) {
+ printf("%02x", intRAM[i]);
+ if (j < 15)
+ printf(",");
+ j++;
+ if (j == 16 && i != 63) {
+ printf("\n");
+ printf("%02x:", i + 1);
+ j = 0;
+ }
+ }
+ printf("\n\n");
+ }
+ }
+ } else if (!strcmp(tok, "run")) {
+ tok = strtok(NULL, " ");
+ if (tok) {
+ sscanf(tok, "%hx", &run_to);
+ printf("Run to %x\n", run_to);
+ while (pc != run_to) {
+ cpu_exec();
+ if (KBHIT())
+ break;
+ }
+ show_reg();
+ }
+ } else if (!strcmp(tok, "bp")) {
+ int bp;
+ tok = strtok(NULL, " ");
+ bp = 65535;
+ sscanf(tok, "%x", &bp);
+ if (bp == 65535) {
+ if (app_data.breakpoint == 65535)
+ printf("No Breakpoint set.\n");
+ else
+ printf("Breakpoint at %x\n", app_data.breakpoint);
+ } else {
+ sscanf(tok, "%x", &bp);
+ app_data.breakpoint = bp;
+ printf("Breakpoint set to %x\n", app_data.breakpoint);
+ }
+ } else if (!strcmp(tok, "bpc")) {
+ if (app_data.breakpoint == 65535)
+ printf("No Breakpoint set.\n");
+ else {
+ app_data.breakpoint = 65535;
+ printf("Breakpoint cleared.\n");
+ }
+ } else if (!strcmp(tok, "runvb")) {
+ printf("Run to VBL\n");
+ while (master_clk < 5500) {
+ cpu_exec();
+ if (KBHIT())
+ break;
+ }
+ show_reg();
+ } else if (!strcmp(tok, "runnvb")) {
+ printf("Run to no VBL\n");
+ while (master_clk > 5500) {
+ cpu_exec();
+ if (KBHIT())
+ break;
+ }
+ show_reg();
+ } else if (!strcmp(tok, "go")) {
+ tok = strtok(NULL, " ");
+ if (tok)
+ sscanf(tok, "%d", &go);
+ } else if (!strcmp(tok, "di")) {
+ if (tok) {
+ tok = strtok(NULL, " ");
+ ad = 65535;
+ sscanf(tok, "%hx", &ad);
+ if (ad == 65535)
+ ad = nDisAsm;
+
+ for (i = 0; i < 20; i++) {
+ if (ad < 32768)
+ ad = ad + disasm(ad);
+ else
+ ad = 0;
+ }
+ nDisAsm = ad;
+ printf("\n");
+ }
+ } else if (!strcmp(tok, "md")) {
+ tok = strtok(NULL, " ");
+ if (tok) {
+ ad = 65535;
+ sscanf(tok, "%hx", &ad);
+ if (ad == 65535)
+ ad = nMemDump;
+ printf("\n");
+
+ for (j = 0; j < 10; j++) {
+ if (ad + j * 16 < 32768) {
+ printf("%04x : ", ad + j * 16);
+ for (i = 0; i < 16; i++)
+ printf("%02x ", rom[ad + j * 16 + i]);
+ printf("\n");
+ } else {
+ ad = 0;
+ }
+ }
+ nMemDump = ad + 10 * 16;
+ printf("\n\n");
+ }
+ } else if (!strcmp(tok, "sndlog")) {
+ if (app_data.sound_en) {
+ tok = strtok(NULL, " ");
+ if (tok) {
+ char file[80] = "";
+ sscanf(tok, "%79s", file);
+ if (strlen(file) > 0) {
+ sndlog = fopen(file, "wb");
+ if (sndlog)
+ printf("Sound log file created\n");
+ else
+ printf("Sound log file creation failed\n");
+ }
+ }
+ printf("\n");
+ } else
+ printf("Sound emulation disabled\n\n");
+
+ } else if (!strcmp(tok, "ss")) {
+ tok = strtok(NULL, " ");
+ if (tok) {
+ char file[80] = "";
+ sscanf(tok, "%79s", file);
+ if (strlen(file) > 0) {
+ savestate(file);
+ }
+ }
+ printf("\n");
+
+ } else if (!strcmp(tok, "ls")) {
+ tok = strtok(NULL, " ");
+ if (tok) {
+ char file[80] = "";
+ sscanf(tok, "%79s", file);
+ if (strlen(file) > 0) {
+ loadstate(file);
+ }
+ }
+ printf("\n");
+
+ } else if (!strcmp(tok, "showfps")) {
+ show_fps = 1;
+
+ } else if (!strcmp(tok, "c")) {
+ int t;
+ tok = strtok(NULL, " ");
+ if (tok) {
+ sscanf(tok, "%hx", &ad);
+ printf("Addr Old New (enter to exit)\n"); // Header
+
+ do {
+ printf("%.4X %.2X ?", ad, rom[ad]); // Memory Position, Old Value
+
+ result = fgets(inp, 80, stdin);
+ if (inp[0] != 10) {
+ t = 65535;
+ sscanf(inp, "%x", &t);
+ if (t < 256) {
+ d = (Byte) t;
+ rom[ad] = d;
+ ad = (ad == 32768) ? 0 : ad + 1;
+ } else {
+ printf("wrong value, try again\n");
+ }
+ }
+ } while (inp[0] != 10);
+ }
+ printf("\n");
+ } else if (!strcmp(tok, "as")) {
+ tok = strtok(NULL, " ");
+ if (tok) {
+ sscanf(tok, "%hx", &ad);
+
+ printf("Addr Instruction (enter to exit)\n"); // Header
+ do {
+ printf("%.4X ", ad); // Memory Position
+ result = fgets(inp, 80, stdin);
+
+ if (inp[0] != 10) {
+ ad = ad + assemble(inp, ad);
+ }
+ } while (inp[0] != 10);
+ }
+ printf("\n");
+
+ } else if ((strlen(tok) > 0) && (strcmp(tok, "\n"))) {
+ printf("Unknown command\n\n");
+ }
+
+ }
+
+#ifdef ALLEGRO_WINDOWS
+ FreeConsole();
+#endif
+
+}
+
+static void show_reg(void)
+{
+ int i;
+
+ make_psw_debug();
+ printf("PC=%.3X A=%.2X PSW=%.2X P1=%.2X P2=%.2X", pc, acc, psw, p1, p2);
+ printf(" clk: %d reg:%d count:%x f:%x\n", master_clk, reg_pnt, itimer,
+ frame);
+ disasm(pc);
+ printf("\n");
+
+ printf("R%d: %02x R%d': %02x PSW: ", 0, intRAM[0], 0, intRAM[24]);
+ printf("%sC %sAC %sF0 %sF1 SP:%.2X\n", psw & 0x80 ? "" : "!",
+ psw & 0x40 ? "" : "!", psw & 0x20 ? "" : "!", psw & 0x10 ? "" : "!",
+ psw & 0x07);
+
+ printf("R%d: %02x R%d': %02x P1: ", 1, intRAM[1], 1, intRAM[25]);
+ printf("%sLum %sCopy %sVP+ %sExtRam %sVDC %sKeyB Bank:%i\n",
+ p1 & 0x80 ? "" : "!", p1 & 0x40 ? "" : "!", p1 & 0x20 ? "" : "!",
+ p1 & 0x10 ? "" : "!", p1 & 0x08 ? "" : "!", p1 & 0x04 ? "" : "!",
+ p1 & 0x03);
+
+ printf("R%d: %02x R%d': %02x ", 2, intRAM[2], 2, intRAM[26]);
+ printf("MB%i RB%i\n", A11ff >> 11, reg_pnt > 4);
+
+ for (i = 3; i < 8; i++) {
+ printf("R%d: %02x R%d': %02x\n", i, intRAM[i], i, intRAM[i + 24]);
+ }
+}
+
+static int disasm(ADDRESS p)
+{
+ Byte op, d;
+ ADDRESS adr;
+
+ op = rom[p++];
+ printf("%04x %02x", p - 1, op);
+ if (lookup[op].bytes == 2)
+ printf(" %02x", rom[p]);
+ else
+ printf(" ");
+ printf(" %s", lookup[op].mnemonic);
+ switch (lookup[op].type) {
+ case 0:
+ printf("\n");
+ break;
+ case 1:
+ d = rom[p];
+ printf(" #%02x\n", d);
+ break;
+ case 2:
+ adr = rom[p];
+ adr = adr | ((op & 0xE0) << 3);
+ printf(" $%03x\n", adr);
+ break;
+ case 3:
+ printf(" $%02x\n", rom[p]);
+ break;
+ }
+ return lookup[op].bytes;
+}
+
+static int assemble(char *opcode, int p)
+{
+ char *str_value;
+ int op = 0;
+ int value;
+ int t;
+
+ while ((op < 256)
+ && (strncasecmp(opcode, lookup[op].mnemonic,
+ strlen(lookup[op].mnemonic)) != 0))
+ op++;
+
+ if (op == 256) {
+ printf("Wrong opcode, please try again.\n");
+ return (0);
+ }
+
+ str_value = opcode + strlen(lookup[op].mnemonic);
+ while (str_value[0] == ' ')
+ str_value++;
+
+ switch (lookup[op].type) {
+ case 0: // no other value needed
+ rom[p] = op;
+ break;
+ case 1: // #value needed
+ if (str_value[0] != '#') {
+ printf("Error: #xx expected\n");
+ return (0);
+ }
+ t = 65335;
+ sscanf(str_value + 1, "%2x", &t);
+ if (t >= 256) {
+ printf("Error: #xx expected (value #00-#FF)\n");
+ return (0);
+ } else
+ value = (Byte) t;
+ rom[p] = op;
+ rom[p + 1] = value;
+ break;
+ case 2: // $addresss needed (max. 7FF)
+ if (str_value[0] != '$') {
+ printf("Error: $xxx expected %s\n", str_value);
+ return (0);
+ }
+ t = 65335;
+ sscanf(str_value + 1, "%x", &t);
+ if (t >= 2048) {
+ printf("Error: $xxx expected (value below $800)\n");
+ return (0);
+ } else
+ value = (Byte) t;
+ rom[p] = op | ((t & 1792) >> 3);
+ rom[p + 1] = value;
+ break;
+
+ case 3: // $address needed (max. FF)
+ if (str_value[0] != '$') {
+ printf("Error: $xx expected\n");
+ return (0);
+ }
+ t = 65335;
+ sscanf(str_value + 1, "%x", &t);
+ if (t >= 256) {
+ printf("Error: $xx expected (value $00-$FF)\n");
+ return (0);
+ } else
+ value = (Byte) t;
+ rom[p] = op;
+ rom[p + 1] = value;
+ break;
+
+ }
+ return lookup[op].bytes;
+}
+
+void decimal2binary(int decimal_value, char binary_value[32], short digits)
+{
+ short i;
+ for (i = digits; i >= 0; i--) {
+ binary_value[i] = (char) ('0' + (int) (decimal_value / (1 << i)));
+ decimal_value = decimal_value % (1 << i);
+ }
+ binary_value[digits] = 0;
+}
+
+static int spriteprint(ADDRESS p)
+{
+ char binary_value[32];
+ int i;
+
+ decimal2binary(rom[p], binary_value, 8);
+ printf("%04x %sb ", p, binary_value);
+
+ for (i = 7; i >= 0; i--) {
+ if (binary_value[i] == '0')
+ printf(" ");
+ else
+ printf("%c", 178);
+ }
+
+ printf("\n");
+ return 1;
+}
diff --git a/clean/src/debug.h b/clean/src/debug.h
new file mode 100755
index 0000000..ce9be9e
--- /dev/null
+++ b/clean/src/debug.h
@@ -0,0 +1,14 @@
+#ifndef DEBUG_H
+#define DEBUG_H
+
+void debug(void);
+
+#endif /* DEBUG_H */
+
+
+
+
+
+
+
+
diff --git a/clean/src/dis48.c b/clean/src/dis48.c
new file mode 100755
index 0000000..b752dbc
--- /dev/null
+++ b/clean/src/dis48.c
@@ -0,0 +1,144 @@
+
+/*
+ * O2/8048 disassembler
+ */
+
+
+#include
+#include
+#include
+#include
+#include "types.h"
+#include "table.h"
+#include "debug.h"
+
+#define BIOSLEN 1024
+#define MAXLEN 8192
+
+
+Byte rom[MAXLEN+BIOSLEN];
+ADDRESS pc;
+
+int parse_option(char *attr, char *val);
+
+static int disasm(ADDRESS p) {
+ Byte op,d;
+ ADDRESS adr;
+
+ op=rom[p++];
+ printf("%04x %02x",p-1,op);
+ if (lookup[op].bytes == 2) printf(" %02x",rom[p]); else printf(" ");
+ printf(" %s",lookup[op].mnemonic);
+ switch(lookup[op].type) {
+ case 0:
+ printf("\n");
+ break;
+ case 1:
+ d=rom[p];
+ printf(" #%02x\n",d);
+ break;
+ case 2:
+ adr=rom[p];
+ adr = adr | ((op & 0xE0) << 3);
+ printf(" $%03x\n",adr);
+ break;
+ case 3:
+ printf(" $%02x\n",rom[p]);
+ break;
+ }
+ if (op == 0x83 || op == 0x93 || (((p-2+lookup[op].bytes) & 0xff) == 0xff)) printf("\n"); // Linebreak after ret, retr and end of page
+ return lookup[op].bytes;
+}
+
+
+int main(int argc, char **argv){
+ int n;
+ int i,j;
+ int start;
+ long len;
+ FILE *fn;
+ static char file[MAXC], attr[MAXC], val[MAXC], *p;
+ pc = BIOSLEN;
+ if (argc<2) {
+ printf("Usage: dis48 [file] [-bios]\n");
+ exit(0);
+ }
+
+ /* load image */
+ for(i=1; iMAXLEN) {
+ printf("Invalid image size");
+ fclose(fn);
+ exit(0);
+ }
+
+ rewind(fn);
+ if (fread(&rom[pc],1,len,fn) != (size_t)len) {
+ printf("Error loading %s\n",argv[1]);
+ fclose(fn);
+ exit(0);
+ }
+ fclose(fn);
+
+ start = pc;
+ while (pc < start+len) {
+ n = disasm(pc);
+ pc = pc + n;
+ }
+ exit(0);
+}
+
+int parse_option(char *attr, char *val)
+{
+ if (!strcmp(attr,"bios")) {
+ pc = 0;
+ } else {
+ fprintf(stderr,"Invalid option : %s\n",attr);
+ return 0;
+ }
+ return 1;
+}
diff --git a/clean/src/keyboard.c b/clean/src/keyboard.c
new file mode 100755
index 0000000..2b0414f
--- /dev/null
+++ b/clean/src/keyboard.c
@@ -0,0 +1,374 @@
+/*
+ * O2EM Free Odyssey2 / Videopac+ Emulator
+ *
+ * Created by Daniel Boris (c) 1997,1998
+ *
+ * Developed by Andre de la Rocha
+ * Arlindo M. de Oliveira
+ *
+ * http://o2em.sourceforge.net
+ *
+ *
+ *
+ * Keyboard emulation
+ */
+
+#include
+#include
+#include
+#include "types.h"
+#include "cpu.h"
+#include "config.h"
+#include "vmachine.h"
+#include "vdc.h"
+#include "audio.h"
+#include "voice.h"
+#include "vpp.h"
+#include "keyboard.h"
+#include "allegro.h"
+#include "score.h"
+
+int NeedsPoll = 0;
+
+Byte keycode;
+Byte last_key;
+Byte new_int=0; /* Is new interrupt installed */
+
+Byte key_done=0;
+Byte key_debug=0;
+#ifdef OPENEMU
+struct keyb keybtab[] = {
+ {KEY_A,"A"},
+ {KEY_B,"B"},
+ {KEY_C,"C"},
+ {KEY_D,"D"},
+ {KEY_E,"E"},
+ {KEY_F,"F"},
+ {KEY_G,"G"},
+ {KEY_H,"H"},
+ {KEY_I,"I"},
+ {KEY_J,"J"},
+ {KEY_K,"K"},
+ {KEY_L,"L"},
+ {KEY_M,"M"},
+ {KEY_N,"N"},
+ {KEY_O,"O"},
+ {KEY_P,"P"},
+ {KEY_Q,"Q"},
+ {KEY_R,"R"},
+ {KEY_S,"S"},
+ {KEY_T,"T"},
+ {KEY_U,"U"},
+ {KEY_V,"V"},
+ {KEY_W,"W"},
+ {KEY_X,"X"},
+ {KEY_Y,"Y"},
+ {KEY_Z,"Z"},
+ {KEY_0,"0"},
+ {KEY_1,"1"},
+ {KEY_2,"2"},
+ {KEY_3,"3"},
+ {KEY_4,"4"},
+ {KEY_5,"5"},
+ {KEY_6,"6"},
+ {KEY_7,"7"},
+ {KEY_8,"8"},
+ {KEY_9,"9"},
+ {KEY_0_PAD,"0_PAD"},
+ {KEY_1_PAD,"1_PAD"},
+ {KEY_2_PAD,"2_PAD"},
+ {KEY_3_PAD,"3_PAD"},
+ {KEY_4_PAD,"4_PAD"},
+ {KEY_5_PAD,"5_PAD"},
+ {KEY_6_PAD,"6_PAD"},
+ {KEY_7_PAD,"7_PAD"},
+ {KEY_8_PAD,"8_PAD"},
+ {KEY_9_PAD,"9_PAD"},
+ {KEY_TILDE,"TILDE"},
+ {KEY_MINUS,"MINUS"},
+ {KEY_EQUALS,"EQUALS"},
+ {KEY_BACKSPACE,"BACKSPACE"},
+ {KEY_TAB,"TAB"},
+ {KEY_OPENBRACE,"OPENBRACE"},
+ {KEY_CLOSEBRACE,"CLOSEBRACE"},
+ {KEY_ENTER,"ENTER"},
+ {KEY_COLON,"COLON"},
+ {KEY_QUOTE,"QUOTE"},
+ {KEY_BACKSLASH,"BACKSLASH"},
+ {KEY_BACKSLASH2,"BACKSLASH2"},
+ {KEY_COMMA,"COMMA"},
+ {KEY_STOP,"STOP"},
+ {KEY_SLASH,"SLASH"},
+ {KEY_SPACE,"SPACE"},
+ {KEY_INSERT,"INSERT"},
+ {KEY_DEL,"DEL"},
+ {KEY_HOME,"HOME"},
+ {KEY_END,"END"},
+ {KEY_PGUP,"PGUP"},
+ {KEY_PGDN,"PGDN"},
+ {KEY_LEFT,"LEFT"},
+ {KEY_RIGHT,"RIGHT"},
+ {KEY_UP,"UP"},
+ {KEY_DOWN,"DOWN"},
+ {KEY_SLASH_PAD,"SLASH_PAD"},
+ {KEY_ASTERISK,"ASTERISK"},
+ {KEY_MINUS_PAD,"MINUS_PAD"},
+ {KEY_PLUS_PAD,"PLUS_PAD"},
+ {KEY_DEL_PAD,"DEL_PAD"},
+ {KEY_ENTER_PAD,"ENTER_PAD"},
+ {KEY_PRTSCR,"PRTSCR"},
+ {KEY_PAUSE,"PAUSE"},
+ {KEY_ABNT_C1,"ABNT_C1"},
+ {KEY_YEN,"YEN"},
+ {KEY_KANA,"KANA"},
+ {KEY_AT,"AT"},
+ {KEY_CIRCUMFLEX,"CIRCUMFLEX"},
+ {KEY_COLON2,"COLON2"},
+ {KEY_KANJI,"KANJI"},
+ {KEY_LSHIFT,"LSHIFT"},
+ {KEY_RSHIFT,"RSHIFT"},
+ {KEY_LCONTROL,"LCONTROL"},
+ {KEY_RCONTROL,"RCONTROL"},
+ {KEY_ALT,"ALT"},
+ {KEY_ALTGR,"ALTGR"},
+ {KEY_LWIN,"LWIN"},
+ {KEY_RWIN,"RWIN"},
+ {KEY_MENU,"MENU"},
+ {KEY_SCRLOCK,"SCRLOCK"},
+ {KEY_NUMLOCK,"NUMLOCK"},
+ {KEY_F1,"F1"},
+ {KEY_F2,"F2"},
+ {KEY_F3,"F3"},
+ {KEY_F4,"F4"},
+ {KEY_F5,"F5"},
+ {KEY_F6,"F6"},
+ {KEY_F7,"F7"},
+ {KEY_F8,"F8"},
+ {KEY_F9,"F9"},
+ {KEY_F10,"F10"},
+ {KEY_F11,"F11"},
+ {KEY_F12,"F12"},
+ {KEY_ESC,"ESC"},
+ {0,""}
+};
+#endif
+
+int joykeys[2][5] = {{0,0,0,0,0},{0,0,0,0,0}};
+int joykeystab[128];
+int syskeys[8] = {0,0,0,0,0,0,0,0};
+
+void set_defjoykeys(int stick_number, int control_scheme){
+ printf("Setting keyboard controller %d to %d\n", stick_number, control_scheme);
+ if (control_scheme) {
+ // TODO : Implement Azery / Qwerty handler
+ set_joykeys(stick_number, KEY_W, KEY_S, KEY_A, KEY_D, KEY_SPACE);
+ } else {
+ set_joykeys(stick_number,KEY_UP,KEY_DOWN,KEY_LEFT,KEY_RIGHT,KEY_L);
+ }
+}
+
+void set_defsystemkeys(void)
+{
+ set_systemkeys(KEY_F12,KEY_F1,KEY_F4,KEY_F5,KEY_F8,KEY_F2,KEY_F3,KEY_F6);
+}
+
+void set_joykeys(int stick_number, int up, int down, int left, int right, int fire){
+ printf("Setting joypad controller %d \n", stick_number);
+ int i, j;
+ if ((stick_number<0) || (stick_number>1)) {
+ return;
+ }
+ joykeys[stick_number][0] = up;
+ joykeys[stick_number][1] = down;
+ joykeys[stick_number][2] = left;
+ joykeys[stick_number][3] = right;
+ joykeys[stick_number][4] = fire;
+
+ for (i=0; i<128; i++) {
+ joykeystab[i]=0;
+ }
+
+ for (j=0; j<2; j++) {
+ for (i=0; i<5; i++) {
+ if ((joykeys[j][i]<1) || (joykeys[j][i]>127)) {
+ joykeys[j][i] = 0;
+ } else {
+ joykeystab[joykeys[j][i]] = 1;
+ }
+ }
+ }
+}
+
+void set_systemkeys(int k_quit,int k_pause,int k_debug,int k_reset,int k_screencap,int k_save,int k_load,int k_inject)
+{
+ syskeys[0] = k_quit;
+ syskeys[1] = k_pause;
+ syskeys[2] = k_debug;
+ syskeys[3] = k_reset;
+ syskeys[4] = k_screencap;
+ syskeys[5] = k_save;
+ syskeys[6] = k_load;
+ syskeys[7] = k_inject;
+}
+
+void handle_key(void){
+ if (NeedsPoll) poll_keyboard();
+
+
+ if (key[syskeys[0]] || key[KEY_ESC]) {
+ do {
+ rest(5);
+ if (NeedsPoll) poll_keyboard();
+ } while (key[syskeys[0]] || key[KEY_ESC]);
+ key_done=1;
+ }
+
+ if (key[syskeys[1]]) {
+ do {
+ rest(5);
+ if (NeedsPoll) poll_keyboard();
+ } while (key[syskeys[1]]);
+
+ mute_audio();
+ mute_voice();
+ abaut();
+
+ do {
+ rest(5);
+ if (NeedsPoll) poll_keyboard();
+
+ if (key[KEY_ALT] && key[KEY_ENTER]) {
+ app_data.fullscreen = app_data.fullscreen ? 0 : 1;
+ grmode();
+ abaut();
+ do {
+ rest(5);
+ if (NeedsPoll) poll_keyboard();
+ } while (key[KEY_ENTER]);
+ }
+
+ } while ((!key[syskeys[1]]) && (!key[KEY_ESC]) && (!key[syskeys[0]]));
+ do {
+ rest(5);
+ if (NeedsPoll) poll_keyboard();
+ } while (key[syskeys[1]]);
+
+ init_sound_stream();
+ }
+
+ if (key[syskeys[5]]) {
+ if (savestate(app_data.statefile)==0) {
+ display_msg("Savefile saved.",5);
+ }
+ do {
+ rest(5);
+ if (NeedsPoll) poll_keyboard();
+ } while (key[syskeys[5]]);
+ }
+
+ /* LOAD STATE */
+ if (key[syskeys[6]]) {
+ int stateError;
+ if ((stateError=loadstate(app_data.statefile))==0) {
+ display_msg("Savefile loaded.",5);
+ } else if (stateError>=199) {
+ if (stateError==199) display_msg("Wrong ROM-File for Savefile.",5);
+ else if (stateError==200+ROM_O2) display_msg("Wrong BIOS for Savefile: O2ROM needed.",5);
+ else if (stateError==200+ROM_G7400) display_msg("Wrong BIOS for Savefile: G7400 ROM needed.",5);
+ else if (stateError==200+ROM_C52) display_msg("Wrong BIOS for Savefile: C52 ROM needed.",5);
+ else if (stateError==200+ROM_JOPAC) display_msg("Wrong BIOS for Savefile: JOPAC ROM needed.",5);
+ else display_msg("Wrong BIOS for Savefile: UNKNOWN ROM needed.",5);
+ }
+ do {
+ rest(5);
+ if (NeedsPoll) poll_keyboard();
+ } while (key[syskeys[6]]);
+ }
+
+ if (key[syskeys[2]]) key_debug=1;
+
+ if (key[syskeys[3]]) {
+ init_cpu();
+ init_roms();
+ init_vpp();
+ clearscr();
+ do {
+ rest(5);
+ if (NeedsPoll) poll_keyboard();
+ } while (key[syskeys[3]]);
+ }
+
+ /* SET HIGHSCORE */
+ if (key[syskeys[7]]) {
+ set_score(app_data.scoretype, app_data.scoreaddress, app_data.default_highscore);
+ }
+
+
+ if (key[syskeys[4]]) {
+#ifdef OPENEMU
+ BITMAP *bmp;
+ PALETTE pal;
+ char *p;
+ static char name[1024];
+ static int scshot_counter = 0;
+
+ if (strlen(app_data.scshot)>0){
+ if ((p=strchr(app_data.scshot,'@'))) {
+ *p = 0;
+ sprintf(name, "%s%02d%s", app_data.scshot, scshot_counter++, p+1);
+ *p = '@';
+ } else {
+ strcpy(name, app_data.scshot);
+ }
+ get_palette(pal);
+ bmp = create_sub_bitmap(screen, 0, 0, SCREEN_W, SCREEN_H);
+ save_bitmap(name, bmp, pal);
+ destroy_bitmap(bmp);
+ do {
+ rest(5);
+ if (NeedsPoll) poll_keyboard();
+ } while (key[syskeys[4]]);
+ }
+#endif
+ }
+
+ if (key[KEY_ALT] && key[KEY_ENTER]) {
+ app_data.fullscreen = app_data.fullscreen ? 0 : 1;
+ grmode();
+ do {
+ rest(5);
+ if (NeedsPoll) poll_keyboard();
+ } while (key[KEY_ENTER]);
+ }
+
+}
+
+Byte keyjoy(int jn){
+ Byte d;
+ d=0xFF;
+ if ((jn>=0) && (jn<=1)){
+ if (NeedsPoll) poll_keyboard();
+ if (key[joykeys[jn][0]]) d &= 0xFE;
+ if (key[joykeys[jn][1]]) d &= 0xFB;
+ if (key[joykeys[jn][2]]) d &= 0xF7;
+ if (key[joykeys[jn][3]]) d &= 0xFD;
+ if (key[joykeys[jn][4]]) d &= 0xEF;
+ }
+ return d;
+}
+
+
+void init_keyboard(void){
+ key_done=0;
+ key_debug=0;
+ install_keyboard();
+ new_int=1;
+ NeedsPoll = keyboard_needs_poll();
+}
+
+
+void Set_Old_Int9(void){
+ remove_keyboard();
+ new_int=0;
+}
+
diff --git a/clean/src/keyboard.h b/clean/src/keyboard.h
new file mode 100755
index 0000000..c8fae16
--- /dev/null
+++ b/clean/src/keyboard.h
@@ -0,0 +1,96 @@
+#ifndef __KEYBOARD_H
+#define __KEYBOARD_H
+
+void Set_Old_Int9(void);
+void init_keyboard(void);
+void handle_key(void);
+void set_joykeys(int joy, int up, int down, int left, int right, int fire);
+void set_systemkeys(int k_quit, int k_pause, int k_debug, int k_reset,
+ int k_screencap, int k_save, int k_load, int k_inject);
+void set_defjoykeys(int joy, int sc);
+void set_defsystemkeys(void);
+Byte keyjoy(int jn);
+
+extern Byte new_int;
+extern int NeedsPoll;
+extern Byte key_done;
+extern Byte key_debug;
+extern int joykeys[2][5];
+extern int joykeystab[128];
+extern int syskeys[8];
+
+struct keyb
+{
+ int keybcode;
+ char *keybname;
+};
+
+extern struct keyb keybtab[];
+
+#ifdef OPENEMU
+#endif
+
+#define KEY_W 0
+#define KEY_S 0
+#define KEY_A 0
+#define KEY_D 0
+#define KEY_SPACE 0
+#define KEY_UP 0
+#define KEY_DOWN 0
+#define KEY_LEFT 0
+#define KEY_RIGHT 0
+#define KEY_L 0
+#define KEY_F12 0
+#define KEY_F1 0
+#define KEY_F4 0
+#define KEY_F5 0
+#define KEY_F8 0
+#define KEY_F2 0
+#define KEY_F3 0
+#define KEY_F6 0
+#define KEY_ESC 0
+#define KEY_ALT 0
+#define KEY_ENTER 0
+
+#define KEY_0 0
+#define KEY_1 0
+#define KEY_2 0
+#define KEY_3 0
+#define KEY_4 0
+#define KEY_5 0
+#define KEY_6 0
+#define KEY_7 0
+#define KEY_8 0
+#define KEY_9 0
+#define KEY_SLASH 0
+#define KEY_P 0
+#define KEY_PLUS_PAD 0
+#define KEY_E 0
+#define KEY_R 0
+#define KEY_T 0
+#define KEY_U 0
+#define KEY_I 0
+#define KEY_O 0
+#define KEY_Q 0
+#define KEY_F 0
+#define KEY_G 0
+#define KEY_H 0
+#define KEY_J 0
+#define KEY_K 0
+#define KEY_Z 0
+#define KEY_X 0
+#define KEY_C 0
+#define KEY_V 0
+#define KEY_B 0
+#define KEY_M 0
+#define KEY_STOP 0
+#define KEY_MINUS 0
+#define KEY_ASTERISK 0
+#define KEY_SLASH_PAD 0
+#define KEY_EQUALS 0
+#define KEY_Y 0
+#define KEY_N 0
+#define KEY_DEL 0
+
+#endif
+
diff --git a/clean/src/main.c b/clean/src/main.c
new file mode 100755
index 0000000..ddd3c5a
--- /dev/null
+++ b/clean/src/main.c
@@ -0,0 +1,922 @@
+/*
+ * O2EM Free Odyssey2 / Videopac+ Emulator
+ *
+ * Created by Daniel Boris (c) 1997,1998
+ *
+ * Developed by Andre de la Rocha
+ * Arlindo M. de Oliveira
+ *
+ * http://o2em.sourceforge.net
+ *
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#include "crc32.h"
+#include "audio.h"
+#include "vmachine.h"
+#include "config.h"
+#include "vdc.h"
+#include "cpu.h"
+#include "debug.h"
+#include "keyboard.h"
+#include "voice.h"
+#include "allegro.h"
+#include "score.h"
+#ifdef ALLEGRO_WINDOWS
+#include "winalleg.h"
+#endif
+static char bios[MAXC], scshot[MAXC], xrom[MAXC], romdir[MAXC], xbios[MAXC],
+ biosdir[MAXC], arkivo[MAXC][MAXC], biossux[MAXC], romssux[MAXC],
+ odyssey2[MAXC], g7400[MAXC], c52[MAXC], jopac[MAXC], file_l[MAXC],
+ bios_l[MAXC], file_v[MAXC], scorefile[MAXC], statefile[MAXC],
+ path[MAXC];
+FILE *f;
+char name_f, rom_f, c_j;
+char pathx, *k, *launcher_flag_r, *launcher_flag_b, identify;
+int file_name(char *pathx);
+int suck_bios();
+int suck_roms();
+int identify_bios(char *identify);
+int contax, o2flag, g74flag, c52flag, jopflag, helpflag;
+int j;
+unsigned long crcx = ~0;
+static long filesize(FILE * stream);
+static void load_bios(const char *biosname);
+static void load_cart(char *file);
+static void helpus(void);
+int parse_option(char *attr, char *val);
+void read_default_config(void);
+
+int main(int argc, char *argv[])
+{
+ int i, cnt, cnt2;
+ static char file[MAXC], attr[MAXC], val[MAXC], *p, *binver;
+#if defined(ALLEGRO_WINDOWS)
+ binver = "Windows binary";
+#elif defined(ALLEGRO_DOS)
+ binver = "DOS binary";
+#elif defined(ALLEGRO_LINUX)
+ binver = "Linux binary";
+#elif defined(ALLEGRO_BEOS)
+ binver = "BEOS binary";
+#elif defined(ALLEGRO_QNX)
+ binver = "QNX binary";
+#elif defined(ALLEGRO_UNIX)
+ binver = "UNIX binary";
+#elif defined(ALLEGRO_MPW)
+ binver = "MacOS binary";
+#else
+ binver = "Unknown binary";
+#endif
+ printf("%s %s\n", "\nO2EM v" O2EM_VERSION " " RELEASE_DATE " - ", binver);
+ printf(
+ "Free Odyssey2 / Videopac+ Emulator - http://o2em.sourceforge.net\n");
+ printf("Created by Daniel Boris (c)1996/1998\n");
+ printf("Developed by:\n");
+ printf(" Andre de la Rocha since version 0.80\n");
+ printf(" Arlindo M. de Oliveira since version 1.16\n");
+ printf("\n");
+ app_data.debug = 0;
+ app_data.stick[0] = app_data.stick[1] = 1;
+ app_data.sticknumber[0] = app_data.sticknumber[1] = 0;
+ set_defjoykeys(0, 0);
+ set_defjoykeys(1, 1);
+ set_defsystemkeys();
+ app_data.bank = 0;
+ app_data.limit = 1;
+ app_data.sound_en = 1;
+ app_data.speed = 100;
+ app_data.wsize = 2;
+#ifdef ALLEGRO_DOS
+ app_data.fullscreen = 1;
+#else
+ app_data.fullscreen = 0;
+#endif
+ app_data.scanlines = 0;
+ app_data.voice = 1;
+ app_data.window_title = "O2EM v" O2EM_VERSION;
+ app_data.svolume = 100;
+ app_data.vvolume = 100;
+ app_data.filter = 0;
+ app_data.exrom = 0;
+ app_data.three_k = 0;
+ app_data.crc = 0;
+ app_data.scshot = scshot;
+ app_data.statefile = statefile;
+ app_data.euro = 0;
+ app_data.openb = 0;
+ app_data.vpp = 0;
+ app_data.bios = 0;
+ app_data.scoretype = 0;
+ app_data.scoreaddress = 0;
+ app_data.default_highscore = 0;
+ app_data.breakpoint = 65535;
+ app_data.megaxrom = 0;
+ strcpy(file, "");
+ strcpy(file_l, "");
+ strcpy(bios_l, "");
+ strcpy(bios, "");
+ strcpy(scshot, "");
+ strcpy(statefile, "");
+ strcpy(xrom, "");
+ strcpy(scorefile, "highscore.txt");
+ read_default_config();
+ if (argc >= 2) {
+ for (i = 1; i < argc; i++) {
+ if (argv[i][0] != '-') {
+ strncat(file, argv[i], MAXC - 1);
+ file[MAXC - 1] = 0;
+ strcpy(file_v, file);
+ } else {
+ p = strtok(argv[i], "=");
+ if (p) {
+ strncpy(attr, p + 1, MAXC - 1);
+ attr[MAXC - 1] = 0;
+ } else {
+ strcpy(attr, "");
+ }
+ p = strtok(NULL, "=");
+ if (p) {
+ strncpy(val, p, MAXC - 1);
+ val[MAXC - 1] = 0;
+ if (!strcmp(attr, "romdir") || !strcmp(attr, "ROMDIR")) {
+ strcpy(romdir, val);
+ strcat(romdir, file);
+ strcpy(file, romdir);
+ strcpy(romdir, val);
+ }
+ if (!strcmp(attr, "biosdir") || !strcmp(attr, "BIOSDIR")) {
+ strcpy(biosdir, val);
+ }
+ } else {
+ strcpy(val, "");
+ }
+ strlwr(attr);
+ if (!parse_option(attr, val)) {
+ exit(EXIT_FAILURE);
+ }
+ }
+ }
+ if (helpflag) {
+ helpus();
+ }
+ if (strlen(file) == 0) {
+ fprintf(stderr, "Error: file name missing\n");
+ exit(EXIT_FAILURE);
+ }
+ printf("Starting emulation ...\n");
+ allegro_init ();
+ install_timer();
+ init_audio();
+ printf("Using Allegro %s\n", allegro_id);
+ /********************** ROMs if Launcher running... */
+ k = strchr(romdir, '/');
+ launcher_flag_r = strchr(file, '\\');
+ if (k != 0) {
+ strcpy(xrom, romdir);
+ } else if (!launcher_flag_r) {
+ strcpy(xrom, "roms/");
+ strcpy(romdir, file);
+ strcpy(file, xrom);
+ strcat(file, romdir);
+ strcpy(romdir, xrom);
+ } else {
+ cnt = 0;
+ cnt2 = 0;
+ for (cnt = 0; file[cnt] != '\0'; cnt = cnt + 1) {
+ if (file[cnt] == '\\') {
+ cnt2 = cnt;
+ }
+ }
+ for (cnt = 0; cnt <= cnt2; cnt++) {
+ file_l[cnt] = file[cnt];
+ }
+ strcpy(romdir, file_l);
+ strcpy(xrom, romdir);
+ }
+ file_name(xrom);
+ if (contax < 3) {
+ printf("\nROMs directory empty!\n");
+ exit(EXIT_FAILURE);
+ }
+ app_data.crc = crc32_file(file);
+ crcx = app_data.crc;
+ suck_roms();
+ launcher_flag_b = strchr(bios, '\\');
+
+ if (!launcher_flag_b) {
+ k = strchr(biosdir, '/');
+ if (k != 0) {
+ strcpy(xbios, biosdir);
+ } else {
+ strcpy(xbios, "bios/");
+ strcpy(biosdir, xbios);
+ }
+ file_name(xbios);
+ if (contax < 3) {
+ printf("\nBIOS directory empty!\n");
+ exit(EXIT_FAILURE);
+ }
+ suck_bios();
+ c_j = strcmp(bios, "jopac");
+ if ((rom_f != 1) && (c_j != 0)) {
+ strcpy(bios, g7400);
+ }
+ if ((!o2flag) && (!jopflag) && (!c52flag) && (!g74flag)) {
+ printf("\ndir '%s' without BIOS !\n", biosdir);
+ exit(EXIT_FAILURE);
+ }
+ printf("BIOS found:\n");
+ if (!strcmp(bios, "g7400")) {
+ strcpy(bios, g7400);
+ if (g74flag != 1) {
+ printf("\nG7400 BIOS not found !\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+ if (g74flag)
+ printf(" G7400 VP+\n");
+ if (!strcmp(bios, "c52")) {
+ strcpy(bios, c52);
+ if (c52flag != 1) {
+ printf("\nC52 BIOS not found !\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+ if (c52flag)
+ printf(" C52\n");
+ if (!strcmp(bios, "jopac")) {
+ strcpy(bios, jopac);
+ if (jopflag != 1) {
+ printf("\nJOPAC BIOS not found !\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+ if (jopflag)
+ printf(" JOPAC VP+\n");
+ if ((!strcmp(bios, "")) || (!strcmp(bios, "o2rom"))) {
+ strcpy(bios, odyssey2);
+ if ((!o2flag) && (!c52flag) && (rom_f)) {
+ printf("Odyssey2 BIOS not found !\n");
+ exit(EXIT_FAILURE);
+ }
+ if ((!o2flag) && (c52flag) && (rom_f)) {
+ printf("\nOdyssey2 BIOS not found !\n");
+ printf("Loading C52 BIOS ... ");
+ strcpy(bios, c52);
+ }
+ }
+ if (o2flag)
+ printf(" Odyssey 2\n");
+ }
+ if (launcher_flag_b) {
+ identify_bios(bios);
+ if (rom_f != 1) {
+ if (!((g74flag) || (jopflag))) {
+ fprintf(stderr, "\nError: ROM only VP+ BIOS");
+ exit(EXIT_FAILURE);
+ }
+ }
+ } else {
+ if (rom_f != 1) {
+ if (!((g74flag) || (jopflag))) {
+ printf("\nROM only VP+ BIOS\n");
+ exit(EXIT_FAILURE);
+ }
+ if (!(g74flag)) {
+ printf("\nVP+ G7400 BIOS not found !");
+ printf("\nLoading VP+ Jopac BIOS ...");
+ strcpy(bios, jopac);
+ }
+ }
+ }
+ load_bios(bios);
+ load_cart(file);
+ if (app_data.voice)
+ load_voice_samples(path);
+ init_display();
+ init_cpu();
+ init_system();
+ set_score(app_data.scoretype, app_data.scoreaddress, app_data.default_highscore);
+ int stateError;
+ if ((stateError = loadstate(app_data.statefile)) == 0) {
+ printf("Savefile loaded.");
+ } else if (stateError >= 199) {
+ if (stateError == 199)
+ fprintf(stderr, "Wrong ROM-File for Savefile.");
+ else if (stateError == 200 + ROM_O2)
+ fprintf(stderr, "Wrong BIOS for Savefile: O2ROM needed.");
+ else if (stateError == 200 + ROM_G7400)
+ fprintf(stderr, "Wrong BIOS for Savefile: G7400 ROM needed.");
+ else if (stateError == 200 + ROM_C52)
+ fprintf(stderr, "Wrong BIOS for Savefile: C52 ROM needed.");
+ else if (stateError == 200 + ROM_JOPAC)
+ fprintf(stderr, "Wrong BIOS for Savefile: JOPAC ROM needed.");
+ else
+ fprintf(stderr, "Wrong BIOS for Savefile: UNKNOWN ROM needed.");
+ return (0);
+ }
+ if (app_data.debug)
+ key_debug = 1;
+#ifndef _DEBUG
+#ifdef ALLEGRO_WINDOWS
+ FreeConsole ();
+#endif
+#endif
+ run();
+ if (app_data.scoretype != 0)
+ save_highscore(get_score(app_data.scoretype, app_data.scoreaddress),
+ scorefile);
+ exit(EXIT_SUCCESS);
+ }
+ if (!strcmp(attr, "help") || !strcmp(attr, "HELP"))
+ helpus();
+ printf("type o2em -help\n");
+ exit(EXIT_SUCCESS);
+}
+
+END_OF_MAIN ();
+
+int parse_option(char *attr, char *val)
+{
+ int control_scheme;
+ if (!strcmp(attr, "nolimit")) {
+ app_data.limit = !(val[0] != '0');
+ } else if (!strcmp(attr, "nosound")) {
+ app_data.sound_en = !(val[0] != '0');
+ } else if (!strcmp(attr, "novoice")) {
+ app_data.voice = !(val[0] != '0');
+ } else if (!strcmp(attr, "filter")) {
+ app_data.filter = (val[0] != '0');
+ } else if (!strcmp(attr, "debug")) {
+ app_data.debug = (val[0] != '0');
+ } else if ((!strcmp(attr, "s1")) || (!strcmp(attr, "s2"))) {
+ int stick_number;
+ stick_number = (!strcmp(attr, "s1")) ? 0 : 1;
+ if (strlen(val) < 2) {
+ control_scheme = -1;
+ sscanf(val, "%d", &control_scheme);
+ if ((control_scheme >= 0) && (control_scheme <= 3)) {
+ if ((control_scheme == 1) || (control_scheme == 2)) {
+ app_data.stick[stick_number] = 1;
+ set_defjoykeys(stick_number, control_scheme - 1);
+ } else {
+ app_data.stick[stick_number] = (control_scheme == 0) ? 0 : 2;
+ if (control_scheme == 3) {
+ app_data.sticknumber[stick_number] = app_data.sticknumber[0]
+ + app_data.sticknumber[1] + 1;
+ }
+ set_joykeys(stick_number, 0, 0, 0, 0, 0);
+ }
+ } else {
+ fprintf(stderr, "Invalid value for option %s\n", attr);
+ return 0;
+ }
+ } else {
+ char *p, *s;
+ int i, k, code, nk, codes[5];
+ strupr(val);
+ nk = 0;
+ p = strtok(val, ",");
+ while (p) {
+ i = code = 0;
+ k = keybtab[i].keybcode;
+ s = keybtab[i].keybname;
+ while (k && (code == 0)) {
+ if (strcmp(s, p) == 0)
+ code = k;
+ i++;
+ k = keybtab[i].keybcode;
+ s = keybtab[i].keybname;
+ }
+ if (!code) {
+ fprintf(stderr,
+ "Invalid value for option %s : key %s unknown\n",
+ attr, p);
+ return 0;
+ }
+ codes[nk] = code;
+ p = strtok(NULL, ",");
+ nk++;
+ if (nk > 5) {
+ fprintf(
+ stderr,
+ "Invalid value for option %s : invalid number of keys\n",
+ attr);
+ return 0;
+ }
+ }
+ if (nk != 5) {
+ fprintf(
+ stderr,
+ "Invalid value for option %s : invalid number of keys\n",
+ attr);
+ return 0;
+ }
+ app_data.stick[stick_number] = 1;
+ set_joykeys(stick_number, codes[0], codes[1], codes[2], codes[3], codes[4]);
+ }
+ } else if (!strcmp(attr, "s0")) {
+ char *p, *s;
+ int i, k, code, nk, codes[8];
+ strupr(val);
+ nk = 0;
+ p = strtok(val, ",");
+ while (p) {
+ i = code = 0;
+ k = keybtab[i].keybcode;
+ s = keybtab[i].keybname;
+ while (k && (code == 0)) {
+ if (strcmp(s, p) == 0)
+ code = k;
+ i++;
+ k = keybtab[i].keybcode;
+ s = keybtab[i].keybname;
+ }
+ if (!code) {
+ fprintf(stderr,
+ "Invalid value for option %s : key %s unknown\n", attr,
+ p);
+ return 0;
+ }
+ codes[nk] = code;
+ p = strtok(NULL, ",");
+ nk++;
+ if (nk > 8) {
+ fprintf(
+ stderr,
+ "Invalid value for option %s : invalid number of keys\n",
+ attr);
+ return 0;
+ }
+ }
+ if (nk != 8) {
+ fprintf(stderr,
+ "Invalid value for option %s : invalid number of keys\n",
+ attr);
+ return 0;
+ }
+ set_systemkeys(codes[0], codes[1], codes[2], codes[3], codes[4],
+ codes[5], codes[6], codes[7]);
+ } else if (!strcmp(attr, "speed")) {
+ control_scheme = -1;
+ sscanf(val, "%d", &control_scheme);
+ if ((control_scheme > 0) && (control_scheme <= 10000))
+ app_data.speed = control_scheme;
+ else {
+ fprintf(stderr, "Invalid value for option %s\n", attr);
+ return 0;
+ }
+ } else if (!strcmp(attr, "svolume")) {
+ control_scheme = -1;
+ sscanf(val, "%d", &control_scheme);
+ if ((control_scheme >= 0) && (control_scheme <= 100))
+ app_data.svolume = control_scheme;
+ else {
+ fprintf(stderr, "Invalid value for option %s\n", attr);
+ return 0;
+ }
+ if (control_scheme == 0)
+ app_data.sound_en = 0;
+ } else if (!strcmp(attr, "vvolume")) {
+ control_scheme = -1;
+ sscanf(val, "%d", &control_scheme);
+ if ((control_scheme >= 0) && (control_scheme <= 100))
+ app_data.vvolume = control_scheme;
+ else {
+ fprintf(stderr, "Invalid value for option %s\n", attr);
+ return 0;
+ }
+ if (control_scheme == 0)
+ app_data.voice = 0;
+ } else if (!strcmp(attr, "wsize")) {
+ control_scheme = -1;
+ sscanf(val, "%d", &control_scheme);
+ if ((control_scheme > 0) && (control_scheme < 5)) {
+ app_data.wsize = control_scheme;
+ app_data.fullscreen = 0;
+ } else {
+ fprintf(stderr, "Invalid value for option %s\n", attr);
+ return 0;
+ }
+ } else if (!strcmp(attr, "fullscreen")) {
+ app_data.fullscreen = (val[0] != '0');
+ } else if (!strcmp(attr, "scanlines")) {
+ app_data.scanlines = (val[0] != '0');
+ } else if (!strcmp(attr, "scshot")) {
+ strcpy(scshot, val);
+ } else if (!strcmp(attr, "savefile")) {
+ strcpy(statefile, val);
+ } else if (!strcmp(attr, "biosdir")) {
+ strcpy(xbios, val);
+ } else if (!strcmp(attr, "bios")) {
+ strcpy(bios, val);
+ } else if (!strcmp(attr, "romdir")) {
+ strcpy(xrom, val);
+ } else if (!strcmp(attr, "help")) {
+ helpflag = 1;
+ } else if (!strcmp(attr, "euro")) {
+ app_data.euro = (val[0] != '0');
+ } else if (!strcmp(attr, "exrom")) {
+ app_data.exrom = (val[0] != '0');
+ } else if (!strcmp(attr, "3k")) {
+ app_data.three_k = (val[0] != '0');
+ } else if (!strcmp(attr, "g7400")) {
+ strcpy(bios, "g7400");
+ } else if (!strcmp(attr, "c52")) {
+ strcpy(bios, "c52");
+ } else if (!strcmp(attr, "jopac")) {
+ strcpy(bios, "jopac");
+ } else if (!strcmp(attr, "o2rom")) {
+ strcpy(bios, "o2rom");
+ } else if (!strcmp(attr, "scorefile")) {
+ strcpy(scorefile, val);
+ } else if (!strcmp(attr, "scoreadr")) {
+ control_scheme = -1;
+ sscanf(val, "%d", &control_scheme);
+ if ((control_scheme >= 0) && (control_scheme <= 255))
+ app_data.scoreaddress = control_scheme;
+ else {
+ fprintf(stderr, "Invalid value for option %s\n", attr);
+ return 0;
+ }
+ } else if (!strcmp(attr, "scoretype")) {
+ control_scheme = -1;
+ sscanf(val, "%d", &control_scheme);
+ if ((control_scheme >= 0) && (control_scheme <= 9999))
+ app_data.scoretype = control_scheme;
+ else {
+ fprintf(stderr, "Invalid value for option %s\n", attr);
+ return 0;
+ }
+ } else if (!strcmp(attr, "score")) {
+ control_scheme = -1;
+ sscanf(val, "%d", &control_scheme);
+ if ((control_scheme >= 0) && (control_scheme <= 999999))
+ app_data.default_highscore = control_scheme;
+ else {
+ fprintf(stderr, "Invalid value for option %s\n", attr);
+ return 0;
+ }
+ } else {
+ if (!helpflag) {
+ fprintf(stderr, "Invalid option : %s\n", attr);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+void read_default_config(void)
+{
+ FILE *f;
+ static char attr[MAXC], val[MAXC], s[MAXC];
+ char *p, *fn;
+ int i, l;
+ fn = "o2em_def.cfg";
+ f = fopen(fn, "r");
+ if (!f) {
+ fn = "O2EM_DEF.CFG";
+ f = fopen(fn, "r");
+ }
+ if (!f)
+ return;
+
+ l = 0;
+ while (fgets(s, MAXC - 1, f)) {
+ l++;
+ p = s;
+ while (*p && (isspace (*p)))
+ p++;
+ if (*p && (*p != '#')) {
+ i = 0;
+ while (*p && (!isspace (*p)) && (*p != '='))
+ attr[i++] = *p++;
+ attr[i] = 0;
+ while (*p && (isspace (*p)))
+ p++;
+ i = 0;
+ if (*p == '=') {
+ p++;
+ while (*p && (isspace (*p)))
+ p++;
+ if (*p == '"') {
+ p++;
+ while (*p && (*p != '"') && (*p != '\n') && (*p != '\r'))
+ val[i++] = *p++;
+ } else {
+ while (*p && (!isspace (*p)))
+ val[i++] = *p++;
+ }
+ }
+ val[i] = 0;
+ if (strlen(attr) > 0) {
+ strlwr(attr);
+ if (!parse_option(attr, val)) {
+ printf("Error in the %s file at line number %d !\n\n", fn,
+ l);
+ }
+ }
+ }
+ }
+ fclose(f);
+}
+
+static long filesize(FILE * stream)
+{
+ long curpos, length;
+ curpos = ftell(stream);
+ fseek(stream, 0L, SEEK_END);
+ length = ftell(stream);
+ fseek(stream, curpos, SEEK_SET);
+ return length;
+}
+
+static void load_bios(const char *biosname)
+{
+ FILE *fn;
+ static char s[MAXC + 10];
+ unsigned long crc;
+ int i;
+
+ if ((biosname[strlen(biosname) - 1] == '/')
+ || (biosname[strlen(biosname) - 1] == '\\')
+ || (biosname[strlen(biosname) - 1] == ':')) {
+ strcpy(s, biosname);
+ strcat(s, odyssey2);
+ fn = fopen(s, "rb");
+
+ if (!fn) {
+ strcpy(s, biosname);
+ strcat(s, odyssey2);
+ fn = fopen(s, "rb");
+ }
+ } else {
+ strcpy(s, biosname);
+ fn = fopen(biosname, "rb");
+ }
+
+ if (!fn) {
+ fprintf(stderr, "Error loading bios ROM (%s)\n", s);
+ exit(EXIT_FAILURE);
+ }
+ if (fread(rom_table[0], 1024, 1, fn) != 1) {
+ fprintf(stderr, "Error loading bios ROM %s\n", odyssey2);
+ exit(EXIT_FAILURE);
+ }
+ strcpy(s, biosname);
+ fn = fopen(biosname, "rb");
+ if (!fn) {
+ fprintf(stderr, "Error loading bios ROM (%s)\n", s);
+ exit(EXIT_FAILURE);
+ }
+ if (fread(rom_table[0], 1024, 1, fn) != 1) {
+ fprintf(stderr, "Error loading bios ROM %s\n", odyssey2);
+ exit(EXIT_FAILURE);
+ }
+ fclose(fn);
+ for (i = 1; i < 8; i++) {
+ memcpy(rom_table[i], rom_table[0], 1024);
+ }
+ crc = crc32_buf(rom_table[0], 1024);
+ if (crc == 0x8016A315) {
+ printf("Odyssey2 bios ROM loaded\n");
+ app_data.vpp = 0;
+ app_data.bios = ROM_O2;
+ } else if (crc == 0xE20A9F41) {
+ printf("Videopac+ G7400 bios ROM loaded\n");
+ app_data.vpp = 1;
+ app_data.bios = ROM_G7400;
+ } else if (crc == 0xA318E8D6) {
+ if (!((!o2flag) && (c52flag)))
+ printf("C52 bios ROM loaded\n");
+ else
+ printf("Ok\n");
+ app_data.vpp = 0;
+ app_data.bios = ROM_C52;
+
+ } else if (crc == 0x11647CA5) {
+ if (g74flag)
+ printf("Jopac bios ROM loaded\n");
+ else
+ printf(" Ok\n");
+ app_data.vpp = 1;
+ app_data.bios = ROM_JOPAC;
+ } else {
+ printf("Bios ROM loaded (unknown version)\n");
+ app_data.vpp = 0;
+ app_data.bios = ROM_UNKNOWN;
+ }
+}
+
+static void load_cart(char *file)
+{
+ FILE *fn;
+ long l;
+ int i, nb;
+ app_data.crc = crc32_file(file);
+ if (app_data.crc == 0xAFB23F89)
+ app_data.exrom = 1; /* Musician */
+ if (app_data.crc == 0x3BFEF56B)
+ app_data.exrom = 1; /* Four in 1 Row! */
+ if (app_data.crc == 0x9B5E9356)
+ app_data.exrom = 1; /* Four in 1 Row! (french) */
+
+ if (((app_data.crc == 0x975AB8DA) || (app_data.crc == 0xE246A812))
+ && (!app_data.debug)) {
+ fprintf(stderr, "Error: file %s is an incomplete ROM dump\n", file_v);
+ exit(EXIT_FAILURE);
+ }
+
+ fn = fopen(file, "rb");
+ if (!fn) {
+ fprintf(stderr, "Error loading %s\n", file_v);
+ exit(EXIT_FAILURE);
+ }
+ printf("Loading: \"%s\" Size: ", file_v);
+ l = filesize(fn);
+ if ((l % 1024) != 0) {
+ fprintf(stderr, "Error: file %s is an invalid ROM dump\n", file_v);
+ exit(EXIT_FAILURE);
+ }
+
+ /* special MegaCART design by Soeren Gust */
+ if ((l == 32768) || (l == 65536) || (l == 131072) || (l == 262144)
+ || (l == 524288) || (l == 1048576)) {
+ app_data.megaxrom = 1;
+ app_data.bank = 1;
+ megarom = malloc(1048576);
+ if (megarom == NULL) {
+ fprintf(stderr, "Out of memory loading %s\n", file);
+ exit(EXIT_FAILURE);
+ }
+ if (fread(megarom, l, 1, fn) != 1) {
+ fprintf(stderr, "Error loading %s\n", file);
+ exit(EXIT_FAILURE);
+ }
+
+ /* mirror shorter files into full megabyte */
+ if (l < 65536)
+ memcpy(megarom + 32768, megarom, 32768);
+ if (l < 131072)
+ memcpy(megarom + 65536, megarom, 65536);
+ if (l < 262144)
+ memcpy(megarom + 131072, megarom, 131072);
+ if (l < 524288)
+ memcpy(megarom + 262144, megarom, 262144);
+ if (l < 1048576)
+ memcpy(megarom + 524288, megarom, 524288);
+ /* start in bank 0xff */
+ memcpy(&rom_table[0][1024], megarom + 4096 * 255 + 1024, 3072);
+ printf("MegaCart %ldK", l / 1024);
+ nb = 1;
+ } else if (((l % 3072) == 0)) {
+ app_data.three_k = 1;
+ nb = l / 3072;
+
+ for (i = nb - 1; i >= 0; i--) {
+ if (fread(&rom_table[i][1024], 3072, 1, fn) != 1) {
+ fprintf(stderr, "Error loading %s\n", file);
+ exit(EXIT_FAILURE);
+ }
+ }
+ printf("%dK", nb * 3);
+ } else {
+ nb = l / 2048;
+ if ((nb == 2) && (app_data.exrom)) {
+ if (fread(&extROM[0], 1024, 1, fn) != 1) {
+ fprintf(stderr, "Error loading %s\n", file);
+ exit(EXIT_FAILURE);
+ }
+ if (fread(&rom_table[0][1024], 3072, 1, fn) != 1) {
+ fprintf(stderr, "Error loading %s\n", file);
+ exit(EXIT_FAILURE);
+ }
+ printf("3K EXROM");
+ } else {
+ for (i = nb - 1; i >= 0; i--) {
+ if (fread(&rom_table[i][1024], 2048, 1, fn) != 1) {
+ fprintf(stderr, "Error loading %s\n", file);
+ exit(EXIT_FAILURE);
+ }
+ memcpy(&rom_table[i][3072], &rom_table[i][2048], 1024); /* simulate missing A10 */
+ }
+ printf("%dK", nb * 2);
+ }
+ }
+ fclose(fn);
+ rom = rom_table[0];
+ if (nb == 1)
+ app_data.bank = 1;
+ else if (nb == 2)
+ app_data.bank = app_data.exrom ? 1 : 2;
+ else if (nb == 4)
+ app_data.bank = 3;
+ else
+ app_data.bank = 4;
+
+ if ((rom_table[nb - 1][1024 + 12] == 'O')
+ && (rom_table[nb - 1][1024 + 13] == 'P')
+ && (rom_table[nb - 1][1024 + 14] == 'N')
+ && (rom_table[nb - 1][1024 + 15] == 'B'))
+ app_data.openb = 1;
+
+ printf(" CRC: %08lX\n", app_data.crc);
+}
+
+/*************************** Helpus*/
+void helpus(void)
+{
+ allegro_init ();
+ install_timer();
+ init_display();
+ init_system();
+#ifdef ALLEGRO_WINDOWS
+ FreeConsole ();
+#endif
+ help();
+ exit(EXIT_SUCCESS);
+}
+
+int file_name(char *pathx)
+{
+ DIR *dir_p;
+ struct dirent *dir_entry_p;
+ contax = 0;
+ dir_p = opendir(pathx);
+ if (dir_p == NULL) {
+ fprintf(stderr, "dir '%s' not found !\n", pathx);
+ exit(-1);
+ }
+ while (0 != (dir_entry_p = readdir(dir_p))) {
+ strcpy(arkivo[contax], dir_entry_p->d_name);
+ contax++;
+ }
+ closedir(dir_p);
+ return (0);
+}
+
+/********************* Search BIOS */
+int suck_bios()
+{
+ int i;
+ for (i = 0; i < contax; ++i) {
+ strcpy(biossux, biosdir);
+ strcat(biossux, arkivo[i]);
+ identify_bios(biossux);
+ }
+ return (0);
+}
+
+/********************* Search ROM */
+int suck_roms()
+{
+ int i;
+ rom_f = 1;
+ for (i = 0; i < contax; ++i) {
+ strcpy(romssux, romdir);
+ strcat(romssux, arkivo[i]);
+ app_data.crc = crc32_file(romssux);
+ if (app_data.crc == crcx) {
+ if ((app_data.crc == 0xD7089068) || (app_data.crc == 0xB0A7D723)
+ || (app_data.crc == 0x0CA26992)
+ || (app_data.crc == 0x0B6EB25B)
+ || (app_data.crc == 0x06861A9C)
+ || (app_data.crc == 0xB2F0F0B4)
+ || (app_data.crc == 0x68560DC7)
+ || (app_data.crc == 0x0D2D721D)
+ || (app_data.crc == 0xC4134DF8)
+ || (app_data.crc == 0xA75C42F8)) {
+ rom_f = 0;
+ }
+ }
+ }
+ return 0;
+}
+
+/********************* Ready BIOS */
+int identify_bios(char *biossux)
+{
+ app_data.crc = crc32_file(biossux);
+ if (app_data.crc == 0x8016A315) {
+ strcpy(odyssey2, biossux);
+ o2flag = 1;
+ }
+ if (app_data.crc == 0xE20A9F41) {
+ strcpy(g7400, biossux);
+ g74flag = 1;
+ }
+ if (app_data.crc == 0xA318E8D6) {
+ strcpy(c52, biossux);
+ c52flag = 1;
+ }
+ if (app_data.crc == 0x11647CA5) {
+ strcpy(jopac, biossux);
+ jopflag = 1;
+ }
+ return (0);
+}
diff --git a/clean/src/o2em.png b/clean/src/o2em.png
new file mode 100755
index 0000000..1febae9
Binary files /dev/null and b/clean/src/o2em.png differ
diff --git a/clean/src/o2em.rc b/clean/src/o2em.rc
new file mode 100755
index 0000000..8960011
--- /dev/null
+++ b/clean/src/o2em.rc
@@ -0,0 +1,3 @@
+#include
+
+allegro_icon ICON DISCARDABLE "o2em.ico"
diff --git a/clean/src/o2em.res b/clean/src/o2em.res
new file mode 100755
index 0000000..6c5d4e1
Binary files /dev/null and b/clean/src/o2em.res differ
diff --git a/clean/src/score.c b/clean/src/score.c
new file mode 100755
index 0000000..317420d
--- /dev/null
+++ b/clean/src/score.c
@@ -0,0 +1,144 @@
+
+/*
+ * O2EM Free Odyssey2 / Videopac+ Emulator
+ *
+ * Created by Daniel Boris (c) 1997,1998
+ *
+ * Developed by Andre de la Rocha
+ *
+ * http://o2em.sourceforge.net
+ *
+ *
+ *
+ * Score loading/saving by manopac
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "vmachine.h"
+#include "types.h"
+#include "score.h"
+
+/*--------------------------------------------------
+ Calculate Score from given Values
+ Scoretype = abcd:
+ ramtype a = 1: ext ram / 2: int ram
+ valuetype b = 1: 1 Byte each Digit / 2: 1/2 Byte each Digit
+ directíon c = 1: higher value digits first / 2: low value digits first
+ count d = number of digits
+ --------------------------------------------------*/
+int get_score(int scoretype, int scoreaddress)
+{
+ int score=0;
+
+ if (scoretype!=0)
+ {
+ int position;
+ int i;
+ Byte *RAM;
+
+ int count = scoretype%10;
+ int direction = ((scoretype/10)%10)==1?1:-1;
+ float valuetype = (float) (3-((scoretype/100)%10))/2;
+ int ramtype = scoretype/1000;
+
+ position = scoreaddress+ (direction==1?0:(count*valuetype-1));
+ RAM = ramtype==1?extRAM:intRAM;
+
+ for(i=0;i>(((i+1)%2)*4)*(abs((int) ((valuetype-1)*2))))&15);
+ }
+ }
+
+ return(score);
+}
+
+/*--------------------------------------------------
+ Set HighScore into Memory
+ Scoretype = abcd:
+ ramtype a = 1: ext ram / 2: int ram
+ valuetype b = 1: 1 Byte each Digit / 2: 1/2 Byte each Digit
+ directíon c = 1: higher value digits first / 2: low value digits first
+ count d = number of digits
+ --------------------------------------------------*/
+
+void set_score(int scoretype, int scoreaddress, int score)
+{
+
+ if (scoretype!=0 && score>0)
+ {
+ int position;
+ int i;
+ Byte *RAM;
+ int digit;
+
+ int count = scoretype%10;
+ int direction = ((scoretype/10)%10)==1?-1:1;
+ float valuetype = (float) (3-((scoretype/100)%10))/2;
+ int ramtype = scoretype/1000;
+
+ position = scoreaddress+ (direction==1?0:(count*valuetype-1));
+ RAM = ramtype==1?extRAM:intRAM;
+
+ for(i=count-1;i>=0;i--)
+ {
+ digit = score / power(10,i);
+ RAM[position+(int)(valuetype*i*direction)]=((valuetype==0.5)&&(i%2==0))?(RAM[position+(int)(valuetype*i*direction)]<<4)+digit:digit;
+ score = score - digit*power(10,i);
+ }
+ }
+}
+
+
+
+/*-----------------------------------------------------
+ Save Highscore to File
+-------------------------------------------------------*/
+void save_highscore(int highscore,char *scorefile)
+{
+ FILE *fn;
+
+ highscore = highscore==app_data.default_highscore?0:highscore;
+
+ fn = fopen(scorefile,"w");
+ if (fn==NULL) {
+ fprintf(stderr,"Error opening highscore-file %s: %i\n",scorefile,errno);
+ exit(EXIT_FAILURE);
+ }
+
+ if (fprintf(fn,"%i",highscore)<=0)
+ {
+ fprintf(stderr,"Error writing to highscore-file %s: %i\n",scorefile,errno);
+ exit(EXIT_FAILURE);
+ }
+
+ fclose(fn);
+}
+
+
+/***********************************
+ Integer-Implementation of pow
+ ***********************************/
+int power(int base, int higher)
+{
+ if (higher==0) {
+ return(1);
+ } else if (higher==1) {
+ return(base);
+ } else {
+ int i;
+ int value=base;
+
+ for (i=2;i<=higher;i++)
+ {
+ value = value*base;
+ }
+ return(value);
+ }
+}
diff --git a/clean/src/score.h b/clean/src/score.h
new file mode 100755
index 0000000..0868801
--- /dev/null
+++ b/clean/src/score.h
@@ -0,0 +1,10 @@
+#ifndef __SCORE_H
+#define __SCORE_H
+
+int get_score(int scoretype, int scoreaddress);
+void set_score(int scoretype, int scoreaddress, int highscore);
+void save_highscore(int highscore,char *scorefile);
+int power(int base, int higher);
+
+#endif
+
diff --git a/clean/src/table.c b/clean/src/table.c
new file mode 100755
index 0000000..49169b4
--- /dev/null
+++ b/clean/src/table.c
@@ -0,0 +1,341 @@
+
+/*
+ * O2EM Free Odyssey2 / Videopac+ Emulator
+ *
+ * Created by Daniel Boris (c) 1997,1998
+ *
+ * Developed by Andre de la Rocha
+ * Arlindo M. de Oliveira
+ *
+ * http://o2em.sourceforge.net
+ *
+ *
+ *
+ * 8048 Mnemonics
+ */
+
+
+#include "cpu.h"
+#include "table.h"
+
+
+struct lookup_tag lookup[] = {
+
+ /* 00 */ {"NOP",1,0},
+ /* 01 */ {"ILL",1,0},
+ /* 02 */ {"OUTL BUS,A",1,0},
+ /* 03 */ {"ADD A,",2,1},
+
+ /* 04 */ {"JMP",2,2},
+ /* 05 */ {"EN I",1,0},
+ /* 06 */ {"ILL",1,0},
+ /* 07 */ {"DEC A",1,0},
+
+ /* 08 */ {"INS A,BUS",1,0},
+ /* 09 */ {"IN A,P1",1,0},
+ /* 0A */ {"IN A,P2",1,0},
+ /* 0B */ {"ILL",1,0},
+
+ /* 0C */ {"MOVD A,P4",1,0},
+ /* 0D */ {"MOVD A,P5",1,0},
+ /* 0E */ {"MOVD A,P6",1,0},
+ /* 0F */ {"MOVD A,P7",1,0},
+
+ /* 10 */ {"INC @R0",1,0},
+ /* 11 */ {"INC @R1",1,0},
+ /* 12 */ {"JB0",2,3},
+ /* 13 */ {"ADDC A,",2,1},
+
+ /* 14 */ {"CALL",2,2},
+ /* 15 */ {"DIS I",1,0},
+ /* 16 */ {"JTF",2,3},
+ /* 17 */ {"INC A",1,0},
+
+ /* 18 */ {"INC R0",1,0},
+ /* 19 */ {"INC R1",1,0},
+ /* 1A */ {"INC R2",1,0},
+ /* 1B */ {"INC R3",1,0},
+
+ /* 1C */ {"INC R4",1,0},
+ /* 1D */ {"INC R5",1,0},
+ /* 1E */ {"INC R6",1,0},
+ /* 1F */ {"INC R7",1,0},
+
+ /* 20 */ {"XCH A,@R0",1,0},
+ /* 21 */ {"XCH A,@R1",1,0},
+ /* 22 */ {"ILL",1,0},
+ /* 23 */ {"MOV A,",2,1},
+
+ /* 24 */ {"JMP",2,2},
+ /* 25 */ {"EN TCNTI",1,0},
+ /* 26 */ {"JNT0",2,3},
+ /* 27 */ {"CLR A",1,0},
+
+ /* 28 */ {"XCH A,R0",1,0},
+ /* 29 */ {"XCH A,R1",1,0},
+ /* 2A */ {"XCH A,R2",1,0},
+ /* 2B */ {"XCH A,R3",1,0},
+
+ /* 2C */ {"XCH A,R4",1,0},
+ /* 2D */ {"XCH A,R5",1,0},
+ /* 2E */ {"XCH A,R6",1,0},
+ /* 2F */ {"XCH A,R7",1,0},
+
+ /* 30 */ {"XCHD A,@R0",1,0},
+ /* 31 */ {"XCHD A,@R1",1,0},
+ /* 32 */ {"JB1",2,3},
+ /* 33 */ {"ILL",1,0},
+
+ /* 34 */ {"CALL",2,2},
+ /* 35 */ {"DIS TCNTI",1,0},
+ /* 36 */ {"JT0",2,3},
+ /* 37 */ {"CPL A",1,0},
+
+ /* 38 */ {"ILL",1,0},
+ /* 39 */ {"OUTL P1,A",1,0},
+ /* 3A */ {"OUTL P2,A",1,0},
+ /* 3B */ {"ILL",1,0},
+
+ /* 3C */ {"MOVD P4,A",1,0},
+ /* 3D */ {"MOVD P5,A",1,0},
+ /* 3E */ {"MOVD P6,A",1,0},
+ /* 3F */ {"MOVD P7,A",1,0},
+
+ /* 40 */ {"ORL A,@R0",1,0},
+ /* 41 */ {"ORL A,@R1",1,0},
+ /* 42 */ {"MOV A,T",1,0},
+ /* 43 */ {"ORL A,",2,1},
+
+ /* 44 */ {"JMP",2,2},
+ /* 45 */ {"STRT CNT",1,0},
+ /* 46 */ {"JNT1",2,3},
+ /* 47 */ {"SWAP",1,0},
+
+ /* 48 */ {"ORL A,R0",1,0},
+ /* 49 */ {"ORL A,R1",1,0},
+ /* 4A */ {"ORL A,R2",1,0},
+ /* 4B */ {"ORL A,R3",1,0},
+
+ /* 4C */ {"ORL A,R4",1,0},
+ /* 4D */ {"ORL A,R5",1,0},
+ /* 4E */ {"ORL A,R6",1,0},
+ /* 4F */ {"ORL A,R7",1,0},
+
+ /* 50 */ {"ANL A,@R0",1,0},
+ /* 51 */ {"ANL A,@R1",1,0},
+ /* 52 */ {"JB2",2,3},
+ /* 53 */ {"ANL A,",2,1},
+
+ /* 54 */ {"CALL",2,2},
+ /* 55 */ {"STRT T",1,0},
+ /* 56 */ {"JT1",2,3},
+ /* 57 */ {"ILL",1,0},
+
+ /* 58 */ {"ANL A,R0",1,0},
+ /* 59 */ {"ANL A,R1",1,0},
+ /* 5A */ {"ANL A,R2",1,0},
+ /* 5B */ {"ANL A,R3",1,0},
+
+ /* 5C */ {"ANL A,R4",1,0},
+ /* 5D */ {"ANL A,R5",1,0},
+ /* 5E */ {"ANL A,R6",1,0},
+ /* 5F */ {"ANL A,R7",1,0},
+
+ /* 60 */ {"ADD A,@R0",1,0},
+ /* 61 */ {"ADD A,@R1",1,0},
+ /* 62 */ {"MOV T,A",1,0},
+ /* 63 */ {"ILL",1,0},
+
+ /* 64 */ {"JMP",2,2},
+ /* 65 */ {"STOP TCNT",1,0},
+ /* 66 */ {"ILL",1,0},
+ /* 67 */ {"RRC A",1,0},
+
+ /* 68 */ {"ADD A,R0",1,0},
+ /* 69 */ {"ADD A,R1",1,0},
+ /* 6A */ {"ADD A,R2",1,0},
+ /* 6B */ {"ADD A,R3",1,0},
+
+ /* 6C */ {"ADD A,R4",1,0},
+ /* 6D */ {"ADD A,R5",1,0},
+ /* 6E */ {"ADD A,R6",1,0},
+ /* 6F */ {"ADD A,R7",1,0},
+
+ /* 70 */ {"ADDC A,@R0",1,0},
+ /* 71 */ {"ADDC A,@R1",1,0},
+ /* 72 */ {"JB3",2,3},
+ /* 73 */ {"ILL",1,0},
+
+ /* 74 */ {"CALL",2,2},
+ /* 75 */ {"ENT0 CLK",1,0},
+ /* 76 */ {"JF1",2,3},
+ /* 77 */ {"RR A",1,0},
+
+ /* 78 */ {"ADDC A,R0",1,0},
+ /* 79 */ {"ADDC A,R1",1,0},
+ /* 7A */ {"ADDC A,R2",1,0},
+ /* 7B */ {"ADDC A,R3",1,0},
+
+ /* 7C */ {"ADDC A,R4",1,0},
+ /* 7D */ {"ADDC A,R5",1,0},
+ /* 7E */ {"ADDC A,R6",1,0},
+ /* 7F */ {"ADDC A,R7",1,0},
+
+ /* 80 */ {"MOVX A,@R0",1,0},
+ /* 81 */ {"MOVX A,@R1",1,0},
+ /* 82 */ {"ILL",1,0},
+ /* 83 */ {"RET",1,0},
+
+ /* 84 */ {"JMP",2,2},
+ /* 85 */ {"CLR F0",1,0},
+ /* 86 */ {"JNI",2,3},
+ /* 87 */ {"ILL",1,0},
+
+ /* 88 */ {"ORL BUS,",2,1},
+ /* 89 */ {"ORL P1,",2,1},
+ /* 8A */ {"ORL P2,",2,1},
+ /* 8B */ {"ILL",1,0},
+
+ /* 8C */ {"ORLD P4,A",1,0},
+ /* 8D */ {"ORLD P5,A",1,0},
+ /* 8E */ {"ORLD P6,A",1,0},
+ /* 8F */ {"ORLD P7,A",1,0},
+
+ /* 90 */ {"MOVX @R0,A",1,0},
+ /* 91 */ {"MOVX @R1,A",1,0},
+ /* 92 */ {"JB4",2,3},
+ /* 93 */ {"RETR",1,0},
+
+ /* 94 */ {"CALL",2,2},
+ /* 95 */ {"CPL F0",1,0},
+ /* 96 */ {"JNZ",2,3},
+ /* 97 */ {"CLR C",1,0},
+
+ /* 98 */ {"ANL BUS,",2,1},
+ /* 99 */ {"ANL P1,",2,1},
+ /* 9A */ {"ANL P2,",2,1},
+ /* 9B */ {"ILL",1,0},
+
+ /* 9C */ {"ANLD P4,A",1,0},
+ /* 9D */ {"ANLD P5,A",1,0},
+ /* 9E */ {"ANLD P6,A",1,0},
+ /* 9F */ {"ANLD P7,A",1,0},
+
+ /* A0 */ {"MOV @R0,A",1,0},
+ /* A1 */ {"MOV @R1,A",1,0},
+ /* A2 */ {"ILL",1,0},
+ /* A3 */ {"MOVP A,@A",1,0},
+
+ /* A4 */ {"JMP",2,2},
+ /* A5 */ {"CLR F1",1,0},
+ /* A6 */ {"ILL",1,0},
+ /* A7 */ {"CPL C",1,0},
+
+ /* A8 */ {"MOV R0,A",1,0},
+ /* A9 */ {"MOV R1,A",1,0},
+ /* AA */ {"MOV R2,A",1,0},
+ /* AB */ {"MOV R3,A",1,0},
+ /* AC */ {"MOV R4,A",1,0},
+ /* AD */ {"MOV R5,A",1,0},
+ /* AE */ {"MOV R6,A",1,0},
+ /* AF */ {"MOV R7,A",1,0},
+
+ /* B0 */ {"MOV @R0,",2,1},
+ /* B1 */ {"MOV @R1,",2,1},
+ /* B2 */ {"JB5",2,3},
+ /* B3 */ {"JMPP @A",1,0},
+
+ /* B4 */ {"CALL",2,2},
+ /* B5 */ {"CPL F1",1,0},
+ /* B6 */ {"JF0",2,3},
+ /* B7 */ {"ILL",1,0},
+
+ /* B8 */ {"MOV R0,",2,1},
+ /* B9 */ {"MOV R1,",2,1},
+ /* BA */ {"MOV R2,",2,1},
+ /* BB */ {"MOV R3,",2,1},
+
+ /* BC */ {"MOV R4,",2,1},
+ /* BD */ {"MOV R5,",2,1},
+ /* BE */ {"MOV R6,",2,1},
+ /* BF */ {"MOV R7,",2,1},
+
+ /* C0 */ {"ILL",1,0},
+ /* C1 */ {"ILL",1,0},
+ /* C2 */ {"ILL",1,0},
+ /* C3 */ {"ILL",1,0},
+
+ /* C4 */ {"JMP",2,2},
+ /* C5 */ {"SEL RB0",1,0},
+ /* C6 */ {"JZ",2,3},
+ /* C7 */ {"MOV A,PSW",1,0},
+
+ /* C8 */ {"DEC R0",1,0},
+ /* C9 */ {"DEC R1",1,0},
+ /* CA */ {"DEC R2",1,0},
+ /* CB */ {"DEC R3",1,0},
+
+ /* CC */ {"DEC R4",1,0},
+ /* CD */ {"DEC R5",1,0},
+ /* CE */ {"DEC R6",1,0},
+ /* CF */ {"DEC R7",1,0},
+
+ /* D0 */ {"XRL A,@R0",1,0},
+ /* D1 */ {"XRL A,@R1",1,0},
+ /* D2 */ {"JB6",2,3},
+ /* D3 */ {"XRL A,",2,1},
+
+ /* D4 */ {"CALL",2,2},
+ /* D5 */ {"SEL RB1",1,0},
+ /* D6 */ {"ILL",1,0},
+ /* D7 */ {"MOV PSW,A",1,0},
+
+ /* D8 */ {"XRL A,R0",1,0},
+ /* D9 */ {"XRL A,R1",1,0},
+ /* DA */ {"XRL A,R2",1,0},
+ /* DB */ {"XRL A,R3",1,0},
+ /* DC */ {"XRL A,R4",1,0},
+ /* DD */ {"XRL A,R5",1,0},
+ /* DE */ {"XRL A,R6",1,0},
+ /* DF */ {"XRL A,R7",1,0},
+
+ /* E0 */ {"ILL",1,0},
+ /* E1 */ {"ILL",1,0},
+ /* E2 */ {"ILL",1,0},
+ /* E3 */ {"MOVP3 A,@A",1,0},
+
+ /* E4 */ {"JMP",2,2},
+ /* E5 */ {"SEL MB0",1,0},
+ /* E6 */ {"JNC",2,3},
+ /* E7 */ {"RL A",1,0},
+
+ /* E8 */ {"DJNZ R0,",2,3},
+ /* E9 */ {"DJNZ R1,",2,3},
+ /* EA */ {"DJNZ R2,",2,3},
+ /* EB */ {"DJNZ R3,",2,3},
+ /* EC */ {"DJNZ R4,",2,3},
+ /* ED */ {"DJNZ R5,",2,3},
+ /* EE */ {"DJNZ R6,",2,3},
+ /* EF */ {"DJNZ R7,",2,3},
+
+ /* F0 */ {"MOV A,@R0",1,0},
+ /* F1 */ {"MOV A,@R1",1,0},
+ /* F2 */ {"JB7",2,3},
+ /* F3 */ {"ILL",1,0},
+
+ /* F4 */ {"CALL",2,2},
+ /* F5 */ {"SEL MB1",1,0},
+ /* F6 */ {"JC",2,3},
+ /* F7 */ {"RLC A",1,0},
+
+ /* F8 */ {"MOV A,R0",1,0},
+ /* F9 */ {"MOV A,R1",1,0},
+ /* FA */ {"MOV A,R2",1,0},
+ /* FB */ {"MOV A,R3",1,0},
+ /* FC */ {"MOV A,R4",1,0},
+ /* FD */ {"MOV A,R5",1,0},
+ /* FE */ {"MOV A,R6",1,0},
+ /* FF */ {"MOV A,R7",1,0}
+
+};
+
diff --git a/clean/src/table.h b/clean/src/table.h
new file mode 100755
index 0000000..df8d890
--- /dev/null
+++ b/clean/src/table.h
@@ -0,0 +1,10 @@
+#ifndef __TABLE_H
+#define __TABLE_H
+
+extern struct lookup_tag {
+ char *mnemonic;
+ unsigned char bytes;
+ unsigned char type;
+} lookup[];
+
+#endif
diff --git a/clean/src/timefunc.c b/clean/src/timefunc.c
new file mode 100755
index 0000000..b50021d
--- /dev/null
+++ b/clean/src/timefunc.c
@@ -0,0 +1,100 @@
+
+/*
+ * O2EM Free Odyssey2 / Videopac+ Emulator
+ *
+ * Created by Daniel Boris (c) 1997,1998
+ *
+ * Developed by Andre de la Rocha
+ * Arlindo M. de Oliveira
+ *
+ * http://o2em.sourceforge.net
+ *
+ *
+ *
+ * Timing functions
+ */
+
+
+#include
+#include "allegro.h"
+#ifdef ALLEGRO_WINDOWS
+#include "winalleg.h"
+#elif defined(ALLEGRO_UNIX) || defined(ALLEGRO_LINUX)
+#include
+#include
+#endif
+#include "timefunc.h"
+
+
+
+#ifdef ALLEGRO_WINDOWS
+
+/* Windows */
+long gettimeticks(void){
+ LARGE_INTEGER counter, freq;
+ static LONG_LONG first=-1;
+ if (QueryPerformanceCounter(&counter))
+ if (QueryPerformanceFrequency(&freq)) {
+ if (first<0) first = counter.QuadPart;
+ return (long)(((counter.QuadPart-first)*TICKSPERSEC)/freq.QuadPart);
+ }
+ return (long)((((LONG_LONG)clock())*TICKSPERSEC)/CLOCKS_PER_SEC);
+}
+
+#elif defined(ALLEGRO_UNIX) || defined(ALLEGRO_LINUX)
+
+#if defined(_BSD_SOURCE) || defined(FREEBSD)
+
+/* Unix with gettimeofday */
+long gettimeticks(void){
+ struct timeval tv;
+ static LONG_LONG first=-1;
+ LONG_LONG ll;
+ if (first<0) {
+ if (gettimeofday(&tv, NULL) != 0)
+ return (long)((((LONG_LONG)clock())*TICKSPERSEC)/CLOCKS_PER_SEC);
+ first = ((LONG_LONG)tv.tv_sec)*1000000 + tv.tv_usec;
+ }
+ if (gettimeofday(&tv, NULL) == 0) {
+ ll = ((LONG_LONG)tv.tv_sec)*1000000 + tv.tv_usec;
+ return (long) (((ll-first)*TICKSPERSEC)/1000000);
+ }
+ return (long)((((LONG_LONG)clock())*TICKSPERSEC)/CLOCKS_PER_SEC);
+}
+
+#else
+
+/* Unix without gettimeofday */
+long gettimeticks(void){
+ struct tms t;
+ return (long)((((LONG_LONG)times(&t))*TICKSPERSEC)/sysconf(_SC_CLK_TCK));
+}
+
+#endif
+
+#else
+
+/* Default (use Allegro timers) */
+
+volatile long ticks_counter = 0;
+static int timer_init = 0;
+
+void inc_ticks_counter(void){
+ ticks_counter++;
+}
+
+END_OF_FUNCTION(inc_ticks_counter);
+
+long gettimeticks(void){
+ if (timer_init==0) {
+ ticks_counter=0;
+ LOCK_VARIABLE(ticks_counter);
+ LOCK_FUNCTION(inc_ticks_counter);
+ install_int(inc_ticks_counter, 1);
+ timer_init=1;
+ }
+ return (long)(((LONG_LONG)ticks_counter*TICKSPERSEC)/1000);
+}
+
+#endif
+
diff --git a/clean/src/timefunc.h b/clean/src/timefunc.h
new file mode 100755
index 0000000..61da087
--- /dev/null
+++ b/clean/src/timefunc.h
@@ -0,0 +1,8 @@
+#ifndef __TIMEFUNC_H
+#define __TIMEFUNC_H
+
+#define TICKSPERSEC 10000
+
+long gettimeticks(void);
+
+#endif
diff --git a/clean/src/types.h b/clean/src/types.h
new file mode 100755
index 0000000..a0a8afe
--- /dev/null
+++ b/clean/src/types.h
@@ -0,0 +1,8 @@
+#ifndef TYPES_H
+#define TYPES_H
+
+typedef unsigned char Byte;
+typedef unsigned short ADDRESS;
+#define MAXC 1024
+#endif /* TYPES_H */
+
diff --git a/clean/src/vdc.c b/clean/src/vdc.c
new file mode 100755
index 0000000..57d7a99
--- /dev/null
+++ b/clean/src/vdc.c
@@ -0,0 +1,830 @@
+/*
+ * O2EM Free Odyssey2 / Videopac+ Emulator
+ *
+ * Created by Daniel Boris (c) 1997,1998
+ *
+ * Developed by Andre de la Rocha
+ * Arlindo M. de Oliveira
+ *
+ * http://o2em.sourceforge.net
+ *
+ *
+ *
+ * O2 Video Display Controller emulation
+ */
+
+#include
+#include
+#include
+#include "types.h"
+#include "vmachine.h"
+#include "config.h"
+#include "keyboard.h"
+#include "cset.h"
+#include "timefunc.h"
+#include "cpu.h"
+#include "vpp.h"
+#include "vdc.h"
+#include "allegro.h"
+#include "audio.h"
+#include "voice.h"
+
+#define COL_SP0 0x01
+#define COL_SP1 0x02
+#define COL_SP2 0x04
+#define COL_SP3 0x08
+#define COL_VGRID 0x10
+#define COL_HGRID 0x20
+#define COL_VPP 0x40
+#define COL_CHAR 0x80
+
+#define X_START 8
+#define Y_START 24
+
+static long colortable[2][16] = {
+ /* O2 palette */
+ { 0x000000, 0x0e3dd4, 0x00981b, 0x00bbd9, 0xc70008, 0xcc16b3, 0x9d8710,
+ 0xe1dee1, 0x5f6e6b, 0x6aa1ff, 0x3df07a, 0x31ffff, 0xff4255, 0xff98ff,
+ 0xd9ad5d, 0xffffff },
+ /* VP+ G7400 palette */
+ { 0x000000, 0x0000b6, 0x00b600, 0x00b6b6, 0xb60000, 0xb600b6, 0xb6b600,
+ 0xb6b6b6, 0x494949, 0x4949ff, 0x49ff49, 0x49ffff, 0xff4949, 0xff49ff,
+ 0xffff49, 0xffffff }
+};
+
+/* Collision buffer */
+static Byte *col = NULL;
+
+static PALETTE colors, oldcol;
+
+/* The pointer to the graphics buffer */
+static Byte *vscreen = NULL;
+
+static BITMAP *bitmap, *bitmap_cache;
+static int cached_lines[MAXLINES];
+
+Byte coltab[256];
+
+long clip_low;
+long clip_high;
+
+int show_fps = 0;
+
+int wsize;
+
+static void create_cmap(void);
+static void draw_char(Byte ypos, Byte xpos, Byte chr, Byte col);
+static void draw_quad(Byte ypos, Byte xpos, Byte cp0l, Byte cp0h, Byte cp1l,
+ Byte cp1h, Byte cp2l, Byte cp2h, Byte cp3l, Byte cp3h);
+static void draw_grid(void);
+INLINE void mputvid(unsigned int ad, unsigned int len, Byte d, Byte c);
+
+void draw_region(void)
+{
+ int i;
+ if (regionoff == 0xffff) {
+ i = (master_clk / (LINECNT - 1) - 5);
+ } else {
+ i = (master_clk / 22 + regionoff);
+ }
+ i = (snapline(i, VDCwrite[0xA0], 0));
+ if (app_data.crc == 0xA7344D1F) {
+ i = (master_clk / 22 + regionoff) + 6;
+ i = (snapline(i, VDCwrite[0xA0], 0) + 6);
+ }/*Atlantis*/
+
+ if (app_data.crc == 0xD0BC4EE6) {
+ i = (master_clk / 24 + regionoff) - 6;
+ i = (snapline(i, VDCwrite[0xA0], 0) + 7);
+ }/*Frogger*/
+
+ if (app_data.crc == 0x26517E77) {
+ i = (master_clk / 22 + regionoff);
+ i = (snapline(i, VDCwrite[0xA0], 0) - 5);
+ }/*Comando Noturno*/
+
+ if (app_data.crc == 0xA57E1724) {
+ i = (master_clk / (LINECNT - 1) - 5);
+ i = (snapline(i, VDCwrite[0xA0], 0) - 3);
+ }/*Catch the ball*/
+
+ if (i < 0)
+ i = 0;
+ clip_low = last_line * (long) BMPW;
+ clip_high = i * (long) BMPW;
+ if (clip_high > BMPW * BMPH)
+ clip_high = BMPW * BMPH;
+ if (clip_low < 0)
+ clip_low = 0;
+ if (clip_low < clip_high)
+ draw_display();
+ last_line = i;
+}
+
+static void create_cmap(void)
+{
+ int i;
+
+ /* Initialise parts of the colors array */
+ for (i = 0; i < 16; i++) {
+ /* Use the color values from the color table */
+ colors[i + 32].r = colors[i].r = (colortable[app_data.vpp ? 1 : 0][i]
+ & 0xff0000) >> 18;
+ colors[i + 32].g = colors[i].g = (colortable[app_data.vpp ? 1 : 0][i]
+ & 0x00ff00) >> 10;
+ colors[i + 32].b = colors[i].b = (colortable[app_data.vpp ? 1 : 0][i]
+ & 0x0000ff) >> 2;
+ }
+
+ for (i = 16; i < 32; i++) {
+ /* Half-bright colors for the 50% scanlines */
+ colors[i + 32].r = colors[i].r = colors[i - 16].r / 2;
+ colors[i + 32].g = colors[i].g = colors[i - 16].g / 2;
+ colors[i + 32].b = colors[i].b = colors[i - 16].b / 2;
+ }
+
+ for (i = 64; i < 256; i++)
+ colors[i].r = colors[i].g = colors[i].b = 0;
+}
+
+void grmode(void)
+{
+ set_color_depth(8);
+ wsize = app_data.wsize;
+ if (app_data.fullscreen) {
+ if (app_data.scanlines) {
+ wsize = 2;
+ if (set_gfx_mode(GFX_AUTODETECT_FULLSCREEN, 640, 480, 0, 0)) {
+ wsize = 1;
+ if (set_gfx_mode(GFX_AUTODETECT_FULLSCREEN, 320, 240, 0, 0)) {
+ fprintf(stderr, "Error: could not create screen.\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+ } else {
+#ifdef ALLEGRO_DOS
+ wsize = 1;
+ if (set_gfx_mode(GFX_AUTODETECT_FULLSCREEN, 320, 240, 0, 0)) {
+ wsize = 2;
+ if (set_gfx_mode(GFX_AUTODETECT_FULLSCREEN, 640, 480, 0, 0)) {
+ fprintf(stderr,"Error: could not create screen.\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+#else
+ wsize = 2;
+ if (set_gfx_mode(GFX_AUTODETECT_FULLSCREEN, 640, 480, 0, 0)) {
+ wsize = 1;
+ if (set_gfx_mode(GFX_AUTODETECT_FULLSCREEN, 320, 240, 0, 0)) {
+ fprintf(stderr, "Error: could not create screen.\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+#endif
+ }
+ } else {
+ if (set_gfx_mode(GFX_AUTODETECT_WINDOWED, WNDW * wsize, WNDH * wsize, 0,
+ 0)) {
+ wsize = 2;
+ if (set_gfx_mode(GFX_AUTODETECT_WINDOWED, WNDW * 2, WNDH * 2, 0,
+ 0)) {
+ if (set_gfx_mode(GFX_AUTODETECT, WNDW * 2, WNDH * 2, 0, 0)) {
+ fprintf(stderr, "Error: could not create window.\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+#ifndef ALLEGRO_DOS
+ printf("Could not set the requested window size\n");
+#endif
+ }
+ }
+
+ if ((app_data.scanlines) && (wsize == 1)) {
+#ifndef ALLEGRO_DOS
+ printf("Could not set scanlines\n");
+#endif
+ }
+ set_palette(colors);
+ set_window_title(app_data.window_title);
+ clearscr();
+ set_display_switch_mode(SWITCH_PAUSE);
+}
+
+void set_textmode(void)
+{
+ set_palette(oldcol);
+ set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
+ if (new_int) {
+ Set_Old_Int9();
+ }
+}
+
+void clearscr(void)
+{
+ acquire_screen();
+ clear(screen);
+ release_screen();
+ clear(bitmap_cache);
+}
+
+INLINE void mputvid(unsigned int ad, unsigned int len, Byte d, Byte c)
+{
+ if ((ad > (unsigned long) clip_low) && (ad < (unsigned long) clip_high)) {
+ unsigned int i;
+ if (((len & 3) == 0) && (sizeof(unsigned long) == 4)) {
+ unsigned long dddd = (((unsigned long) d) & 0xff)
+ | ((((unsigned long) d) & 0xff) << 8)
+ | ((((unsigned long) d) & 0xff) << 16)
+ | ((((unsigned long) d) & 0xff) << 24);
+ unsigned long cccc = (((unsigned long) c) & 0xff)
+ | ((((unsigned long) c) & 0xff) << 8)
+ | ((((unsigned long) c) & 0xff) << 16)
+ | ((((unsigned long) c) & 0xff) << 24);
+ for (i = 0; i < len >> 2; i++) {
+ *((unsigned long*) (vscreen + ad)) = dddd;
+ cccc |= *((unsigned long*) (col + ad));
+ *((unsigned long*) (col + ad)) = cccc;
+ coltab[c] |= ((cccc | (cccc >> 8) | (cccc >> 16) | (cccc >> 24))
+ & 0xff);
+ ad += 4;
+ }
+ } else {
+ for (i = 0; i < len; i++) {
+ vscreen[ad] = d;
+ col[ad] |= c;
+ coltab[c] |= col[ad++];
+ }
+ }
+ }
+}
+
+static void draw_grid(void)
+{
+ unsigned int pnt, pn1;
+ Byte mask, d;
+ int j, i, x, w;
+ Byte color;
+
+ if (VDCwrite[0xA0] & 0x40) {
+ for (j = 0; j < 9; j++) {
+ pnt = (((j * 24) + 24) * BMPW);
+ for (i = 0; i < 9; i++) {
+ pn1 = pnt + (i * 32) + 20;
+ color = ColorVector[j * 24 + 24];
+ mputvid(
+ pn1,
+ 4,
+ (color & 0x07) | ((color & 0x40) >> 3)
+ | (color & 0x80 ? 0 : 8), COL_HGRID);
+ color = ColorVector[j * 24 + 25];
+ mputvid(
+ pn1 + BMPW,
+ 4,
+ (color & 0x07) | ((color & 0x40) >> 3)
+ | (color & 0x80 ? 0 : 8), COL_HGRID);
+ color = ColorVector[j * 24 + 26];
+ mputvid(
+ pn1 + BMPW * 2,
+ 4,
+ (color & 0x07) | ((color & 0x40) >> 3)
+ | (color & 0x80 ? 0 : 8), COL_HGRID);
+ }
+ }
+ }
+
+ mask = 0x01;
+ for (j = 0; j < 9; j++) {
+ pnt = (((j * 24) + 24) * BMPW);
+ for (i = 0; i < 9; i++) {
+ pn1 = pnt + (i * 32) + 20;
+ if ((pn1 + BMPW * 3 >= (unsigned long) clip_low)
+ && (pn1 <= (unsigned long) clip_high)) {
+ d = VDCwrite[0xC0 + i];
+ if (j == 8) {
+ d = VDCwrite[0xD0 + i];
+ mask = 1;
+ }
+ if (d & mask) {
+ color = ColorVector[j * 24 + 24];
+ mputvid(
+ pn1,
+ 36,
+ (color & 0x07) | ((color & 0x40) >> 3)
+ | (color & 0x80 ? 0 : 8), COL_HGRID);
+ color = ColorVector[j * 24 + 25];
+ mputvid(
+ pn1 + BMPW,
+ 36,
+ (color & 0x07) | ((color & 0x40) >> 3)
+ | (color & 0x80 ? 0 : 8), COL_HGRID);
+ color = ColorVector[j * 24 + 26];
+ mputvid(
+ pn1 + BMPW * 2,
+ 36,
+ (color & 0x07) | ((color & 0x40) >> 3)
+ | (color & 0x80 ? 0 : 8), COL_HGRID);
+ }
+ }
+ }
+ mask = mask << 1;
+ }
+
+ mask = 0x01;
+ w = 4;
+ if (VDCwrite[0xA0] & 0x80) {
+ w = 32;
+ }
+ for (j = 0; j < 10; j++) {
+ pnt = (j * 32);
+ mask = 0x01;
+ d = VDCwrite[0xE0 + j];
+ for (x = 0; x < 8; x++) {
+ pn1 = pnt + (((x * 24) + 24) * BMPW) + 20;
+ if (d & mask) {
+ for (i = 0; i < 24; i++) {
+ if ((pn1 >= (unsigned long) clip_low)
+ && (pn1 <= (unsigned long) clip_high)) {
+ color = ColorVector[x * 24 + 24 + i];
+ mputvid(
+ pn1,
+ w,
+ (color & 0x07) | ((color & 0x40) >> 3)
+ | (color & 0x80 ? 0 : 8), COL_VGRID);
+ }
+ pn1 += BMPW;
+ }
+ }
+ mask = mask << 1;
+ }
+ }
+}
+
+void finish_display(void)
+{
+ int x, y, sn;
+ static int cache_counter = 0;
+
+ vpp_finish_bmp(vscreen, 9, 5, BMPW - 9, BMPH - 5, bitmap->w, bitmap->h);
+
+ if (show_fps) {
+ static long last = -1, index = 0, curr = 0, t = 0;
+ if (last < 0)
+ last = gettimeticks();
+ index = (index + 1) % 200;
+ if (!index) {
+ t = gettimeticks();
+ curr = t - last;
+ last = t;
+ }
+ if (curr) {
+ textprintf_ex(bitmap, font, 20, 4, 7, 0, "FPS :%3d",
+ (int) ((200.0 * TICKSPERSEC) / curr + 0.5));
+ }
+ }
+
+ for (y = 0; y < bitmap->h; y++) {
+ cached_lines[y] = !memcmp(bitmap_cache->line[y], bitmap->line[y], bitmap->w);
+ if (!cached_lines[y])
+ memcpy(bitmap_cache->line[y], bitmap->line[y], bitmap->w);
+ }
+
+ for (y = 0; y < 10; y++)
+ cached_lines[(y + cache_counter) % bitmap->h] = 0;
+ cache_counter = (cache_counter + 10) % bitmap->h;
+
+ acquire_screen();
+
+ sn = ((wsize > 1) && (app_data.scanlines)) ? 1 : 0;
+
+ for (y = 0; y < WNDH; y++) {
+ if (!cached_lines[y + 2])
+ stretch_blit(bitmap, screen, 7, 2 + y, WNDW, 1, 0, y * wsize,
+ WNDW * wsize, wsize - sn);
+ }
+
+ if (sn) {
+ for (y = 0; y < WNDH; y++) {
+ if (!cached_lines[y + 2]) {
+ for (x = 0; x < bitmap->w; x++)
+ bitmap->line[y + 2][x] += 16;
+ stretch_blit(bitmap, screen, 7, 2 + y, WNDW, 1, 0,
+ (y + 1) * wsize - 1, WNDW * wsize, 1);
+ memcpy(bitmap->line[y + 2], bitmap_cache->line[y + 2], bitmap->w);
+ }
+ }
+ }
+ release_screen();
+}
+
+void clear_collision(void)
+{
+ load_colplus(col);
+ coltab[0x01] = coltab[0x02] = 0;
+ coltab[0x04] = coltab[0x08] = 0;
+ coltab[0x10] = coltab[0x20] = 0;
+ coltab[0x40] = coltab[0x80] = 0;
+}
+
+void draw_display(void)
+{
+ int i, j, x, sm, t;
+ Byte y, b, d1, cl, c;
+
+ unsigned int pnt, pnt2;
+
+ for (i = clip_low / BMPW; i < clip_high / BMPW; i++)
+ memset(
+ vscreen + i * BMPW,
+ ((ColorVector[i] & 0x38) >> 3)
+ | (ColorVector[i] & 0x80 ? 0 : 8), BMPW);
+
+ if (VDCwrite[0xA0] & 0x08)
+ draw_grid();
+
+ if (useforen && (!(VDCwrite[0xA0] & 0x20)))
+ return;
+
+ for (i = 0x10; i < 0x40; i += 4)
+ draw_char(VDCwrite[i], VDCwrite[i + 1], VDCwrite[i + 2],
+ VDCwrite[i + 3]);
+
+ /* draw quads, position mapping happens in ext_write (vmachine.c)*/
+ for (i = 0x40; i < 0x80; i += 0x10)
+ draw_quad(VDCwrite[i], VDCwrite[i + 1], VDCwrite[i + 2],
+ VDCwrite[i + 3], VDCwrite[i + 6], VDCwrite[i + 7],
+ VDCwrite[i + 10], VDCwrite[i + 11], VDCwrite[i + 14],
+ VDCwrite[i + 15]);
+
+ c = 8;
+ for (i = 12; i >= 0; i -= 4) {
+ pnt2 = 0x80 + (i * 2);
+ y = VDCwrite[i];
+ x = VDCwrite[i + 1] - 8;
+ t = VDCwrite[i + 2];
+ cl = ((t & 0x38) >> 3);
+ cl = ((cl & 2) | ((cl & 1) << 2) | ((cl & 4) >> 2)) + 8;
+ /*174*/
+ if ((x < 164) && (y > 0) && (y < 232)) {
+ pnt = y * BMPW + (x * 2) + 20 + sproff;
+ if (t & 4) {
+ if ((pnt + BMPW * 32 >= (unsigned long) clip_low)
+ && (pnt <= (unsigned long) clip_high)) {
+ for (j = 0; j < 8; j++) {
+ sm = (((j % 2 == 0) && (((t >> 1) & 1) != (t & 1)))
+ || ((j % 2 == 1) && (t & 1))) ? 1 : 0;
+ d1 = VDCwrite[pnt2++];
+ for (b = 0; b < 8; b++) {
+ if (d1 & 0x01) {
+ if ((x + b + sm < 159) && (y + j < 247)) {
+ mputvid(sm + pnt, 4, cl, c);
+ mputvid(sm + pnt + BMPW, 4, cl, c);
+ mputvid(sm + pnt + 2 * BMPW, 4, cl, c);
+ mputvid(sm + pnt + 3 * BMPW, 4, cl, c);
+ }
+ }
+ pnt += 4;
+ d1 = d1 >> 1;
+ }
+ pnt += BMPW * 4 - 32;
+ }
+ }
+ } else {
+ if ((pnt + BMPW * 16 >= (unsigned long) clip_low)
+ && (pnt <= (unsigned long) clip_high)) {
+ for (j = 0; j < 8; j++) {
+ sm = (((j % 2 == 0) && (((t >> 1) & 1) != (t & 1)))
+ || ((j % 2 == 1) && (t & 1))) ? 1 : 0;
+ d1 = VDCwrite[pnt2++];
+ for (b = 0; b < 8; b++) {
+ if (d1 & 0x01) {
+ if ((x + b + sm < 160) && (y + j < 249)) {
+ mputvid(sm + pnt, 2, cl, c);
+ mputvid(sm + pnt + BMPW, 2, cl, c);
+ }
+ }
+ pnt += 2;
+ d1 = d1 >> 1;
+ }
+ pnt += BMPW * 2 - 16;
+ }
+ }
+ }
+ }
+ c = c >> 1;
+ }
+}
+
+void draw_char(Byte ypos, Byte xpos, Byte chr, Byte col)
+{
+ int j, c;
+ Byte cl, d1;
+ int y, b, n;
+ unsigned int pnt;
+
+ y = (ypos & 0xFE);
+ pnt = y * BMPW + ((xpos - 8) * 2) + 20;
+
+ ypos = ypos >> 1;
+ n = 8 - (ypos % 8) - (chr % 8);
+ if (n < 3)
+ n = n + 7;
+
+ if ((pnt + BMPW * 2 * n >= (unsigned long) clip_low)
+ && (pnt <= (unsigned long) clip_high)) {
+
+ c = (int) chr + ypos;
+ if (col & 0x01)
+ c += 256;
+ if (c > 511)
+ c = c - 512;
+
+ cl = ((col & 0x0E) >> 1);
+ cl = ((cl & 2) | ((cl & 1) << 2) | ((cl & 4) >> 2)) + 8;
+
+ if ((y > 0) && (y < 232) && (xpos < 157)) {
+ for (j = 0; j < n; j++) {
+ d1 = cset[c + j];
+ for (b = 0; b < 8; b++) {
+ if (d1 & 0x80) {
+ if ((xpos - 8 + b < 160) && (y + j < 240)) {
+ mputvid(pnt, 2, cl, COL_CHAR);
+ mputvid(pnt + BMPW, 2, cl, COL_CHAR);
+ }
+ }
+ pnt += 2;
+ d1 = d1 << 1;
+ }
+ pnt += BMPW * 2 - 16;
+ }
+ }
+ }
+}
+
+/* This quad drawing routine can display the quad cut off effect used in KTAA.
+ * It needs more testing with other games, especially the clipping.
+ * This code is quite slow and needs a rewrite by somebody with more experience
+ * than I (sgust) have */
+
+void draw_quad(Byte ypos, Byte xpos, Byte cp0l, Byte cp0h, Byte cp1l, Byte cp1h,
+ Byte cp2l, Byte cp2h, Byte cp3l, Byte cp3h)
+{
+ /* char set pointers */
+ int chp[4];
+ /* colors */
+ Byte col[4];
+ /* pointer into screen bitmap */
+ unsigned int pnt;
+ /* offset into current line */
+ unsigned int off;
+ /* loop variables */
+ int i, j, lines;
+
+ /* get screen bitmap position of quad */
+ pnt = (ypos & 0xfe) * BMPW + ((xpos - 8) * 2) + 20;
+ /* abort drawing if completely below the bottom clip */
+ if (pnt > (unsigned long) clip_high)
+ return;
+ /* extract and convert char-set offsets */
+ chp[0] = cp0l | ((cp0h & 1) << 8);
+ chp[1] = cp1l | ((cp1h & 1) << 8);
+ chp[2] = cp2l | ((cp2h & 1) << 8);
+ chp[3] = cp3l | ((cp3h & 1) << 8);
+ for (i = 0; i < 4; i++)
+ chp[i] = (chp[i] + (ypos >> 1)) & 0x1ff;
+ lines = 8 - (chp[3] + 1) % 8;
+ /* abort drawing if completely over the top clip */
+ if (pnt + BMPW * 2 * lines < (unsigned long) clip_low)
+ return;
+ /* extract and convert color information */
+ col[0] = (cp0h & 0xe) >> 1;
+ col[1] = (cp1h & 0xe) >> 1;
+ col[2] = (cp2h & 0xe) >> 1;
+ col[3] = (cp3h & 0xe) >> 1;
+ for (i = 0; i < 4; i++)
+ col[i] = ((col[i] & 2) | ((col[i] & 1) << 2) | ((col[i] & 4) >> 2)) + 8;
+ /* now draw the quad line by line controlled by the last quad */
+ while (lines-- > 0) {
+ off = 0;
+ /* draw all 4 sub-quads */
+ for (i = 0; i < 4; i++) {
+ /* draw sub-quad pixel by pixel, but stay in same line */
+ for (j = 0; j < 8; j++) {
+ if ((cset[chp[i]] & (1 << (7 - j))) && (off < BMPW)) {
+ mputvid(pnt + off, 2, col[i], COL_CHAR);
+ mputvid(pnt + off + BMPW, 2, col[i], COL_CHAR);
+ }
+ /* next pixel */
+ off += 2;
+ }
+ /* space between sub-quads */
+ off += 16;
+ }
+ /* advance char-set pointers */
+ for (i = 0; i < 4; i++)
+ chp[i] = (chp[i] + 1) & 0x1ff;
+ /* advance screen bitmap pointer */
+ pnt += BMPW * 2;
+ }
+}
+
+void close_display(void)
+{
+ free(vscreen);
+ free(col);
+}
+
+void window_close_hook(void)
+{
+ key_debug = 0;
+ key_done = 1;
+
+ // FIXME : Quit program in a clean way
+ //finish_display();
+ //close_display();
+ //allegro_exit();
+}
+static void txtmsg(int x, int y, int c, const char *s)
+{
+ textout_centre_ex(bitmap, font, s, x + 1, y + 1, makecol(255, 0, 0),
+ makecol(0, 0, 0));
+ textout_centre_ex(bitmap, font, s, x, y, c, makecol(0, 0, 0));
+}
+void display_bg(void)
+{
+ rectfill(bitmap, 20, 72, 311, 172, 9 + 32);
+ line(bitmap, 20, 72, 311, 72, 15 + 32);
+ line(bitmap, 20, 72, 20, 172, 15 + 32);
+ line(bitmap, 21, 172, 311, 172, 1 + 32);
+ line(bitmap, 311, 172, 311, 72, 1 + 32);
+}
+
+void abaut(void)
+{
+ char *ver;
+ char exitstr[80];
+ int i = 0;
+ while (syskeys[1] != keybtab[i].keybcode)
+ i++;
+
+ strcpy(exitstr, "Press ");
+ strcat(exitstr, keybtab[i].keybname);
+ strcat(exitstr, " to continue");
+
+#if defined(ALLEGRO_WINDOWS)
+ ver = "Windows version";
+#elif defined(ALLEGRO_DOS)
+ ver = "DOS version";
+#elif defined(ALLEGRO_LINUX)
+ ver = "Linux version";
+#elif defined(ALLEGRO_BEOS)
+ ver = "BEOS version";
+#elif defined(ALLEGRO_QNX)
+ ver = "QNX version";
+#elif defined(ALLEGRO_UNIX)
+ ver = "UNIX version";
+#elif defined(ALLEGRO_MPW)
+ ver = "MacOS version";
+#else
+ ver = "Unknown platform";
+#endif
+ display_bg();
+ txtmsg(166, 76, 15 + 32, "O2EM v" O2EM_VERSION " " RELEASE_DATE);
+ txtmsg(166, 90, 15 + 32, "Free Odyssey2 / VP+ Emulator");
+ txtmsg(166, 104, 15 + 32, ver);
+ txtmsg(166, 118, 15 + 32, "Developed by Andre de la Rocha");
+ txtmsg(168, 132, 15 + 32, "and Arlindo M. de Oliveira");
+ txtmsg(166, 148, 15 + 32, "Copyright 1996/1998 by Daniel Boris");
+ txtmsg(166, 162, 15 + 32, exitstr);
+ finish_display();
+}
+void display_msg(char *msg, int waits)
+{
+ mute_audio();
+ mute_voice();
+ rectfill(bitmap, 60, 72, 271, 90, 9 + 32);
+ line(bitmap, 60, 72, 271, 72, 15 + 32);
+ line(bitmap, 60, 72, 60, 90, 15 + 32);
+ line(bitmap, 61, 90, 271, 90, 1 + 32);
+ line(bitmap, 271, 90, 271, 72, 1 + 32);
+ txtmsg(166, 76, 15 + 32, msg);
+ finish_display();
+ rest(waits * 100);
+ init_sound_stream();
+}
+void init_display(void)
+{
+ get_palette(oldcol);
+ create_cmap();
+ bitmap = create_bitmap(BMPW, BMPH);
+ bitmap_cache = create_bitmap(BMPW, BMPH);
+ if ((!bitmap) || (!bitmap_cache)) {
+ fprintf(stderr, "Could not allocate memory for screen buffer.\n");
+ exit(EXIT_FAILURE);
+ }
+ vscreen = (Byte *) bitmap->dat;
+ clear(bitmap);
+ clear(bitmap_cache);
+ col = (Byte *) malloc(BMPW * BMPH);
+ if (!col) {
+ fprintf(stderr, "Could not allocate memory for collision buffer.\n");
+ free(vscreen);
+ exit(EXIT_FAILURE);
+ }
+ memset(col, 0, BMPW * BMPH);
+ if (!app_data.debug) {
+ grmode();
+ init_keyboard();
+ }
+ set_close_button_callback(window_close_hook);
+
+}
+/*************************** Help*/
+void help(void)
+{
+ int yet_another_index = 40;
+ int index = 0;
+ int counter = 0;
+ int way = 0;
+ static char hl[96][70] = {
+ "-wsize=n", " Window size (1-4)", "",
+ "-fullscreen", " Full screen mode", "",
+ "-help", " This instructions", "",
+ "-scanlines", " Enable scanlines", "",
+ "-nosound", " Turn off sound emulation", "",
+ "-novoice", " Turn off voice emulation", "",
+ "-svolume=n", " Set sound volume (0-100)", "",
+ "-vvolume=n", " Set voice volume (0-100)", "",
+ "-filter", " Enable low-pass audio filter", "",
+ "-debug", " Start the emulator in ", " debug mode", "",
+ "-speed=n", " Relative speed", " (100 = original)", "",
+ "-nolimit", " Turn off speed limiter", "",
+ "-bios=file", " Set the O2 bios file name/dir", "",
+ "-biosdir=path", " Set the O2 bios path ", " (default= bios/ )", "",
+ "-romdir=path", " Set the O2 roms Path ", " (default= roms/ )", "",
+ "-scshot=file", " Set the screenshot file ", " name/template", "",
+ "-euro", " Use European timing /", " 50Hz mode", "",
+ "-exrom", " Use special 3K program/", " 1K data ROM mode", "",
+ "-3k", " Use 3K rom mapping mode", "",
+ "-s=mode/keys", " Define stick n mode/keys (n=1-2)", "",
+ "-c52", " Start the emulator with ", " french Odyssey 2 BIOS", "",
+ "-g7400", " Start the emulator ", " with VP+ BIOS", "",
+ "-jopac", " Start the emulator with ", " french VP+ bios", "",
+ "-scoretype=m", " Set Scoretype to m (see manual)", "",
+ "-scoreadr=n", " Set Scoreaddress to n ", " (decimal value)", "",
+ "-scorefile=file", " Set Output-Scorefile to ", " file (highscore.txt)", "",
+ "-score=n", " Set Highscore to n", "",
+ "-savefile=file", " Load/Save State ", " from/to file"
+ };
+
+ textout_ex(bitmap, font, "O2EM v" O2EM_VERSION " Help", 26, 16, 2, 0);
+ textout_ex(bitmap, font, "Use: o2em [options]", 26, 26, 2, 0);
+ rect(bitmap, 20, 12, 315, 228, 6);
+ line(bitmap, 20, 35, 315, 35, 6);
+ for (index = 0; index < 16; index++) {
+ textout_ex(bitmap, font, hl[counter + index], 26, yet_another_index, 4, makecol(0, 0, 0));
+ yet_another_index += 12;
+ }
+ yet_another_index = 40;
+ finish_display();
+ do {
+ rest(25);
+ if (NeedsPoll)
+ poll_keyboard();
+ if (key[KEY_DOWN]) {
+ counter++;
+ if (counter >= 80)
+ counter = 80;
+ rectfill(bitmap, 25, 36, 306, 227, 0);
+ for (index = 0; index < 16; index++) {
+ textout_ex(bitmap, font, hl[counter + index], 26, yet_another_index, 4,
+ makecol(0, 0, 0));
+ yet_another_index += 12;
+ }
+ yet_another_index = 40;
+ for (way = 0; way < 8; way++)
+ finish_display();
+ }
+ if (key[KEY_UP]) {
+ counter--;
+ if (counter <= 0)
+ counter = 0;
+ rectfill(bitmap, 25, 36, 306, 227, 0);
+ for (index = 0; index < 16; index++) {
+ textout_ex(bitmap, font, hl[counter + index], 26, yet_another_index, 4,
+ makecol(0, 0, 0));
+ yet_another_index += 12;
+ }
+ yet_another_index = 40;
+ for (way = 0; way < 8; way++)
+ finish_display();
+ }
+
+ } while (!key[KEY_ESC]);
+ do {
+ rest(5);
+ if (NeedsPoll)
+ poll_keyboard();
+ } while (key[KEY_ESC]);
+ return;
+}
+
diff --git a/clean/src/vdc.h b/clean/src/vdc.h
new file mode 100755
index 0000000..d94460d
--- /dev/null
+++ b/clean/src/vdc.h
@@ -0,0 +1,35 @@
+#ifndef __VDC_H
+#define __VDC_H
+
+#define BMPW 340
+#define BMPH 250
+#define WNDW 320
+#define WNDH 240
+
+#define BOX_W MIN(512, SCREEN_W-16)
+#define BOX_H MIN(256, (SCREEN_H-64)&0xFFF0)
+
+#define BOX_L ((SCREEN_W - BOX_W) / 2)
+#define BOX_R ((SCREEN_W + BOX_W) / 2)
+#define BOX_T ((SCREEN_H - BOX_H) / 2)
+#define BOX_B ((SCREEN_H + BOX_H) / 2)
+
+extern Byte coltab[];
+extern long clip_low;
+extern long clip_high;
+extern int show_fps;
+
+void init_display(void);
+void draw_display(void);
+void set_textmode(void);
+void draw_region(void);
+void finish_display();
+void close_display(void);
+void grmode(void);
+void display_bg(void);
+void display_msg(char *msg, int waits);
+void clear_collision(void);
+void clearscr(void);
+void abaut(void);
+void help(void);
+#endif
diff --git a/clean/src/vmachine.c b/clean/src/vmachine.c
new file mode 100755
index 0000000..39f0dad
--- /dev/null
+++ b/clean/src/vmachine.c
@@ -0,0 +1,908 @@
+/*
+ * O2EM Free Odyssey2 / Videopac+ Emulator
+ *
+ * Created by Daniel Boris (c) 1997,1998
+ *
+ * Developed by Andre de la Rocha
+ * Arlindo M. de Oliveira
+ *
+ * http://o2em.sourceforge.net
+ *
+ *
+ *
+ * Main O2 machine emulation
+ */
+
+#include
+#include
+#include
+#include "audio.h"
+#include "types.h"
+#include "cpu.h"
+#include "keyboard.h"
+#include "config.h"
+#include "debug.h"
+#include "vdc.h"
+#include "vpp.h"
+#include "timefunc.h"
+#include "voice.h"
+#include "vmachine.h"
+#include "allegro.h"
+
+static Byte x_latch, y_latch;
+static int romlatch = 0;
+static Byte line_count;
+static int fps = FPS_NTSC;
+
+static Byte snapedlines[MAXLINES + 2 * MAXSNAP][256][2];
+
+int evblclk = EVBLCLK_NTSC;
+
+struct resource app_data;
+int frame = 0;
+Byte dbstick1, dbstick2;
+
+int int_clk; /* counter for length of /INT pulses */
+int master_clk; /* Master clock */
+int h_clk; /* horizontal clock */
+unsigned long clk_counter;
+int last_line;
+int key2vcnt = 0;
+int mstate;
+
+int pendirq = 0;
+int enahirq = 1;
+int useforen = 0;
+long regionoff = 0xffff;
+int mxsnap = 2;
+int sproff = 0;
+int tweakedaudio = 0;
+
+Byte rom_table[8][4096];
+
+Byte intRAM[64];
+Byte extRAM[256];
+Byte extROM[1024];
+Byte VDCwrite[256];
+Byte ColorVector[MAXLINES];
+Byte AudioVector[MAXLINES];
+Byte *rom;
+Byte *megarom;
+
+int key2[128];
+
+static unsigned int key_map[6][8] = {
+ { KEY_0, KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_7 },
+ { KEY_8, KEY_9, 0, 0, KEY_SPACE, KEY_SLASH, KEY_L, KEY_P },
+ { KEY_PLUS_PAD, KEY_W, KEY_E, KEY_R, KEY_T, KEY_U, KEY_I, KEY_O },
+ { KEY_Q, KEY_S, KEY_D, KEY_F, KEY_G, KEY_H, KEY_J, KEY_K },
+ { KEY_A, KEY_Z, KEY_X, KEY_C, KEY_V, KEY_B, KEY_M, KEY_STOP },
+ { KEY_MINUS, KEY_ASTERISK, KEY_SLASH_PAD, KEY_EQUALS, KEY_Y, KEY_N, KEY_DEL, KEY_ENTER }
+};
+
+static void do_kluges(void);
+static void setvideomode(int t);
+
+void run(void)
+{
+ while (!key_done) {
+ if (key_debug) {
+ app_data.debug = 1;
+ set_textmode();
+ mute_audio();
+ mute_voice();
+ debug();
+ grmode();
+ app_data.debug = 0;
+ init_keyboard();
+ init_sound_stream();
+ }
+ cpu_exec();
+ }
+ close_audio();
+ close_voice();
+ close_display();
+}
+
+void handle_vbl(void)
+{
+ if (!app_data.debug) {
+ handle_key();
+ update_audio();
+ update_voice();
+ }
+ draw_region();
+ ext_IRQ();
+ mstate = 1;
+}
+
+void handle_evbl(void)
+{
+ static long last = 0;
+ static int rest_cnt = 0;
+ int i;
+
+#ifndef ALLEGRO_DOS
+ rest(0);
+#endif
+ i = (15 * app_data.speed / 100);
+ rest_cnt = (rest_cnt + 1) % (i < 5 ? 5 : i);
+#ifdef ALLEGRO_WINDOWS
+ if (rest_cnt==0) rest(1);
+#endif
+ last_line = 0;
+ master_clk -= evblclk;
+ frame++;
+ if (!app_data.debug) {
+ finish_display();
+ }
+
+ if (app_data.crc == 0xA7344D1F) {
+ for (i = 0; i < 140; i++) {
+ ColorVector[i] = (VDCwrite[0xA3] & 0x7f) | (p1 & 0x80);
+ AudioVector[i] = VDCwrite[0xAA];
+ }
+ }/*Atlantis*/
+ else
+ for (i = 0; i < MAXLINES; i++) {
+ ColorVector[i] = (VDCwrite[0xA3] & 0x7f) | (p1 & 0x80);
+ AudioVector[i] = VDCwrite[0xAA];
+ }
+
+ if (key2vcnt++ > 10) {
+ key2vcnt = 0;
+ for (i = 0; i < 128; i++)
+ key2[i] = 0;
+ dbstick1 = dbstick2 = 0;
+ }
+ if (app_data.limit) {
+ long d, f;
+ d = (TICKSPERSEC * 100) / (app_data.speed * fps);
+ f = ((d - gettimeticks() + last) * 1000) / TICKSPERSEC;
+ if (f > 0) {
+#ifdef ALLEGRO_WINDOWS
+ f = f-(f%10);
+ if (f>5) rest(f-5);
+#else
+#ifndef ALLEGRO_DOS
+ rest(0);
+#endif
+#endif
+ }
+ while (gettimeticks() - last < d);
+ last = gettimeticks();
+ }
+ mstate = 0;
+}
+
+void handle_evbll(void)
+{
+ static long last = 0;
+ static int rest_cnt = 0;
+ int i;
+
+#ifndef ALLEGRO_DOS
+ rest(0);
+#endif
+ i = (15 * app_data.speed / 100);
+ rest_cnt = (rest_cnt + 1) % (i < 5 ? 5 : i);
+#ifdef ALLEGRO_WINDOWS
+ if (rest_cnt==0) rest(1);
+#endif
+
+ /******************* 150 */
+
+ for (i = 150; i < MAXLINES; i++) {
+ ColorVector[i] = (VDCwrite[0xA3] & 0x7f) | (p1 & 0x80);
+ AudioVector[i] = VDCwrite[0xAA];
+ }
+
+ if (key2vcnt++ > 10) {
+ key2vcnt = 0;
+ for (i = 0; i < 128; i++)
+ key2[i] = 0;
+ dbstick1 = dbstick2 = 0;
+ }
+ if (app_data.limit) {
+ long d, f;
+ d = (TICKSPERSEC * 100) / (app_data.speed * fps);
+ f = ((d - gettimeticks() + last) * 1000) / TICKSPERSEC;
+ if (f > 0) {
+#ifdef ALLEGRO_WINDOWS
+ f = f-(f%10);
+ if (f>5) rest(f-5);
+#else
+#ifndef ALLEGRO_DOS
+ rest(0);
+#endif
+#endif
+ }
+ while (gettimeticks() - last < d)
+ ;
+ last = gettimeticks();
+ }
+ mstate = 0;
+}
+
+void init_system(void)
+{
+ int i, j, k;
+
+ last_line = 0;
+ dbstick1 = 0x00;
+ dbstick2 = 0x00;
+ mstate = 0;
+ master_clk = 0;
+ h_clk = 0;
+ line_count = 0;
+ itimer = 0;
+ clk_counter = 0;
+ init_roms();
+ for (i = 0; i < 256; i++) {
+ VDCwrite[i] = 0;
+ extRAM[i] = 0;
+ }
+ for (i = 0; i < 64; i++) {
+ intRAM[i] = 0;
+ }
+ for (i = 0; i < MAXLINES; i++)
+ AudioVector[i] = ColorVector[i] = 0;
+
+ for (i = 0; i < MAXLINES + 2 * MAXSNAP; i++)
+ for (j = 0; j < 256; j++)
+ for (k = 0; k < 2; k++)
+ snapedlines[i][j][k] = 0;
+
+ if (app_data.stick[0] == 2 || app_data.stick[1] == 2) {
+ i = install_joystick(JOY_TYPE_AUTODETECT);
+ if (i || (num_joysticks < 1)) {
+ fprintf(stderr, "Error: no joystick detected\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+ for (i = 0; i < 128; i++)
+ key2[i] = 0;
+ key2vcnt = 0;
+ if (app_data.euro)
+ setvideomode(1);
+ else
+ setvideomode(0);
+ do_kluges();
+ init_vpp();
+ clear_collision();
+}
+
+void init_roms(void)
+{
+ rom = rom_table[0];
+ romlatch = 0;
+}
+
+Byte read_t1(void)
+{
+ /*17*/
+ if ((h_clk > 16) || (master_clk > VBLCLK))
+ return 1;
+ else
+ return 0;
+}
+
+void write_p1(Byte d)
+{
+ if ((d & 0x80) != (p1 & 0x80)) {
+ int i, l;
+ l = snapline((int) ((float) master_clk / 22.0 + 0.1), VDCwrite[0xA3],
+ 1);
+ for (i = l; i < MAXLINES; i++)
+ ColorVector[i] = (VDCwrite[0xA3] & 0x7f) | (d & 0x80);
+ }
+ p1 = d;
+ if (app_data.bank == 2) {
+ rom = rom_table[~p1 & 0x01];
+ } else if (app_data.bank == 3) {
+ rom = rom_table[~p1 & 0x03];
+ } else if (app_data.bank == 4) {
+ rom = rom_table[(p1 & 1) ? 0 : romlatch];
+ }
+}
+
+Byte read_P2(void)
+{
+ int i, si, so, km;
+
+ if (NeedsPoll)
+ poll_keyboard();
+
+ if (!(p1 & 0x04)) {
+ si = (p2 & 7);
+ so = 0xff;
+ if (si < 6) {
+ for (i = 0; i < 8; i++) {
+ km = key_map[si][i];
+ if ((key[km]
+ && ((!joykeystab[km]) || (key_shifts & KB_CAPSLOCK_FLAG)))
+ || (key2[km])) {
+ so = i ^ 0x07;
+ }
+ }
+ }
+ if (so != 0xff) {
+ p2 = p2 & 0x0F;
+ p2 = p2 | (so << 5);
+ } else {
+ p2 = p2 | 0xF0;
+ }
+ } else {
+ p2 = p2 | 0xF0;
+ }
+ return (p2);
+}
+
+Byte ext_read(ADDRESS adr)
+{
+ Byte d;
+ Byte si;
+ Byte m;
+ int i;
+
+ if (!(p1 & 0x08) && !(p1 & 0x40)) {
+ /* Handle VDC Read */
+ switch (adr) {
+ case 0xA1:
+ d = VDCwrite[0xA0] & 0x02;
+ if (master_clk > VBLCLK)
+ d = d | 0x08;
+ if (h_clk < (LINECNT - 7))
+ d = d | 0x01;
+ if (sound_IRQ)
+ d = d | 0x04;
+ sound_IRQ = 0;
+ return d;
+ case 0xA2:
+ si = VDCwrite[0xA2];
+ m = 0x01;
+ d = 0;
+ for (i = 0; i < 8; i++) {
+ if (si & m) {
+ if (coltab[1] & m)
+ d = d | (coltab[1] & (m ^ 0xFF));
+ if (coltab[2] & m)
+ d = d | (coltab[2] & (m ^ 0xFF));
+ if (coltab[4] & m)
+ d = d | (coltab[4] & (m ^ 0xFF));
+ if (coltab[8] & m)
+ d = d | (coltab[8] & (m ^ 0xFF));
+ if (coltab[0x10] & m)
+ d = d | (coltab[0x10] & (m ^ 0xFF));
+ if (coltab[0x20] & m)
+ d = d | (coltab[0x20] & (m ^ 0xFF));
+ if (coltab[0x80] & m)
+ d = d | (coltab[0x80] & (m ^ 0xFF));
+ }
+ m = m << 1;
+ }
+ clear_collision();
+ return d;
+ case 0xA5:
+ if (!(VDCwrite[0xA0] & 0x02)) {
+ return x_latch;
+ } else {
+ x_latch = h_clk * 12;
+ return x_latch;
+ }
+ case 0xA4:
+ if (!(VDCwrite[0xA0] & 0x02)) {
+ return y_latch;
+ } else {
+ y_latch = master_clk / 22;
+ if (y_latch > 241)
+ y_latch = 0xFF;
+ return y_latch;
+ }
+ default:
+ return VDCwrite[adr];
+ }
+ } else if (!(p1 & 0x10)) {
+ /* Handle ext RAM Read */
+ if (app_data.megaxrom && (adr >= 0x80)) {
+ /* MegaCART registers are mirrored every 4 bytes */
+ if ((adr & 0x83) == 0x83) {
+ /* TODO: emulate EEPROM data in */
+ return 0xff;
+ } else
+ return extRAM[adr & 0x83];
+ } else
+ return extRAM[adr & 0xFF];
+ } else if (!(p1 & 0x20)) {
+ /* Read a Videopac+ register */
+ return vpp_read(adr);
+ } else if (app_data.exrom && (p1 & 0x02)) {
+ /* Handle read from exrom */
+ return extROM[(p2 << 8) | (adr & 0xFF)];
+ } else if (app_data.megaxrom && !(p1 & 0x02) && !(p1 & 0x40)) {
+ /* Handle data read from MegaCART */
+ return megarom[(extRAM[0x81] << 12) | ((p2 & 0x0f) << 8) | (adr & 0xff)];
+ }
+
+ return 0;
+}
+
+Byte in_bus(void)
+{
+ Byte si = 0, d = 0, mode = 0, jn = 0, sticknum = 0;
+
+ if ((p1 & 0x08) && (p1 & 0x10)) {
+ /* Handle joystick read */
+ if (!(p1 & 0x04)) {
+ si = (p2 & 7);
+ }
+ d = 0xFF;
+ if (si == 1) {
+ mode = app_data.stick[0];
+ jn = 0;
+ sticknum = app_data.sticknumber[0] - 1;
+ } else {
+ mode = app_data.stick[1];
+ jn = 1;
+ sticknum = app_data.sticknumber[1] - 1;
+ }
+ switch (mode) {
+ case 1:
+ d = keyjoy(jn);
+ break;
+ case 2:
+ poll_joystick();
+ if (joy[sticknum].stick[0].axis[1].d1)
+ d &= 0xFE; // joy_up
+ if (joy[sticknum].stick[0].axis[0].d2)
+ d &= 0xFD; // joy_right
+ if (joy[sticknum].stick[0].axis[1].d2)
+ d &= 0xFB; // joy_down
+ if (joy[sticknum].stick[0].axis[0].d1)
+ d &= 0xF7; // joy_left
+ if (joy[sticknum].button[0].b || joy[jn].button[1].b)
+ d &= 0xEF; // both main-buttons
+ break;
+ }
+ if (si == 1) {
+ if (dbstick1)
+ d = dbstick1;
+ } else {
+ if (dbstick2)
+ d = dbstick2;
+ }
+ }
+ return d;
+}
+
+void ext_write(Byte dat, ADDRESS adr)
+{
+ int i;
+
+ if (!(p1 & 0x08)) {
+ /* Handle VDC Write */
+ if (adr == 0xA0) {
+ if ((VDCwrite[0xA0] & 0x02) && !(dat & 0x02)) {
+ y_latch = master_clk / 22;
+ x_latch = h_clk * 12;
+ if (y_latch > 241)
+ y_latch = 0xFF;
+ }
+ if ((master_clk <= VBLCLK) && (VDCwrite[0xA0] != dat)) {
+ draw_region();
+ }
+ } else if (adr == 0xA3) {
+ int l;
+ l = snapline((int) ((float) master_clk / 22.0 + 0.5), dat, 1);
+ for (i = l; i < MAXLINES; i++)
+ ColorVector[i] = (dat & 0x7f) | (p1 & 0x80);
+ } else if (adr == 0xAA) {
+ for (i = master_clk / 22; i < MAXLINES; i++)
+ AudioVector[i] = dat;
+ } else if ((adr >= 0x40) && (adr <= 0x7f) && ((adr & 2) == 0)) {
+ /* simulate quad: all 4 sub quad position registers
+ * are mapped to the same internal register */
+ adr = adr & 0x71;
+ /* Another minor thing: the y register always returns
+ * bit 0 as 0 */
+ if ((adr & 1) == 0)
+ dat = dat & 0xfe;
+ VDCwrite[adr] = VDCwrite[adr + 4] = VDCwrite[adr + 8] = VDCwrite[adr
+ + 12] = dat;
+ }
+ VDCwrite[adr] = dat;
+ } else if (!(p1 & 0x10) && !(p1 & 0x40)) {
+ adr = adr & 0xFF;
+
+ if (adr < 0x80) {
+ /* Handle ext RAM Write */
+ extRAM[adr] = dat;
+
+ } else {
+ if (app_data.bank == 4) {
+ romlatch = (~dat) & 7;
+ rom = rom_table[(p1 & 1) ? 0 : romlatch];
+ }
+
+ /* Handle The Voice */
+ if (!(dat & 0x20))
+ reset_voice();
+ else {
+ if (adr == 0xE4)
+ set_voice_bank(0);
+ else if ((adr >= 0xE8) && (adr <= 0xEF))
+ set_voice_bank(adr - 0xE7);
+ else if (((adr >= 0x80) && (adr <= 0xDF))
+ || ((adr >= 0xF0) && (adr <= 0xFF)))
+ trigger_voice(adr);
+ }
+ }
+ } else if (!(p1 & 0x20)) {
+ /* Write to a Videopac+ register */
+ vpp_write(dat, adr);
+ }
+}
+
+static void do_kluges(void)
+{
+ if (app_data.crc == 0xA7344D1F)
+ pendirq = 1; /* Atlantis */
+ if (app_data.crc == 0xFB83171E)
+ pendirq = 1; /* Blockout */
+ if (app_data.crc == 0xD38153F6)
+ pendirq = 1; /* Blockout (french) */
+ if (app_data.crc == 0x881CEAE4)
+ pendirq = 1; /* Wall Street */
+
+ if (app_data.crc == 0x9E42E766)
+ useforen = 1; /* Turtles */
+ if (app_data.crc == 0x1C750349)
+ useforen = 1; /* Turtles (European version) */
+ if (app_data.crc == 0x202F2749)
+ useforen = 1; /* Q*bert */
+ if (app_data.crc == 0x06861A9C)
+ useforen = 1; /* Flashpoint 5 (Videopac adaption) */
+
+ if (app_data.crc == 0xFB83171E)
+ enahirq = 0; /* Blockout*/
+ if (app_data.crc == 0xD38153F6)
+ enahirq = 0; /* Blockout (french) */
+
+ if (app_data.crc == 0xFB83171E)
+ regionoff = 1; /* Blockout*/
+ if (app_data.crc == 0xD38153F6)
+ regionoff = 1; /* Blockout (french) */
+ if (app_data.crc == 0x202F2749)
+ regionoff = 0; /* Q*bert */
+ if (app_data.crc == 0x5216771A)
+ regionoff = 1; /* Popeye */
+ if (app_data.crc == 0x0C2E4811)
+ regionoff = 11; /* Out of this World! / Helicopter Rescue! */
+ if (app_data.crc == 0x67069924)
+ regionoff = 11; /* Smithereens! */
+ if (app_data.crc == 0x44D1A8A5)
+ regionoff = 11; /* Smithereens! (European version) */
+ if (app_data.crc == 0x2391C2FB)
+ regionoff = 11; /* Smithereens! + */
+ if (app_data.crc == 0xBB4AD548)
+ regionoff = 11; /* Smithereens! modified 1 */
+ if (app_data.crc == 0x25057C11)
+ regionoff = 11; /* Smithereens! modified 2 */
+ if (app_data.crc == 0xB936BD78)
+ regionoff = 12; /* Type & Tell */
+ if (app_data.crc == 0xAD8B9AE0)
+ regionoff = 2; /* Type & Tell modified 1 */
+ if (app_data.crc == 0x5C02BEE6)
+ regionoff = 2; /* Type & Tell modified 2 */
+ if (app_data.crc == 0xDC30AD3D)
+ regionoff = 10; /* Dynasty! */
+ if (app_data.crc == 0x7810BAD5)
+ regionoff = 8; /* Dynasty! (European) */
+ if (app_data.crc == 0xA7344D1F)
+ regionoff = 0; /* Atlantis */
+ if (app_data.crc == 0xD0BC4EE6)
+ regionoff = 12; /* Frogger */
+ if (app_data.crc == 0xA57D84F3)
+ regionoff = 8; /* Frogger BR */
+ if (app_data.crc == 0x825976A9)
+ regionoff = 0; /* Mousing Cat 8kb */
+ if (app_data.crc == 0xF390BFEC)
+ regionoff = 0; /* Mousing Cat 4kb */
+ if (app_data.crc == 0x61A350E6)
+ regionoff = 0; /* Mousing Cat (french) */
+ if (app_data.crc == 0x3BFEF56B)
+ regionoff = 1; /* Four in 1 Row! */
+ if (app_data.crc == 0x7C747245)
+ regionoff = 1; /* Four in 1 Row! modified */
+ if (app_data.crc == 0x9B5E9356)
+ regionoff = 1; /* Four in 1 Row! (french) */
+
+ if (app_data.crc == 0x6CEBAB74)
+ regionoff = 12; /* P.T. Barnum's Acrobats! (European version) */
+ if (app_data.crc == 0xE7B26A56)
+ regionoff = 12; /* P.T. Barnum's Acrobats! (European version - Extra keys) */
+
+ if (app_data.crc == 0xFB83171E)
+ mxsnap = 3; /* Blockout*/
+ if (app_data.crc == 0xD38153F6)
+ mxsnap = 3; /* Blockout (french) */
+ if (app_data.crc == 0xA57E1724)
+ mxsnap = 12; /* Catch the Ball / Noughts and Crosses */
+ if (app_data.crc == 0xBE4FF48E)
+ mxsnap = 12; /* Catch the Ball / Noughts and Crosses modified */
+ if (app_data.crc == 0xFD179F6D)
+ mxsnap = 3; /* Clay Pigeon! */
+ if (app_data.crc == 0x9C9DDDF9)
+ mxsnap = 3; /* Verkehr */
+ if (app_data.crc == 0x95936B07)
+ mxsnap = 3; /* Super Cobra */
+ if (app_data.crc == 0x881CEAE4)
+ mxsnap = 3; /* Wall Street */
+ if (app_data.crc == 0x9E42E766)
+ mxsnap = 0; /* Turtles */
+ if (app_data.crc == 0x1C750349)
+ mxsnap = 0; /* Turtles (European version) */
+ if (app_data.crc == 0xD0BC4EE6)
+ mxsnap = 3; /* Frogger */
+ if (app_data.crc == 0xA57D84F3)
+ mxsnap = 3; /* Frogger BR */
+ if (app_data.crc == 0x3BFEF56B)
+ mxsnap = 6; /* Four in 1 Row! */
+ if (app_data.crc == 0x9B5E9356)
+ mxsnap = 6; /* Four in 1 Row! (french) */
+ if (app_data.crc == 0x7C747245)
+ mxsnap = 6; /* Four in 1 Row! modified */
+
+ if (app_data.crc == 0xA7344D1F)
+ setvideomode(1); /* Atlantis */
+ if (app_data.crc == 0x39E31BF0)
+ setvideomode(1); /* Jake */
+ if (app_data.crc == 0x92D0177B)
+ setvideomode(1); /* Jake (hack) */
+ if (app_data.crc == 0x3351FEDA)
+ setvideomode(1); /* Power Lords */
+ if (app_data.crc == 0x40AE062D)
+ setvideomode(1); /* Power Lords (alternate) */
+ if (app_data.crc == 0xD158EEBA)
+ setvideomode(1); /* Labirinth */
+ if (app_data.crc == 0x26B0FF5B)
+ setvideomode(1); /* Nightmare */
+ if (app_data.crc == 0xDF36683F)
+ setvideomode(1); /* Shark Hunter */
+ if (app_data.crc == 0xAF307559)
+ setvideomode(1); /* Super Bee 8Kb */
+ if (app_data.crc == 0x9585D511)
+ setvideomode(1); /* Super Bee 4Kb */
+ if (app_data.crc == 0x58FA6766)
+ setvideomode(1); /* War of the Nerves */
+ if (app_data.crc == 0x58FA6766)
+ setvideomode(1); /* War of the Nerves */
+ if (app_data.crc == 0x39989464)
+ setvideomode(1); /* Hockey! / Soccer! */
+ if (app_data.crc == 0x3BFEF56B)
+ setvideomode(1); /* Four in 1 Row! */
+ if (app_data.crc == 0x9B5E9356)
+ setvideomode(1); /* Four in 1 Row! (french) */
+ if (app_data.crc == 0x7C747245)
+ setvideomode(1); /* Four in 1 Row! modified */
+ if (app_data.crc == 0x68560DC7)
+ setvideomode(1); /* Jopac Moto Crash */
+ if (app_data.crc == 0x020FCA15)
+ setvideomode(1); /* Jopac Moto Crash modified (non VP+) */
+ if (app_data.crc == 0xC4134DF8)
+ setvideomode(1); /* Helicopter Rescue + */
+ if (app_data.crc == 0x0D2D721D)
+ setvideomode(1); /* Trans American Rally + */
+ if (app_data.crc == 0x9D72D4E9)
+ setvideomode(1); /* Blobbers */
+ if (app_data.crc == 0xB2F0F0B4)
+ setvideomode(1); /* Le Tresor Englouti + */
+ if (app_data.crc == 0x0B2DEB61)
+ setvideomode(1); /* Tutankham */
+ if (app_data.crc == 0x313547EB)
+ setvideomode(1); /* VP53 */
+ if (app_data.crc == 0x06861A9C)
+ setvideomode(1); /* Flashpoint 5 (Videopac adaption) */
+ if (app_data.crc == 0xA57E1724)
+ setvideomode(0); /* Catch the Ball / Noughts and Crosses */
+ if (app_data.crc == 0xBE4FF48E)
+ setvideomode(0); /* Catch the Ball / Noughts and Crosses modified */
+ if (app_data.crc == 0xFB83171E)
+ setvideomode(0); /* Blockout*/
+ if (app_data.crc == 0xD38153F6)
+ setvideomode(0); /* Blockout (french) */
+ if (app_data.crc == 0x9BFC3E01)
+ setvideomode(0); /* Demon Attack */
+ if (app_data.crc == 0x50AF9D45)
+ setvideomode(0); /* Demon Attack + */
+ if (app_data.crc == 0x9884EF36)
+ setvideomode(0); /* Demon Attack + modified */
+ if (app_data.crc == 0x4A578DFE)
+ setvideomode(0); /* Restaurant ntsc */
+ if (app_data.crc == 0x863D5E2D)
+ setvideomode(0); /* Shark Hunter ntsc */
+
+ if (app_data.crc == 0xD62814A3)
+ evblclk = 12000; /* Pick Axe Pete */
+ if (app_data.crc == 0xB2FFB353)
+ evblclk = 12000; /* Pick Axe Pete + */
+ if (app_data.crc == 0x81C20196)
+ evblclk = 12000; /* Pick Axe Pete + (modified) */
+
+ if ((app_data.crc == 0xF390BFEC) || (app_data.crc == 0x825976A9)
+ || (app_data.crc == 0x61A350E6)) { /* Mousing Cat */
+ setvideomode(1);
+ evblclk = 7642;
+ }
+
+ if (app_data.crc == 0xD0BC4EE6) { /* Frogger */
+ setvideomode(1);
+ evblclk = 7642;
+
+ }
+ if (app_data.crc == 0x26517E77) { /* Commando Noturno */
+ setvideomode(1);
+ evblclk = 6100;
+ regionoff = 12;
+ }
+ if (app_data.crc == 0xA57E1724) { /* Catch the ball*/
+ regionoff = 5;
+ sproff = 1;
+
+ }
+
+ if ((app_data.crc == 0x2DCB77F0) || (app_data.crc == 0xF6882734)) { /* Depth Charge / Marksman */
+ setvideomode(1);
+ evblclk = 8000;
+ }
+ if (app_data.crc == 0x881CEAE4) { /* Wall Street */
+ setvideomode(1);
+ evblclk = 6100;
+ }
+ if (app_data.crc == 0xD0BC4EE6)
+ tweakedaudio = 1; /* Frogger */
+ if (app_data.crc == 0xA57D84F3)
+ tweakedaudio = 1; /* Frogger BR */
+ if (app_data.crc == 0x5216771A)
+ tweakedaudio = 1; /* Popeye */
+ if (app_data.crc == 0xAFB23F89)
+ tweakedaudio = 1; /* Musician */
+ if (app_data.crc == 0xC4134DF8)
+ tweakedaudio = 1; /* Helicopter Rescue + */
+ if (app_data.crc == 0x0D2D721D)
+ tweakedaudio = 1; /* Trans American Rally + */
+
+ if (app_data.crc == 0xD3B09FEC)
+ sproff = 1; /* Volleyball! */
+ if (app_data.crc == 0x551E38A2)
+ sproff = 1; /* Volleyball! (french) */
+
+}
+
+int snapline(int pos, Byte reg, int t)
+{
+ int i;
+ if (pos < MAXLINES + MAXSNAP + MAXSNAP) {
+ for (i = 0; i < mxsnap; i++) {
+ if (snapedlines[pos + MAXSNAP - i][reg][t])
+ return pos - i;
+ if (snapedlines[pos + MAXSNAP + i][reg][t])
+ return pos + i;
+ }
+ snapedlines[pos + MAXSNAP][reg][t] = 1;
+ }
+ return pos;
+}
+
+static void setvideomode(int t)
+{
+ if (t) {
+ evblclk = EVBLCLK_PAL;
+ fps = FPS_PAL;
+ } else {
+ evblclk = EVBLCLK_NTSC;
+ fps = FPS_NTSC;
+ }
+}
+
+int savestate(char* filename)
+{
+ FILE *fn;
+
+ fn = fopen(filename, "wb");
+ if (fn == NULL) {
+ fprintf(stderr, "Error opening state-file %s: %i\n", filename, errno);
+ return (errno);
+ }
+
+ fwrite(&app_data.crc, sizeof(app_data.crc), 1, fn);
+ fwrite(&app_data.bios, sizeof(app_data.bios), 1, fn);
+
+ fwrite(VDCwrite, 256, 1, fn);
+ fwrite(extRAM, 256, 1, fn);
+ fwrite(intRAM, 64, 1, fn);
+
+ fwrite(&pc, sizeof(pc), 1, fn);
+ fwrite(&sp, sizeof(sp), 1, fn);
+ fwrite(&bs, sizeof(bs), 1, fn);
+ fwrite(&p1, sizeof(p1), 1, fn);
+ fwrite(&p2, sizeof(p2), 1, fn);
+
+ fwrite(&ac, sizeof(ac), 1, fn);
+ fwrite(&cy, sizeof(cy), 1, fn);
+ fwrite(&f0, sizeof(f0), 1, fn);
+ fwrite(&A11, sizeof(A11), 1, fn);
+ fwrite(&A11ff, sizeof(A11ff), 1, fn);
+
+ fwrite(&timer_on, sizeof(timer_on), 1, fn);
+ fwrite(&count_on, sizeof(count_on), 1, fn);
+ fwrite(®_pnt, sizeof(reg_pnt), 1, fn);
+
+ fwrite(&tirq_en, sizeof(tirq_en), 1, fn);
+ fwrite(&xirq_en, sizeof(xirq_en), 1, fn);
+ fwrite(&irq_ex, sizeof(irq_ex), 1, fn);
+ fwrite(&xirq_pend, sizeof(xirq_pend), 1, fn);
+ fwrite(&tirq_pend, sizeof(tirq_pend), 1, fn);
+
+ fclose(fn);
+ return (0);
+
+}
+
+int loadstate(char* filename)
+{
+ FILE *fn;
+ int bios;
+ unsigned long crc;
+
+ fn = fopen(filename, "rb");
+ if (fn == NULL) {
+ // no savefile yet
+ return (errno);
+ }
+
+ sys_fread(&crc, sizeof(crc), 1, fn);
+ if (crc != app_data.crc) {
+ // wrong cart
+ return (199);
+ }
+
+ sys_fread(&bios, sizeof(bios), 1, fn);
+ if (bios != app_data.bios) // wrong bios
+ {
+ return (200 + bios);
+ }
+
+ sys_fread(VDCwrite, 256, 1, fn);
+ sys_fread(extRAM, 256, 1, fn);
+ sys_fread(intRAM, 64, 1, fn);
+
+ sys_fread(&pc, sizeof(pc), 1, fn);
+ sys_fread(&sp, sizeof(sp), 1, fn);
+ sys_fread(&bs, sizeof(bs), 1, fn);
+ sys_fread(&p1, sizeof(p1), 1, fn);
+ sys_fread(&p2, sizeof(p2), 1, fn);
+
+ sys_fread(&ac, sizeof(ac), 1, fn);
+ sys_fread(&cy, sizeof(cy), 1, fn);
+ sys_fread(&f0, sizeof(f0), 1, fn);
+ sys_fread(&A11, sizeof(A11), 1, fn);
+ sys_fread(&A11ff, sizeof(A11ff), 1, fn);
+
+ sys_fread(&timer_on, sizeof(timer_on), 1, fn);
+ sys_fread(&count_on, sizeof(count_on), 1, fn);
+ sys_fread(®_pnt, sizeof(reg_pnt), 1, fn);
+
+ sys_fread(&tirq_en, sizeof(tirq_en), 1, fn);
+ sys_fread(&xirq_en, sizeof(xirq_en), 1, fn);
+ sys_fread(&irq_ex, sizeof(irq_ex), 1, fn);
+ sys_fread(&xirq_pend, sizeof(xirq_pend), 1, fn);
+ sys_fread(&tirq_pend, sizeof(tirq_pend), 1, fn);
+ fclose(fn);
+ return (0);
+}
+
+size_t sys_fread(void *ptr, size_t size, size_t nitems, FILE *stream)
+{
+ return fread(ptr, size, nitems, stream);
+}
diff --git a/clean/src/vmachine.h b/clean/src/vmachine.h
new file mode 100755
index 0000000..50ce8a3
--- /dev/null
+++ b/clean/src/vmachine.h
@@ -0,0 +1,101 @@
+#ifndef VMACHINE_H
+#define VMACHINE_H
+
+#include "types.h"
+
+#define LINECNT 21
+#define MAXLINES 500
+#define MAXSNAP 50
+
+#define VBLCLK 5493
+#define EVBLCLK_NTSC 5964
+#define EVBLCLK_PAL 7259
+
+#define FPS_NTSC 60
+#define FPS_PAL 50
+
+extern Byte dbstick1, dbstick2;
+extern int last_line;
+
+extern int evblclk;
+
+extern int master_clk; /* Master clock */
+extern int int_clk; /* counter for length of /INT pulses for JNI */
+extern int h_clk; /* horizontal clock */
+extern Byte coltab[256];
+extern int mstate;
+
+extern Byte rom_table[8][4096];
+extern Byte intRAM[];
+extern Byte extRAM[];
+extern Byte extROM[];
+extern Byte VDCwrite[256];
+extern Byte ColorVector[MAXLINES];
+extern Byte AudioVector[MAXLINES];
+extern Byte *rom;
+extern Byte *megarom;
+
+extern int frame;
+extern int key2[128];
+extern int key2vcnt;
+extern unsigned long clk_counter;
+
+extern int enahirq;
+extern int pendirq;
+extern int useforen;
+extern long regionoff;
+extern int sproff;
+extern int tweakedaudio;
+
+Byte read_P2(void);
+int snapline(int pos, Byte reg, int t);
+void ext_write(Byte dat, ADDRESS adr);
+Byte ext_read(ADDRESS adr);
+void handle_vbl(void);
+void handle_evbl(void);
+void handle_evbll(void);
+Byte in_bus(void);
+void write_p1(Byte d);
+Byte read_t1(void);
+void init_system(void);
+void init_roms(void);
+void run(void);
+int savestate(char* filename);
+int loadstate(char* filename);
+size_t sys_fread(void * ptr, size_t size, size_t nitems, FILE * stream);
+
+extern struct resource {
+ int bank;
+ int debug;
+ int stick[2];
+ int sticknumber[2];
+ int limit;
+ int sound_en;
+ int speed;
+ int wsize;
+ int fullscreen;
+ int scanlines;
+ int voice;
+ int svolume;
+ int vvolume;
+ int exrom;
+ int three_k;
+ int filter;
+ int euro;
+ int openb;
+ int megaxrom;
+ int vpp;
+ int bios;
+ unsigned long crc;
+ char *window_title;
+ char *scshot;
+ int scoretype;
+ int scoreaddress;
+ int default_highscore;
+ int breakpoint;
+ char *statefile;
+} app_data;
+
+
+#endif /* VMACHINE_H */
+
diff --git a/clean/src/voice.c b/clean/src/voice.c
new file mode 100755
index 0000000..1c4a4e9
--- /dev/null
+++ b/clean/src/voice.c
@@ -0,0 +1,158 @@
+/*
+ * O2EM Free Odyssey2 / Videopac+ Emulator
+ *
+ * Created by Daniel Boris (c) 1997,1998
+ *
+ * Developed by Andre de la Rocha
+ * Arlindo M. de Oliveira
+ *
+ * http://o2em.sourceforge.net
+ *
+ *
+ *
+ * O2 Voice emulation
+ */
+
+#include
+#include "vmachine.h"
+#include "cpu.h"
+#include "voice.h"
+#include "allegro.h"
+
+static SAMPLE *voices[9][128];
+static int voice_bank = 0;
+static int voice_num = -1;
+static int voice_addr = 0;
+static int voice_ok = 0;
+static int voice_st = 0;
+static unsigned long clk_voice_start = 0;
+
+void load_voice_samples(char *path)
+{
+ int bank, sam, i, ld = 0;
+ char name[MAXC];
+ SAMPLE *sp = NULL;
+
+ printf("Loading voice samples... ");
+ fflush(stdout);
+
+ for (i = 0; i < 9; i++) {
+ for (sam = 0; sam < 128; sam++) {
+ if (i)
+ bank = 0xE8 + i - 1;
+ else
+ bank = 0xE4;
+ sprintf(name, "%svoice/%02x%02x.wav", path, bank, sam + 0x80);
+
+ voices[i][sam] = load_sample(name);
+
+ if (!voices[i][sam]) {
+ sprintf(name, "%svoice/%02X%02X.WAV", path, bank, sam + 0x80);
+ voices[i][sam] = load_sample(name);
+ }
+
+ if (voices[i][sam]) {
+ ld++;
+ if (!sp)
+ sp = voices[i][sam];
+ }
+ }
+ }
+
+ printf("%d samples loaded\n", ld);
+
+ if (ld > 0) {
+ voice_num = allocate_voice(sp);
+ if (voice_num != -1)
+ voice_ok = 1;
+ else {
+ printf(" ERROR: could not allocate sound card voice\n");
+ voice_ok = 0;
+ }
+ }
+
+}
+
+void update_voice(void)
+{
+ if (!voice_ok)
+ return;
+ if (voice_st == 2) {
+ if (voice_get_position(voice_num) < 0) {
+ if ((voice_bank >= 0) && (voice_bank < 9) && (voice_addr >= 0x80)
+ && (voice_addr <= 0xff)) {
+ if (voices[voice_bank][voice_addr - 0x80]) {
+ reallocate_voice(voice_num,
+ voices[voice_bank][voice_addr - 0x80]);
+ voice_set_volume(voice_num, (255 * app_data.vvolume) / 100);
+ voice_start(voice_num);
+ clk_voice_start = clk_counter;
+ voice_st = 1;
+ } else {
+ voice_st = 0;
+ }
+ }
+ }
+ } else if (voice_st == 1) {
+ if ((voice_get_position(voice_num) < 0)
+ || (clk_counter - clk_voice_start > 20)) {
+ voice_st = 0;
+ }
+ }
+}
+
+void trigger_voice(int addr)
+{
+ if (voice_ok) {
+ if (voice_st)
+ update_voice();
+ if ((voice_st == 0) && (voice_bank >= 0) && (voice_bank < 9)
+ && (addr >= 0x80) && (addr <= 0xff)) {
+ voice_addr = addr;
+ voice_st = 2;
+ update_voice();
+ }
+ }
+}
+
+void set_voice_bank(int bank)
+{
+ if (!voice_ok)
+ return;
+ if ((bank >= 0) && (bank <= 8))
+ voice_bank = bank;
+}
+
+int get_voice_status(void)
+{
+ if (voice_ok) {
+ update_voice();
+ if (voice_st)
+ return 1;
+ }
+ return 0;
+}
+
+void reset_voice(void)
+{
+ if (voice_ok) {
+ voice_stop(voice_num);
+ voice_bank = 0;
+ voice_addr = 0;
+ voice_st = 0;
+ }
+}
+
+void mute_voice(void)
+{
+ if (voice_ok) {
+ voice_stop(voice_num);
+ }
+}
+
+void close_voice(void)
+{
+ reset_voice();
+ voice_ok = 0;
+}
+
diff --git a/clean/src/voice.h b/clean/src/voice.h
new file mode 100755
index 0000000..62a8c06
--- /dev/null
+++ b/clean/src/voice.h
@@ -0,0 +1,14 @@
+#ifndef __VOICE_H
+#define __VOICE_H
+
+void load_voice_samples(char *path);
+void update_voice(void);
+void trigger_voice(int addr);
+void reset_voice(void);
+void set_voice_bank(int bank);
+void close_voice(void);
+void mute_voice(void);
+int get_voice_status(void);
+
+#endif
+
diff --git a/clean/src/vpp.c b/clean/src/vpp.c
new file mode 100755
index 0000000..b2e9b7b
--- /dev/null
+++ b/clean/src/vpp.c
@@ -0,0 +1,549 @@
+/*
+ * O2EM Free Odyssey2 / Videopac+ Emulator
+ *
+ * Created by Daniel Boris (c) 1997,1998
+ *
+ * Developed by Andre de la Rocha
+ * Arlindo M. de Oliveira
+ *
+ * http://o2em.sourceforge.net
+ *
+ *
+ *
+ * Videopac+ G7400 emulation
+ */
+
+#include
+#include
+#include
+#include "types.h"
+#include "vmachine.h"
+#include "vdc.h"
+#include "vpp_cset.h"
+#include "vpp.h"
+#include "allegro.h"
+
+static void vpp_draw_char(int x, int y, Byte ch, Byte c0, Byte c1, Byte ext,
+ Byte dw, Byte dh, Byte ul);
+static void vpp_update_screen(void);
+
+static Byte LumReg = 0xff, TraReg = 0xff;
+static BITMAP *vppbmp = NULL;
+static Byte *colplus = NULL;
+static int vppon = 1;
+static int vpp_cx = 0;
+static int vpp_cy = 0;
+static Byte vpp_data = 0;
+static int inc_curs = 1;
+static int slice = 0;
+static int vpp_y0 = 0;
+static Byte vpp_r = 0;
+Byte dchars[2][960];
+Byte vpp_mem[40][32][4];
+static int frame_cnt = 0;
+static int blink_st = 0;
+static int slicemode = 0;
+static int need_update = 0;
+
+Byte read_PB(Byte p)
+{
+ p &= 0x3;
+ switch (p) {
+ case 0:
+ return LumReg >> 4;
+ break;
+ case 1:
+ return LumReg & 0xf;
+ break;
+ case 2:
+ return TraReg >> 4;
+ break;
+ case 3:
+ return TraReg & 0xf;
+ break;
+ }
+ return 0;
+}
+
+void write_PB(Byte p, Byte val)
+{
+ p &= 0x3;
+ val &= 0xf;
+
+ switch (p) {
+ case 0:
+ LumReg = (val << 4) | (LumReg & 0xf);
+ break;
+ case 1:
+ LumReg = (LumReg & 0xf0) | val;
+ break;
+ case 2:
+ TraReg = (val << 4) | (TraReg & 0xf);
+ break;
+ case 3:
+ TraReg = (TraReg & 0xf0) | val;
+ break;
+ }
+ need_update = 1;
+}
+
+Byte vpp_read(ADDRESS adr)
+{
+ Byte t;
+ static Byte ta = 0;
+ static Byte tb = 0;
+
+ switch (adr) {
+ case 4:
+ return ta;
+ case 5:
+ /* get return value from last read */
+ t = tb;
+ /* the real VPP starts a read cycle,
+ * the data gets returned at next read */
+ if (slicemode) {
+ Byte ext, chr;
+ chr = vpp_mem[vpp_cx][vpp_cy][0];
+ ext = (vpp_mem[vpp_cx][vpp_cy][1] & 0x80) ? 1 : 0;
+ if (chr < 0xA0) {
+ ta = 0;
+ fprintf(stderr, "unsupported: CHARROM read %d %d %d\n", chr,
+ ext, slice);
+ } else {
+ ta = dchars[ext][(chr - 0xA0) * 10 + slice];
+ ta = ((ta & 0x80) >> 7) | ((ta & 0x40) >> 5)
+ | ((ta & 0x20) >> 3) | ((ta & 0x10) >> 1)
+ | ((ta & 0x08) << 1) | ((ta & 0x04) << 3)
+ | ((ta & 0x02) << 5) | ((ta & 0x01) << 7);
+ }
+ tb = 0xff; /* real VPP seems to return junk */
+ slice = (slice + 1) % 10;
+ } else {
+ ta = vpp_mem[vpp_cx][vpp_cy][1];
+ tb = vpp_mem[vpp_cx][vpp_cy][0];
+ if (inc_curs) {
+ vpp_cx++;
+ if (vpp_cx >= 40) {
+ vpp_cx = 0;
+ vpp_cy++;
+ if (vpp_cy >= 24)
+ vpp_cy = 0;
+ }
+ }
+ }
+ return t;
+ case 6:
+ return 0;
+ default:
+ return 0;
+ }
+}
+
+void vpp_write(Byte dat, ADDRESS adr)
+{
+ static Byte ta;
+
+ switch (adr) {
+ case 0:
+ if (!slicemode)
+ vpp_mem[vpp_cx][vpp_cy][1] = dat;
+ else
+ ta = dat;
+ break;
+ case 1:
+ if (slicemode) {
+ Byte ext, chr;
+ chr = vpp_mem[vpp_cx][vpp_cy][0];
+ ext = (vpp_mem[vpp_cx][vpp_cy][1] & 0x80) ? 1 : 0;
+ if (chr >= 0xA0)
+ dchars[ext][(chr - 0xA0) * 10 + slice] = ((ta & 0x80) >> 7)
+ | ((ta & 0x40) >> 5) | ((ta & 0x20) >> 3)
+ | ((ta & 0x10) >> 1) | ((ta & 0x08) << 1)
+ | ((ta & 0x04) << 3) | ((ta & 0x02) << 5)
+ | ((ta & 0x01) << 7);
+ slice = (slice + 1) % 10;
+ } else {
+ vpp_mem[vpp_cx][vpp_cy][0] = dat;
+ if ((dat > 0x7f) && (dat < 0xa0)
+ && (!(vpp_mem[vpp_cx][vpp_cy][1] & 0x80))) {
+ vpp_mem[vpp_cx][vpp_cy][2] = dat;
+ vpp_mem[vpp_cx][vpp_cy][3] = vpp_mem[vpp_cx][vpp_cy][1];
+ } else {
+ vpp_mem[vpp_cx][vpp_cy][2] = vpp_mem[vpp_cx][vpp_cy][3] = 0;
+ }
+ if (inc_curs) {
+ vpp_cx++;
+ if (vpp_cx >= 40) {
+ vpp_cx = 0;
+ vpp_cy++;
+ if (vpp_cy >= 24)
+ vpp_cy = 0;
+ }
+ }
+ }
+ break;
+ case 2:
+ vpp_data = dat;
+ break;
+ case 3:
+ switch (dat & 0xe0) {
+ case 0x00: /* plus_cmd_brow */
+ vpp_cy = vpp_data & 0x1f;
+ vpp_cx = 0;
+ break;
+ case 0x20: /* plus_cmd_loady */
+ vpp_cy = vpp_data & 0x1f;
+ break;
+ case 0x40: /* plus_cmd_loadx */
+ vpp_cx = (vpp_data & 0x3f) % 40;
+ break;
+ case 0x60: /* plus_cmd_incc */
+ vpp_cx++;
+ if (vpp_cx >= 40) {
+ vpp_cx = 0;
+ vpp_cy++;
+ if (vpp_cy >= 24)
+ vpp_cy = 0;
+ }
+ break;
+ case 0x80: /* plus_cmd_loadm */
+ slicemode = 0;
+ slice = (vpp_data & 0x1f) % 10;
+ switch (vpp_data & 0xe0) {
+ case 0x00: /* plus_loadm_wr */
+ inc_curs = 1;
+ break;
+ case 0x20: /* plus_loadm_rd */
+ inc_curs = 1;
+ break;
+ case 0x40: /* plus_loadm_wrni */
+ inc_curs = 0;
+ break;
+ case 0x60: /* plus_loadm_rdni */
+ inc_curs = 0;
+ break;
+ case 0x80: /* plus_loadm_wrsl */
+ slicemode = 1;
+ break;
+ case 0xA0: /* plus_loadm_rdsl */
+ slicemode = 1;
+ break;
+ default:
+ break;
+ }
+ break;
+ case 0xA0: /* plus_cmd_loadr */
+ vpp_r = vpp_data;
+ break;
+ case 0xC0: /* plus_cmd_loady0 */
+ if (vpp_data & 0x20)
+ fprintf(stderr, "unsupported: global double height");
+ vpp_y0 = (vpp_data & 0x1f) % 24;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ need_update = 1;
+}
+
+void vpp_finish_bmp(Byte *vmem, int offx, int offy, int w, int h, int totw,
+ int toth)
+{
+ int i, x, y, t, c, nc, clrx, clry;
+ int tcol[16], m[8] = { 0x01, 0x10, 0x04, 0x40, 0x02, 0x20, 0x08, 0x80 };
+ Byte *pnt, *pnt2, *pnt3;
+
+ if (vppon) {
+ memset(colplus, 0, BMPW * BMPH);
+ vppon = 0;
+ }
+
+ if (TraReg == 0xff)
+ return;
+
+ vppon = 1;
+
+ frame_cnt--;
+ if (frame_cnt <= 0) {
+ frame_cnt = 100;
+ blink_st = 1 - blink_st;
+ need_update = 1;
+ }
+
+ if (need_update)
+ vpp_update_screen();
+
+ for (i = 0; i < 8; i++)
+ tcol[i] = tcol[i + 8] = !(TraReg & m[i]);
+
+ if (w > totw - offx)
+ w = totw - offx;
+ if (h > toth - offy)
+ h = toth - offy;
+
+ if (w > vppbmp->w)
+ w = vppbmp->w;
+ if (h > vppbmp->h)
+ h = vppbmp->h;
+
+ clrx = clry = 0;
+ for (i = 0; (!clrx) && (i < totw); i++)
+ if (tcol[vmem[offy * totw + i] & 7])
+ clrx = 1;
+ for (i = 0; (!clry) && (i < toth); i++)
+ if (tcol[vmem[i * totw + offx] & 7])
+ clry = 1;
+ if (clrx)
+ for (y = 0; y < offy; y++)
+ for (x = 0; x < totw; x++)
+ vmem[y * totw + x] = 0;
+ if (clry)
+ for (y = 0; y < toth; y++)
+ for (x = 0; x < offx; x++)
+ vmem[y * totw + x] = 0;
+
+ for (y = 0; y < h; y++) {
+ pnt = vmem + (offy + y) * totw + offx;
+ pnt2 = (Byte *) vppbmp->line[y];
+
+ x = 0;
+ while (x < w) {
+ pnt3 = pnt;
+ c = *pnt++;
+ t = x++;
+
+ if ((((x + offx) & 3) == 0) && (sizeof(unsigned long) == 4)) {
+ unsigned long cccc, dddd, *p = (unsigned long*) pnt;
+ int t2 = x, w2 = w - 4;
+ cccc = (((unsigned long) c) & 0xff)
+ | ((((unsigned long) c) & 0xff) << 8)
+ | ((((unsigned long) c) & 0xff) << 16)
+ | ((((unsigned long) c) & 0xff) << 24);
+ dddd = *p++;
+ while ((x < w2) && (dddd == cccc)) {
+ x += 4;
+ dddd = *p++;
+ }
+ pnt += x - t2;
+ }
+
+ if (c < 16) {
+ if (tcol[c]) {
+ if (app_data.openb)
+ for (i = 0; i < x - t; i++)
+ *pnt3++ = *pnt2++ & 0xf;
+ else {
+ memcpy(pnt3, pnt2, x - t);
+ pnt2 += x - t;
+ }
+ } else {
+ for (i = 0; i < x - t; i++) {
+ nc = *pnt2++;
+ if ((nc & 0x10) && app_data.openb) {
+ *pnt3++ = nc & 0xf;
+ } else if (nc & 8) {
+ colplus[pnt3++ - vmem] = 0x40;
+ } else {
+ pnt3++;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+static void vpp_draw_char(int x, int y, Byte ch, Byte c0, Byte c1, Byte ext,
+ Byte dw, Byte dh, Byte ul)
+{
+ int xx, yy, d, m, k;
+
+ if ((x > 39) || (y > 24) || (ext > 1))
+ return;
+
+ d = (dh == 2) ? 5 : 0;
+
+ for (yy = 0; yy < 10; yy++) {
+ if (ul && (d == 9))
+ k = 255;
+ else if (ch >= 0xA0)
+ k = dchars[ext][(ch - 0xA0) * 10 + d];
+ else if (ch >= 0x80)
+ k = 255;
+ else
+ k = vpp_cset[ext][ch * 10 + d];
+
+ m = (dw == 2) ? 0x08 : 0x80;
+
+ for (xx = 0; xx < 8; xx++) {
+ vppbmp->line[y * 10 + yy][x * 8 + xx] = (k & m) ? c1 : c0;
+ if ((xx % 2) || (dw == 0))
+ m >>= 1;
+ }
+ if ((yy % 2) || (dh == 0))
+ d++;
+ }
+}
+
+static void vpp_update_screen(void)
+{
+ int i, x, y, l, chr, attr, ext, c0, c1, dw, dh, hpar, vpar, lvd, lhd,
+ ser_chr, ser_atr, ul, conc, box, swapcol;
+ int tlum[8], m[8] = { 0x01, 0x10, 0x04, 0x40, 0x02, 0x20, 0x08, 0x80 };
+
+ clear(vppbmp);
+
+ for (i = 0; i < 8; i++)
+ tlum[i] = (LumReg & m[i]) ? 0 : 8;
+
+ vpar = lvd = 0;
+ for (y = 0; y < 25; y++) {
+
+ vpar = (lvd == 0) ? 0 : 1 - vpar;
+
+ l = (y == 0) ? 31 : (y - 1 + vpp_y0) % 24;
+ c0 = ul = conc = box = 0;
+
+ hpar = lhd = 0;
+ for (x = 0; x < 40; x++) {
+ hpar = (lhd == 0) ? 0 : 1 - hpar;
+
+ chr = vpp_mem[x][l][0];
+ attr = vpp_mem[x][l][1];
+ c1 = attr & 0x7;
+ c1 = ((c1 & 2) | ((c1 & 1) << 2) | ((c1 & 4) >> 2));
+ ext = (attr & 0x80) ? 1 : 0;
+
+ ser_chr = vpp_mem[x][l][2];
+ ser_atr = vpp_mem[x][l][3];
+ if (ser_chr) {
+ c0 = (ser_atr >> 4) & 0x7;
+ c0 = ((c0 & 2) | ((c0 & 1) << 2) | ((c0 & 4) >> 2));
+ ul = ser_chr & 4;
+ conc = ser_chr & 1;
+ box = ser_chr & 2;
+ }
+
+ if (ext) {
+ c0 = (attr >> 4) & 0x7;
+ c0 = ((c0 & 2) | ((c0 & 1) << 2) | ((c0 & 4) >> 2));
+ dw = dh = 0;
+ } else {
+ dw = (attr & 0x20) ? (hpar ? 2 : 1) : 0;
+ dh = (attr & 0x10) ? (vpar ? 2 : 1) : 0;
+ if (dw)
+ lhd = 1;
+ if (dh)
+ lvd = 1;
+ }
+
+ swapcol = 0;
+
+ /* cursor display */
+ if ((x == vpp_cx) && (l == vpp_cy)) {
+ /* on cursor position */
+ if (vpp_r & 0x10) {
+ /* cursor display active */
+ swapcol = !swapcol;
+ if ((vpp_r & 0x80) && blink_st) {
+ /* blinking active */
+ swapcol = !swapcol;
+ }
+ }
+ }
+
+ /* invert attribute */
+ if ((!ext) && (attr & 0x40))
+ swapcol = !swapcol;
+
+ /* blinking chars */
+ if ((vpp_r & 0x80) && !(attr & 8) && !blink_st) {
+ /* cursor handling is done already */
+ if (!(vpp_r & 0x10) || (x != vpp_cx) || (l != vpp_cy)) {
+ c1 = c0;
+ }
+ }
+
+ if (((y == 0) && (vpp_r & 8)) || ((y != 0) && (vpp_r & 1))) {
+ if ((!conc) || (!(vpp_r & 4))) {
+ if (box || (!(vpp_r & 2))) {
+ if (swapcol)
+ vpp_draw_char(x, y, chr, c1 | tlum[c1],
+ c0 | tlum[c0], ext, dw, dh, ul);
+ else
+ vpp_draw_char(x, y, chr, c0 | tlum[c0],
+ c1 | tlum[c1], ext, dw, dh, ul);
+ } else {
+ vpp_draw_char(x, y, 255, (app_data.openb) ? 16 : 0, 0,
+ 0, 0, 0, 0);
+ }
+ }
+ }
+ }
+
+ }
+
+ if (vpp_r & 0x20) {
+ for (y = vppbmp->h - 1; y >= 10; y--)
+ for (x = 0; x < vppbmp->w; x++)
+ vppbmp->line[y][x] = vppbmp->line[(y - 10) / 2 + 10][x];
+ }
+
+ need_update = 0;
+}
+
+void load_colplus(Byte *col)
+{
+ if (vppon)
+ memcpy(col, colplus, BMPW * BMPH);
+ else
+ memset(col, 0, BMPW * BMPH);
+}
+
+void init_vpp(void)
+{
+ int i, j, k;
+
+ if (!vppbmp)
+ vppbmp = create_bitmap(320, 250);
+ if (!colplus)
+ colplus = (Byte *) malloc(BMPW * BMPH);
+
+ if ((!vppbmp) || (!colplus)) {
+ fprintf(stderr,
+ "Could not allocate memory for Videopac+ screen buffer.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ clear(vppbmp);
+ memset(colplus, 0, BMPW * BMPH);
+
+ LumReg = TraReg = 0xff;
+ vpp_cx = 0;
+ vpp_cy = 0;
+ vpp_y0 = 0;
+ vpp_r = 0;
+ inc_curs = 1;
+ vpp_data = 0;
+ frame_cnt = 0;
+ blink_st = 0;
+ slice = 0;
+ slicemode = 0;
+ need_update = 1;
+ vppon = 1;
+
+ for (i = 0; i < 2; i++)
+ for (j = 0; j < 960; j++)
+ dchars[i][j] = 0;
+
+ for (i = 0; i < 40; i++)
+ for (j = 0; j < 32; j++)
+ for (k = 0; k < 4; k++)
+ vpp_mem[i][j][k] = 0;
+}
+
diff --git a/clean/src/vpp.h b/clean/src/vpp.h
new file mode 100755
index 0000000..a9e1276
--- /dev/null
+++ b/clean/src/vpp.h
@@ -0,0 +1,12 @@
+#ifndef __VPP_H
+#define __VPP_H
+
+Byte read_PB(Byte p);
+void write_PB(Byte p, Byte val);
+Byte vpp_read(ADDRESS adr);
+void vpp_write(Byte dat, ADDRESS adr);
+void vpp_finish_bmp(Byte *vmem, int offx, int offy, int w, int h, int totw, int toth);
+void init_vpp(void);
+void load_colplus(Byte *col);
+
+#endif
diff --git a/clean/src/vpp_cset.c b/clean/src/vpp_cset.c
new file mode 100755
index 0000000..4ac0f91
--- /dev/null
+++ b/clean/src/vpp_cset.c
@@ -0,0 +1,285 @@
+
+/*
+ * O2EM Free Odyssey2 / Videopac+ Emulator
+ *
+ * Created by Daniel Boris (c) 1997,1998
+ *
+ * Developed by Andre de la Rocha
+ * Arlindo M. de Oliveira
+ *
+ * http://o2em.sourceforge.net
+ *
+ *
+ *
+ * Videopac+ character table
+ */
+
+
+#include "types.h"
+#include "vpp_cset.h"
+
+
+Byte vpp_cset[2][1280] = {
+ {
+ /* Alphanumeric */
+ 0x00,0x38,0x44,0x40,0x20,0x10,0x00,0x10,0x00,0x00,
+ 0x00,0x10,0x28,0x00,0x38,0x44,0x7c,0x44,0x00,0x00,
+ 0x00,0x08,0x10,0x3c,0x20,0x30,0x20,0x3c,0x00,0x00,
+ 0x00,0x08,0x14,0x10,0x38,0x10,0x24,0x3c,0x00,0x00,
+ 0x00,0x10,0x38,0x50,0x38,0x14,0x54,0x38,0x10,0x00,
+ 0x00,0x38,0x44,0x40,0x40,0x40,0x44,0x38,0x10,0x20,
+ 0x00,0x28,0x28,0x7c,0x28,0x7c,0x28,0x28,0x00,0x00,
+ 0x00,0x20,0x18,0x00,0x38,0x44,0x7c,0x44,0x00,0x00,
+ 0x00,0x20,0x18,0x00,0x44,0x44,0x44,0x38,0x00,0x00,
+ 0x00,0x10,0x08,0x3c,0x20,0x30,0x20,0x3c,0x00,0x00,
+ 0x00,0x3c,0x50,0x50,0x58,0x50,0x50,0x3c,0x00,0x00,
+ 0x00,0x08,0x14,0x3c,0x20,0x30,0x20,0x3c,0x00,0x00,
+ 0x00,0x00,0x10,0x20,0x7f,0x20,0x10,0x00,0x00,0x00,
+ 0x00,0x10,0x38,0x54,0x10,0x10,0x10,0x10,0x10,0x10,
+ 0x00,0x00,0x08,0x04,0xfe,0x04,0x08,0x00,0x00,0x00,
+ 0x10,0x10,0x10,0x10,0x10,0x10,0x54,0x38,0x10,0x00,
+ 0x00,0x18,0x24,0x18,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x10,0x10,0x7c,0x10,0x10,0x00,0x7c,0x00,0x00,
+ 0x00,0x08,0x10,0x38,0x44,0x7c,0x40,0x38,0x00,0x00,
+ 0x00,0x28,0x00,0x38,0x44,0x7c,0x40,0x38,0x00,0x00,
+ 0x00,0x28,0x00,0x30,0x10,0x10,0x10,0x38,0x00,0x00,
+ 0x00,0x00,0x00,0x38,0x40,0x40,0x40,0x38,0x10,0x20,
+ 0x00,0x10,0x28,0x00,0x44,0x44,0x4c,0x34,0x00,0x00,
+ 0x00,0x20,0x10,0x34,0x4c,0x44,0x4c,0x34,0x00,0x00,
+ 0x00,0x00,0x10,0x00,0x7c,0x00,0x10,0x00,0x00,0x00,
+ 0x00,0x20,0x10,0x38,0x44,0x7c,0x40,0x38,0x00,0x00,
+ 0x00,0x00,0x00,0x3c,0x52,0x5e,0x50,0x3e,0x00,0x00,
+ 0x00,0x10,0x28,0x38,0x44,0x7c,0x40,0x38,0x00,0x00,
+ 0x00,0x40,0xc0,0x40,0x44,0x4c,0x14,0x3e,0x04,0x00,
+ 0x00,0x40,0xc0,0x40,0x4c,0x52,0x04,0x08,0x1e,0x00,
+ 0x00,0xe0,0x20,0x40,0x24,0xcc,0x14,0x3e,0x04,0x00,
+ 0x00,0x10,0x28,0x00,0x38,0x44,0x44,0x38,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x10,0x10,0x10,0x10,0x10,0x00,0x10,0x00,0x00,
+ 0x00,0x28,0x28,0x28,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x28,0x00,0x3c,0x20,0x30,0x20,0x3c,0x00,0x00,
+ 0x00,0x10,0x28,0x34,0x4c,0x44,0x4c,0x34,0x00,0x00,
+ 0x00,0x60,0x64,0x08,0x10,0x20,0x4c,0x0c,0x00,0x00,
+ 0x00,0x20,0x50,0x50,0x20,0x54,0x48,0x34,0x00,0x00,
+ 0x00,0x10,0x10,0x20,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x08,0x10,0x20,0x20,0x20,0x10,0x08,0x00,0x00,
+ 0x00,0x20,0x10,0x08,0x08,0x08,0x10,0x20,0x00,0x00,
+ 0x00,0x10,0x54,0x38,0x10,0x38,0x54,0x10,0x00,0x00,
+ 0x00,0x00,0x10,0x10,0x7c,0x10,0x10,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x40,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,
+ 0x01,0x02,0x02,0x04,0x08,0x10,0x20,0x20,0x40,0x80,
+ 0x00,0x10,0x28,0x44,0x44,0x44,0x28,0x10,0x00,0x00,
+ 0x00,0x10,0x30,0x10,0x10,0x10,0x10,0x10,0x00,0x00,
+ 0x00,0x38,0x44,0x04,0x18,0x20,0x40,0x7c,0x00,0x00,
+ 0x00,0x7c,0x04,0x08,0x18,0x04,0x44,0x38,0x00,0x00,
+ 0x00,0x08,0x18,0x28,0x48,0x7c,0x08,0x08,0x00,0x00,
+ 0x00,0x7c,0x40,0x78,0x04,0x04,0x44,0x38,0x00,0x00,
+ 0x00,0x18,0x20,0x40,0x78,0x44,0x44,0x38,0x00,0x00,
+ 0x00,0x7c,0x04,0x08,0x10,0x20,0x20,0x20,0x00,0x00,
+ 0x00,0x38,0x44,0x44,0x38,0x44,0x44,0x38,0x00,0x00,
+ 0x00,0x38,0x44,0x44,0x3c,0x04,0x04,0x38,0x00,0x00,
+ 0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,
+ 0x00,0x00,0x00,0x20,0x00,0x00,0x20,0x20,0x40,0x00,
+ 0x00,0x04,0x08,0x10,0x20,0x10,0x08,0x04,0x00,0x00,
+ 0x00,0x00,0x00,0x7c,0x00,0x7c,0x00,0x00,0x00,0x00,
+ 0x00,0x40,0x20,0x10,0x08,0x10,0x20,0x40,0x00,0x00,
+ 0x00,0x38,0x44,0x04,0x08,0x10,0x00,0x10,0x00,0x00,
+ 0x00,0x38,0x44,0x5c,0x54,0x5c,0x40,0x38,0x00,0x00,
+ 0x00,0x38,0x44,0x44,0x44,0x7c,0x44,0x44,0x00,0x00,
+ 0x00,0x78,0x44,0x44,0x78,0x44,0x44,0x78,0x00,0x00,
+ 0x00,0x38,0x44,0x40,0x40,0x40,0x44,0x38,0x00,0x00,
+ 0x00,0x78,0x44,0x44,0x44,0x44,0x44,0x78,0x00,0x00,
+ 0x00,0x7c,0x40,0x40,0x70,0x40,0x40,0x7c,0x00,0x00,
+ 0x00,0x7c,0x40,0x40,0x70,0x40,0x40,0x40,0x00,0x00,
+ 0x00,0x38,0x44,0x40,0x40,0x4c,0x44,0x3c,0x00,0x00,
+ 0x00,0x44,0x44,0x44,0x7c,0x44,0x44,0x44,0x00,0x00,
+ 0x00,0x38,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00,
+ 0x00,0x1c,0x08,0x08,0x08,0x08,0x48,0x30,0x00,0x00,
+ 0x00,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x00,0x00,
+ 0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x7c,0x00,0x00,
+ 0x00,0x44,0x6c,0x54,0x44,0x44,0x44,0x44,0x00,0x00,
+ 0x00,0x44,0x44,0x64,0x54,0x4c,0x44,0x44,0x00,0x00,
+ 0x00,0x38,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00,
+ 0x00,0x78,0x44,0x44,0x78,0x40,0x40,0x40,0x00,0x00,
+ 0x00,0x38,0x44,0x44,0x44,0x54,0x48,0x34,0x00,0x00,
+ 0x00,0x78,0x44,0x44,0x78,0x50,0x48,0x44,0x00,0x00,
+ 0x00,0x38,0x44,0x40,0x38,0x04,0x44,0x38,0x00,0x00,
+ 0x00,0x7c,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00,
+ 0x00,0x44,0x44,0x44,0x44,0x44,0x44,0x38,0x00,0x00,
+ 0x00,0x44,0x44,0x44,0x28,0x28,0x10,0x10,0x00,0x00,
+ 0x00,0x44,0x44,0x44,0x54,0x54,0x54,0x28,0x00,0x00,
+ 0x00,0x44,0x44,0x28,0x10,0x28,0x44,0x44,0x00,0x00,
+ 0x00,0x44,0x44,0x28,0x10,0x10,0x10,0x10,0x00,0x00,
+ 0x00,0x7c,0x04,0x08,0x10,0x20,0x40,0x7c,0x00,0x00,
+ 0x00,0x1c,0x10,0x10,0x10,0x10,0x10,0x1c,0x00,0x00,
+ 0x80,0x40,0x40,0x20,0x10,0x08,0x04,0x04,0x02,0x01,
+ 0x00,0x38,0x08,0x08,0x08,0x08,0x08,0x38,0x00,0x00,
+ 0x00,0x10,0x28,0x00,0x30,0x10,0x10,0x38,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
+ 0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x34,0x4c,0x44,0x4c,0x34,0x00,0x00,
+ 0x00,0x40,0x40,0x78,0x44,0x44,0x44,0x78,0x00,0x00,
+ 0x00,0x00,0x00,0x38,0x40,0x40,0x40,0x38,0x00,0x00,
+ 0x00,0x04,0x04,0x3c,0x44,0x44,0x44,0x3c,0x00,0x00,
+ 0x00,0x00,0x00,0x38,0x44,0x7c,0x40,0x38,0x00,0x00,
+ 0x00,0x18,0x24,0x20,0x70,0x20,0x20,0x20,0x00,0x00,
+ 0x00,0x00,0x00,0x3c,0x44,0x44,0x3c,0x04,0x24,0x18,
+ 0x00,0x40,0x40,0x58,0x64,0x44,0x44,0x44,0x00,0x00,
+ 0x00,0x10,0x00,0x30,0x10,0x10,0x10,0x38,0x00,0x00,
+ 0x00,0x08,0x00,0x18,0x08,0x08,0x08,0x08,0x48,0x30,
+ 0x00,0x20,0x20,0x24,0x28,0x30,0x28,0x24,0x00,0x00,
+ 0x00,0x30,0x10,0x10,0x10,0x10,0x10,0x38,0x00,0x00,
+ 0x00,0x00,0x00,0x68,0x54,0x54,0x54,0x54,0x00,0x00,
+ 0x00,0x00,0x00,0x58,0x64,0x44,0x44,0x44,0x00,0x00,
+ 0x00,0x00,0x00,0x38,0x44,0x44,0x44,0x38,0x00,0x00,
+ 0x00,0x00,0x00,0x78,0x44,0x44,0x44,0x78,0x40,0x40,
+ 0x00,0x00,0x00,0x3c,0x44,0x44,0x44,0x3c,0x04,0x04,
+ 0x00,0x00,0x00,0x58,0x64,0x40,0x40,0x40,0x00,0x00,
+ 0x00,0x00,0x00,0x38,0x40,0x38,0x04,0x78,0x00,0x00,
+ 0x00,0x20,0x20,0x38,0x20,0x20,0x20,0x18,0x00,0x00,
+ 0x00,0x00,0x00,0x44,0x44,0x44,0x4c,0x34,0x00,0x00,
+ 0x00,0x00,0x00,0x44,0x44,0x28,0x28,0x10,0x00,0x00,
+ 0x00,0x00,0x00,0x44,0x44,0x54,0x54,0x28,0x00,0x00,
+ 0x00,0x00,0x00,0x44,0x28,0x10,0x28,0x44,0x00,0x00,
+ 0x00,0x00,0x00,0x44,0x44,0x4c,0x34,0x04,0x44,0x38,
+ 0x00,0x00,0x00,0x7c,0x08,0x10,0x20,0x7c,0x00,0x00,
+ 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+ 0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+ 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
+ 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff},
+ {
+ /* Separated semi-graphic */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x70,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x77,0x77,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x70,0x70,0x70,0x00,0x00,0x00,0x00,
+ 0x70,0x70,0x00,0x70,0x70,0x70,0x00,0x00,0x00,0x00,
+ 0x07,0x07,0x00,0x70,0x70,0x70,0x00,0x00,0x00,0x00,
+ 0x77,0x77,0x00,0x70,0x70,0x70,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+ 0x70,0x70,0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+ 0x07,0x07,0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+ 0x77,0x77,0x00,0x07,0x07,0x07,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x77,0x77,0x77,0x00,0x00,0x00,0x00,
+ 0x70,0x70,0x00,0x77,0x77,0x77,0x00,0x00,0x00,0x00,
+ 0x07,0x07,0x00,0x77,0x77,0x77,0x00,0x00,0x00,0x00,
+ 0x77,0x77,0x00,0x77,0x77,0x77,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x70,0x00,
+ 0x70,0x70,0x00,0x00,0x00,0x00,0x00,0x70,0x70,0x00,
+ 0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x70,0x70,0x00,
+ 0x77,0x77,0x00,0x00,0x00,0x00,0x00,0x70,0x70,0x00,
+ 0x00,0x00,0x00,0x70,0x70,0x70,0x00,0x70,0x70,0x00,
+ 0x70,0x70,0x00,0x70,0x70,0x70,0x00,0x70,0x70,0x00,
+ 0x07,0x07,0x00,0x70,0x70,0x70,0x00,0x70,0x70,0x00,
+ 0x77,0x77,0x00,0x70,0x70,0x70,0x00,0x70,0x70,0x00,
+ 0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x70,0x70,0x00,
+ 0x70,0x70,0x00,0x07,0x07,0x07,0x00,0x70,0x70,0x00,
+ 0x07,0x07,0x00,0x07,0x07,0x07,0x00,0x70,0x70,0x00,
+ 0x77,0x77,0x00,0x07,0x07,0x07,0x00,0x70,0x70,0x00,
+ 0x00,0x00,0x00,0x77,0x77,0x77,0x00,0x70,0x70,0x00,
+ 0x70,0x70,0x00,0x77,0x77,0x77,0x00,0x70,0x70,0x00,
+ 0x07,0x07,0x00,0x77,0x77,0x77,0x00,0x70,0x70,0x00,
+ 0x77,0x77,0x00,0x77,0x77,0x77,0x00,0x70,0x70,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+ 0x70,0x70,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+ 0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+ 0x77,0x77,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,
+ 0x00,0x00,0x00,0x70,0x70,0x70,0x00,0x07,0x07,0x00,
+ 0x70,0x70,0x00,0x70,0x70,0x70,0x00,0x07,0x07,0x00,
+ 0x07,0x07,0x00,0x70,0x70,0x70,0x00,0x07,0x07,0x00,
+ 0x77,0x77,0x00,0x70,0x70,0x70,0x00,0x07,0x07,0x00,
+ 0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x07,0x07,0x00,
+ 0x70,0x70,0x00,0x07,0x07,0x07,0x00,0x07,0x07,0x00,
+ 0x07,0x07,0x00,0x07,0x07,0x07,0x00,0x07,0x07,0x00,
+ 0x77,0x77,0x00,0x07,0x07,0x07,0x00,0x07,0x07,0x00,
+ 0x00,0x00,0x00,0x77,0x77,0x77,0x00,0x07,0x07,0x00,
+ 0x70,0x70,0x00,0x77,0x77,0x77,0x00,0x07,0x07,0x00,
+ 0x07,0x07,0x00,0x77,0x77,0x77,0x00,0x07,0x07,0x00,
+ 0x77,0x77,0x00,0x77,0x77,0x77,0x00,0x07,0x07,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x77,0x77,0x00,
+ 0x70,0x70,0x00,0x00,0x00,0x00,0x00,0x77,0x77,0x00,
+ 0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x77,0x77,0x00,
+ 0x77,0x77,0x00,0x00,0x00,0x00,0x00,0x77,0x77,0x00,
+ 0x00,0x00,0x00,0x70,0x70,0x70,0x00,0x77,0x77,0x00,
+ 0x70,0x70,0x00,0x70,0x70,0x70,0x00,0x77,0x77,0x00,
+ 0x07,0x07,0x00,0x70,0x70,0x70,0x00,0x77,0x77,0x00,
+ 0x77,0x77,0x00,0x70,0x70,0x70,0x00,0x77,0x77,0x00,
+ 0x00,0x00,0x00,0x07,0x07,0x07,0x00,0x77,0x77,0x00,
+ 0x70,0x70,0x00,0x07,0x07,0x07,0x00,0x77,0x77,0x00,
+ 0x07,0x07,0x00,0x07,0x07,0x07,0x00,0x77,0x77,0x00,
+ 0x77,0x77,0x00,0x07,0x07,0x07,0x00,0x77,0x77,0x00,
+ 0x00,0x00,0x00,0x77,0x77,0x77,0x00,0x77,0x77,0x00,
+ 0x70,0x70,0x00,0x77,0x77,0x77,0x00,0x77,0x77,0x00,
+ 0x07,0x07,0x00,0x77,0x77,0x77,0x00,0x77,0x77,0x00,
+ 0x77,0x77,0x00,0x77,0x77,0x77,0x00,0x77,0x77,0x00,
+ /* Mosaic semi-graphic */
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xf0,0xf0,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x0f,0x0f,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00,
+ 0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00,
+ 0x0f,0x0f,0x0f,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xf0,0xf0,0xf0,0xf0,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x0f,0x0f,0x0f,0x0f,0x00,0x00,0x00,
+ 0xf0,0xf0,0xf0,0x0f,0x0f,0x0f,0x0f,0x00,0x00,0x00,
+ 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0x0f,0x0f,0x0f,0x0f,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,
+ 0xf0,0xf0,0xf0,0xff,0xff,0xff,0xff,0x00,0x00,0x00,
+ 0x0f,0x0f,0x0f,0xff,0xff,0xff,0xff,0x00,0x00,0x00,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf0,0xf0,0xf0,
+ 0xf0,0xf0,0xf0,0x00,0x00,0x00,0x00,0xf0,0xf0,0xf0,
+ 0x0f,0x0f,0x0f,0x00,0x00,0x00,0x00,0xf0,0xf0,0xf0,
+ 0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xf0,0xf0,0xf0,
+ 0x00,0x00,0x00,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,
+ 0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,
+ 0x0f,0x0f,0x0f,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,
+ 0xff,0xff,0xff,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,
+ 0x00,0x00,0x00,0x0f,0x0f,0x0f,0x0f,0xf0,0xf0,0xf0,
+ 0xf0,0xf0,0xf0,0x0f,0x0f,0x0f,0x0f,0xf0,0xf0,0xf0,
+ 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0xf0,0xf0,0xf0,
+ 0xff,0xff,0xff,0x0f,0x0f,0x0f,0x0f,0xf0,0xf0,0xf0,
+ 0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xf0,0xf0,0xf0,
+ 0xf0,0xf0,0xf0,0xff,0xff,0xff,0xff,0xf0,0xf0,0xf0,
+ 0x0f,0x0f,0x0f,0xff,0xff,0xff,0xff,0xf0,0xf0,0xf0,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0xf0,0xf0,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x0f,0x0f,
+ 0xf0,0xf0,0xf0,0x00,0x00,0x00,0x00,0x0f,0x0f,0x0f,
+ 0x0f,0x0f,0x0f,0x00,0x00,0x00,0x00,0x0f,0x0f,0x0f,
+ 0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x0f,0x0f,0x0f,
+ 0x00,0x00,0x00,0xf0,0xf0,0xf0,0xf0,0x0f,0x0f,0x0f,
+ 0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0x0f,0x0f,0x0f,
+ 0x0f,0x0f,0x0f,0xf0,0xf0,0xf0,0xf0,0x0f,0x0f,0x0f,
+ 0xff,0xff,0xff,0xf0,0xf0,0xf0,0xf0,0x0f,0x0f,0x0f,
+ 0x00,0x00,0x00,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
+ 0xf0,0xf0,0xf0,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
+ 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
+ 0xff,0xff,0xff,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,
+ 0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x0f,0x0f,0x0f,
+ 0xf0,0xf0,0xf0,0xff,0xff,0xff,0xff,0x0f,0x0f,0x0f,
+ 0x0f,0x0f,0x0f,0xff,0xff,0xff,0xff,0x0f,0x0f,0x0f,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f,0x0f,0x0f,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,
+ 0xf0,0xf0,0xf0,0x00,0x00,0x00,0x00,0xff,0xff,0xff,
+ 0x0f,0x0f,0x0f,0x00,0x00,0x00,0x00,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,
+ 0x00,0x00,0x00,0xf0,0xf0,0xf0,0xf0,0xff,0xff,0xff,
+ 0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xff,0xff,0xff,
+ 0x0f,0x0f,0x0f,0xf0,0xf0,0xf0,0xf0,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xf0,0xf0,0xf0,0xf0,0xff,0xff,0xff,
+ 0x00,0x00,0x00,0x0f,0x0f,0x0f,0x0f,0xff,0xff,0xff,
+ 0xf0,0xf0,0xf0,0x0f,0x0f,0x0f,0x0f,0xff,0xff,0xff,
+ 0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0x0f,0x0f,0x0f,0x0f,0xff,0xff,0xff,
+ 0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xf0,0xf0,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0x0f,0x0f,0x0f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
+ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}
+};
+
diff --git a/clean/src/vpp_cset.h b/clean/src/vpp_cset.h
new file mode 100755
index 0000000..d0a2887
--- /dev/null
+++ b/clean/src/vpp_cset.h
@@ -0,0 +1,6 @@
+#ifndef __VPP_CSET_H
+#define __VPP_CSET_H
+
+extern Byte vpp_cset[2][1280];
+
+#endif
diff --git a/clean/stubs/allegro.c b/clean/stubs/allegro.c
new file mode 100755
index 0000000..cec10f6
--- /dev/null
+++ b/clean/stubs/allegro.c
@@ -0,0 +1,207 @@
+
+#include "allegro.h"
+
+#include
+#include
+#include
+#define abs(a) miabs(a)
+
+int miabs(int a){
+ if((a)<0)a=-a;
+ return a;
+}
+
+void upcase(char *p)
+{
+ while(*p != '\0')
+ {
+ if(*p >= 97 && *p <= 122)
+ *p -= 32;
+ ++p;
+ }
+}
+void downcase(char *p)
+{
+ while(*p != '\0')
+ {
+ if(*p >= 97-32 && *p <= 122-32)
+ *p += 32;
+ ++p;
+ }
+}
+
+void clear(BITMAP *buff){
+
+ memset(&buff->line,0,buff->w*buff->h);
+}
+
+BITMAP *create_bitmap(int w,int h){
+
+ BITMAP *buff;
+
+ buff = malloc(sizeof (BITMAP));
+ buff->line=malloc(1*w*h);
+
+ buff->w=w;
+ buff->h=h;
+ buff->pitch=w;
+ buff->depth=1;
+
+ return buff;
+}
+
+int destroy_bitmap(BITMAP *buff){
+
+ if (buff->line) {
+ free(buff->line);
+ }
+ free(buff);
+
+ return 0;
+}
+
+
+void rect(BITMAP *buff,int x,int y,int x2,int y2,unsigned char color){
+
+ int i,j,idx;
+
+ int dx= abs(x2-x);
+ int dy= abs(y2-y);
+ int V_WIDTH = buff->w;
+ unsigned char *buffer=buff->line[0];
+
+ for(i=x;iw;
+ unsigned char *buffer=buff->line[0];
+
+ for(i=x;iw;
+ unsigned char *buffer=buff->line[0];
+
+ for(i=x;iw;
+ unsigned char *buffer=buff->line[0];
+
+ for(j=y;jw;
+ unsigned char *buffer=buff->line[0];
+
+ dx = x2 - x1;
+ dy = y2 - y1;
+ sx = (dx >= 0) ? 1 : -1;
+ sy = (dy >= 0) ? 1 : -1;
+
+ if (dx==0) {
+ if (dy>0) {
+ DrawVline(buff, x1, y1,0, dy, color);
+ return;
+
+ } else if (dy<0) {
+ DrawVline(buff, x1, y2,0, -dy, color);
+ return;
+
+ } else {
+ idx=x1+y1*V_WIDTH;
+ buffer[idx]=color;
+ return ;
+ }
+ }
+ if (dy == 0) {
+ if (dx>0) {
+ DrawHline(buff, x1, y1, dx, 0, color);
+ return;
+
+ } else if (dx<0) {
+ DrawHline(buff, x2, y1, -dx,0, color);
+ return;
+ }
+ }
+
+ dx = sx * dx + 1;
+ dy = sy * dy + 1;
+
+ pixx = 1;
+ pixy = V_WIDTH;
+
+ pixx *= sx;
+ pixy *= sy;
+
+ if (dx < dy) {
+ swaptmp = dx;
+ dx = dy;
+ dy = swaptmp;
+ swaptmp = pixx;
+ pixx = pixy;
+ pixy = swaptmp;
+ }
+
+ x = 0;
+ y = 0;
+
+ idx=x1+y1*V_WIDTH;
+
+ for (; x < dx; x++, idx +=pixx) {
+ buffer[idx]=color;
+ y += dy;
+ if (y >= dx) {
+ y -= dx;
+ idx += pixy;
+ }
+ }
+
+}
diff --git a/clean/stubs/allegro.h b/clean/stubs/allegro.h
new file mode 100755
index 0000000..0295ac9
--- /dev/null
+++ b/clean/stubs/allegro.h
@@ -0,0 +1,81 @@
+
+#ifndef ALLEGRO_H
+#define ALLEGRO_H
+
+#define INLINE static inline
+#define rest(a) usleep(a)
+#define strupr upcase
+#define strlwr downcase
+#define keypressed() 0
+#define poll_keyboard()
+#define yield_timeslice()
+
+typedef struct
+{
+ unsigned char *line;
+ int w;
+ int h;
+ int pitch;
+ int depth;
+
+}BITMAP;
+
+//typedef struct
+//{
+// unsigned char r;
+// unsigned char g;
+// unsigned char b;
+//}APALETTE;
+
+typedef struct RGB
+{
+ unsigned char r, g, b;
+ unsigned char filler;
+} RGB;
+#define PAL_SIZE 256
+typedef RGB PALETTE[PAL_SIZE];
+
+struct FONT_VTABLE;
+typedef struct FONT
+{
+ void *data;
+ int height;
+ struct FONT_VTABLE *vtable;
+} FONT;
+
+typedef struct AUDIOSTREAM
+{
+} AUDIOSTREAM;
+
+typedef struct DIGI_DRIVER /* driver for playing digital sfx */
+{
+} DIGI_DRIVER;
+
+#define DIGI_AUTODETECT -1 /* for passing to install_sound() */
+#define MIDI_NONE 0
+
+#define GFX_TEXT -1
+#define GFX_AUTODETECT 0
+#define GFX_AUTODETECT_FULLSCREEN 1
+#define GFX_AUTODETECT_WINDOWED 2
+#define SWITCH_PAUSE 1
+extern BITMAP * screen;
+void set_color_depth (int depth);
+int set_gfx_mode (int card, int w, int h, int v_w, int v_h);
+void set_palette (const PALETTE p);
+void set_window_title (const char *name);
+int set_display_switch_mode (int mode);
+int set_gfx_mode (int card, int w, int h, int v_w, int v_h);
+void acquire_screen (void);
+void release_screen (void);
+void clear (BITMAP *bmp);
+
+void stretch_blit (BITMAP *s, BITMAP *d, int s_x, int s_y, int s_w, int s_h, int d_x, int d_y, int d_w, int d_h);
+
+void textprintf_ex (BITMAP *bmp, const FONT *f, int x, int y, int color, int bg, const char *format, ...);
+
+extern unsigned char key[256*2];
+
+#define INLINE static inline
+
+#endif
diff --git a/src/Makefile b/src/Makefile
new file mode 100755
index 0000000..81abdae
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,72 @@
+CC = gcc
+WINDRES = windres
+
+CFLAGS = -mno-cygwin -O3 -fomit-frame-pointer -Wall -I/usr/local/include
+LFLAGS = -mno-cygwin -s
+LIBALLEG = -L/usr/local/lib -lalleg
+
+
+all: o2em.exe dis48.exe
+
+clean:
+ del -f audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o dis48.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o score.o o2em.res o2em.exe dis48.exe
+
+
+o2em.exe: audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o o2em.res score.o
+ $(CC) $(LFLAGS) audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o score.o o2em.res -o o2em.exe $(LIBALLEG)
+
+dis48.exe: dis48.o table.o
+ $(CC) $(LFLAGS) dis48.o table.o -o dis48.exe
+
+
+audio.o: audio.c audio.h cpu.h types.h config.h vmachine.h
+ $(CC) $(CFLAGS) -c audio.c -o audio.o
+
+cpu.o: cpu.c cpu.h types.h vmachine.h keyboard.h voice.h vdc.h vpp.h
+ $(CC) $(CFLAGS) -c cpu.c -o cpu.o
+
+cset.o: cset.c cset.h types.h
+ $(CC) $(CFLAGS) -c cset.c -o cset.o
+
+debug.o: debug.c debug.h cpu.h keyboard.h vmachine.h audio.h vdc.h table.h
+ $(CC) $(CFLAGS) -c debug.c -o debug.o
+
+dis48.o: dis48.c types.h table.h
+ $(CC) $(CFLAGS) -c dis48.c -o dis48.o
+
+keyboard.o: keyboard.c keyboard.h types.h cpu.h vmachine.h vdc.h audio.h voice.h vpp.h score.h
+ $(CC) $(CFLAGS) -c keyboard.c -o keyboard.o
+
+main.o: main.c crc32.h audio.h vmachine.h config.h vdc.h cpu.h debug.h keyboard.h voice.h score.h
+ $(CC) $(CFLAGS) -c main.c -o main.o
+
+table.o: table.c table.h cpu.h
+ $(CC) $(CFLAGS) -c table.c -o table.o
+
+vdc.o: vdc.c vdc.h types.h vmachine.h config.h keyboard.h cset.h timefunc.h cpu.h vpp.h
+ $(CC) $(CFLAGS) -c vdc.c -o vdc.o
+
+vmachine.o: vmachine.c vmachine.h audio.h types.h cpu.h keyboard.h config.h debug.h vdc.h vpp.h timefunc.h voice.h
+ $(CC) $(CFLAGS) -c vmachine.c -o vmachine.o
+
+timefunc.o: timefunc.c timefunc.h
+ $(CC) $(CFLAGS) -c timefunc.c -o timefunc.o
+
+voice.o: voice.c voice.h vmachine.h cpu.h
+ $(CC) $(CFLAGS) -c voice.c -o voice.o
+
+crc32.o: crc32.c crc32.h
+ $(CC) $(CFLAGS) -c crc32.c -o crc32.o
+
+vpp_cset.o: vpp_cset.c vpp_cset.h
+ $(CC) $(CFLAGS) -c vpp_cset.c -o vpp_cset.o
+
+vpp.o: vpp.c vpp.h types.h vpp_cset.h vmachine.h vdc.h
+ $(CC) $(CFLAGS) -c vpp.c -o vpp.o
+
+score.o: score.c score.h vmachine.h
+ $(CC) $(CFLAGS) -c score.c -o score.o
+
+o2em.res: o2em.rc o2em.ico
+ $(WINDRES) -O coff -o o2em.res -i o2em.rc
+
diff --git a/src/Makefile.djgpp b/src/Makefile.djgpp
new file mode 100755
index 0000000..e170e8a
--- /dev/null
+++ b/src/Makefile.djgpp
@@ -0,0 +1,71 @@
+CC = gcc
+
+CFLAGS = -O3 -Wall -fomit-frame-pointer
+LFLAGS = -s
+LIBALLEG = -lalleg
+
+
+all: o2em.exe dis48.exe
+
+clean:
+ del *.o
+
+
+o2em.exe: audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o o2em.res score.o
+ $(CC) $(LFLAGS) audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o score.o o2em.res -o o2em.exe $(LIBALLEG)
+
+dis48.exe: dis48.o table.o
+ $(CC) $(LFLAGS) dis48.o table.o -o dis48.exe
+
+
+audio.o: audio.c audio.h cpu.h types.h config.h vmachine.h
+ $(CC) $(CFLAGS) -c audio.c -o audio.o
+
+cpu.o: cpu.c cpu.h types.h vmachine.h keyboard.h voice.h vdc.h vpp.h
+ $(CC) $(CFLAGS) -c cpu.c -o cpu.o
+
+cset.o: cset.c cset.h types.h
+ $(CC) $(CFLAGS) -c cset.c -o cset.o
+
+debug.o: debug.c debug.h cpu.h keyboard.h vmachine.h audio.h vdc.h table.h
+ $(CC) $(CFLAGS) -c debug.c -o debug.o
+
+dis48.o: dis48.c types.h table.h
+ $(CC) $(CFLAGS) -c dis48.c -o dis48.o
+
+keyboard.o: keyboard.c keyboard.h types.h cpu.h vmachine.h vdc.h audio.h voice.h vpp.h score.h
+ $(CC) $(CFLAGS) -c keyboard.c -o keyboard.o
+
+main.o: main.c crc32.h audio.h vmachine.h config.h vdc.h cpu.h debug.h keyboard.h voice.h score.h
+ $(CC) $(CFLAGS) -c main.c -o main.o
+
+table.o: table.c table.h cpu.h
+ $(CC) $(CFLAGS) -c table.c -o table.o
+
+vdc.o: vdc.c vdc.h types.h vmachine.h config.h keyboard.h cset.h timefunc.h cpu.h vpp.h
+ $(CC) $(CFLAGS) -c vdc.c -o vdc.o
+
+vmachine.o: vmachine.c vmachine.h audio.h types.h cpu.h keyboard.h config.h debug.h vdc.h vpp.h timefunc.h voice.h
+ $(CC) $(CFLAGS) -c vmachine.c -o vmachine.o
+
+timefunc.o: timefunc.c timefunc.h
+ $(CC) $(CFLAGS) -c timefunc.c -o timefunc.o
+
+voice.o: voice.c voice.h vmachine.h cpu.h
+ $(CC) $(CFLAGS) -c voice.c -o voice.o
+
+crc32.o: crc32.c crc32.h
+ $(CC) $(CFLAGS) -c crc32.c -o crc32.o
+
+vpp_cset.o: vpp_cset.c vpp_cset.h
+ $(CC) $(CFLAGS) -c vpp_cset.c -o vpp_cset.o
+
+vpp.o: vpp.c vpp.h types.h vpp_cset.h vmachine.h vdc.h
+ $(CC) $(CFLAGS) -c vpp.c -o vpp.o
+
+score.o: score.c score.h vmachine.h
+ $(CC) $(CFLAGS) -c score.c -o score.o
+
+o2em.res: o2em.rc o2em.ico
+ $(WINDRES) -O coff -o o2em.res -i o2em.rc
+
diff --git a/src/Makefile.freebsd b/src/Makefile.freebsd
new file mode 100755
index 0000000..94b49d0
--- /dev/null
+++ b/src/Makefile.freebsd
@@ -0,0 +1,68 @@
+CC = gcc
+
+CFLAGS = -O3 -Wall -fomit-frame-pointer -I${PREFIX}/include -DFREEBSD -DPREFIX=\"${PREFIX}\"
+LFLAGS = -s
+LIBALLEG = -L${PREFIX}/lib -lalleg -lalleg_unsharable
+
+
+all: o2em dis48
+
+clean:
+ rm -f audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o score.o dis48.o
+
+
+o2em: audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o score.o
+ $(CC) $(LFLAGS) audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o score.o -o o2em $(LIBALLEG)
+
+dis48: dis48.o table.o
+ $(CC) $(LFLAGS) dis48.o table.o -o dis48
+
+
+audio.o: audio.c audio.h cpu.h types.h config.h vmachine.h
+ $(CC) $(CFLAGS) -c audio.c -o audio.o
+
+cpu.o: cpu.c cpu.h types.h vmachine.h keyboard.h voice.h vdc.h vpp.h
+ $(CC) $(CFLAGS) -c cpu.c -o cpu.o
+
+cset.o: cset.c cset.h types.h
+ $(CC) $(CFLAGS) -c cset.c -o cset.o
+
+debug.o: debug.c debug.h cpu.h keyboard.h vmachine.h audio.h vdc.h table.h
+ $(CC) $(CFLAGS) -c debug.c -o debug.o
+
+dis48.o: dis48.c types.h table.h
+ $(CC) $(CFLAGS) -c dis48.c -o dis48.o
+
+keyboard.o: keyboard.c keyboard.h types.h cpu.h vmachine.h vdc.h audio.h voice.h vpp.h
+ $(CC) $(CFLAGS) -c keyboard.c -o keyboard.o
+
+main.o: main.c crc32.h audio.h vmachine.h config.h vdc.h cpu.h debug.h keyboard.h voice.h
+ $(CC) $(CFLAGS) -c main.c -o main.o
+
+table.o: table.c table.h cpu.h
+ $(CC) $(CFLAGS) -c table.c -o table.o
+
+vdc.o: vdc.c vdc.h types.h vmachine.h config.h keyboard.h cset.h timefunc.h cpu.h vpp.h
+ $(CC) $(CFLAGS) -c vdc.c -o vdc.o
+
+vmachine.o: vmachine.c vmachine.h audio.h types.h cpu.h keyboard.h config.h debug.h vdc.h vpp.h timefunc.h voice.h
+ $(CC) $(CFLAGS) -c vmachine.c -o vmachine.o
+
+timefunc.o: timefunc.c timefunc.h
+ $(CC) $(CFLAGS) -c timefunc.c -o timefunc.o
+
+voice.o: voice.c voice.h vmachine.h cpu.h
+ $(CC) $(CFLAGS) -c voice.c -o voice.o
+
+crc32.o: crc32.c crc32.h
+ $(CC) $(CFLAGS) -c crc32.c -o crc32.o
+
+vpp_cset.o: vpp_cset.c vpp_cset.h
+ $(CC) $(CFLAGS) -c vpp_cset.c -o vpp_cset.o
+
+vpp.o: vpp.c vpp.h types.h vpp_cset.h vmachine.h vdc.h
+ $(CC) $(CFLAGS) -c vpp.c -o vpp.o
+
+score.o: score.c score.h vmachine.h types.h
+ $(CC) $(CFLAGS) -c score.c -o score.o
+
diff --git a/src/Makefile.linux b/src/Makefile.linux
new file mode 100755
index 0000000..39f0170
--- /dev/null
+++ b/src/Makefile.linux
@@ -0,0 +1,68 @@
+CC = gcc
+
+CFLAGS = -O3 -Wall -fomit-frame-pointer -I/usr/include
+LFLAGS = -s
+LIBALLEG = /usr/lib/liballeg.so.4.2 -lalleg_unsharable
+
+
+all: o2em dis48
+
+clean:
+ rm -f audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o score.o dis48.o
+
+
+o2em: audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o score.o
+ $(CC) $(LFLAGS) audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o score.o -o o2em $(LIBALLEG)
+
+dis48: dis48.o table.o
+ $(CC) $(LFLAGS) dis48.o table.o -o dis48
+
+
+audio.o: audio.c audio.h cpu.h types.h config.h vmachine.h
+ $(CC) $(CFLAGS) -c audio.c -o audio.o
+
+cpu.o: cpu.c cpu.h types.h vmachine.h keyboard.h voice.h vdc.h vpp.h
+ $(CC) $(CFLAGS) -c cpu.c -o cpu.o
+
+cset.o: cset.c cset.h types.h
+ $(CC) $(CFLAGS) -c cset.c -o cset.o
+
+debug.o: debug.c debug.h cpu.h keyboard.h vmachine.h audio.h vdc.h table.h
+ $(CC) $(CFLAGS) -c debug.c -o debug.o
+
+dis48.o: dis48.c types.h table.h
+ $(CC) $(CFLAGS) -c dis48.c -o dis48.o
+
+keyboard.o: keyboard.c keyboard.h types.h cpu.h vmachine.h vdc.h audio.h voice.h vpp.h
+ $(CC) $(CFLAGS) -c keyboard.c -o keyboard.o
+
+main.o: main.c crc32.h audio.h vmachine.h config.h vdc.h cpu.h debug.h keyboard.h voice.h
+ $(CC) $(CFLAGS) -c main.c -o main.o
+
+table.o: table.c table.h cpu.h
+ $(CC) $(CFLAGS) -c table.c -o table.o
+
+vdc.o: vdc.c vdc.h types.h vmachine.h config.h keyboard.h cset.h timefunc.h cpu.h vpp.h
+ $(CC) $(CFLAGS) -c vdc.c -o vdc.o
+
+vmachine.o: vmachine.c vmachine.h audio.h types.h cpu.h keyboard.h config.h debug.h vdc.h vpp.h timefunc.h voice.h
+ $(CC) $(CFLAGS) -c vmachine.c -o vmachine.o
+
+timefunc.o: timefunc.c timefunc.h
+ $(CC) $(CFLAGS) -c timefunc.c -o timefunc.o
+
+voice.o: voice.c voice.h vmachine.h cpu.h
+ $(CC) $(CFLAGS) -c voice.c -o voice.o
+
+crc32.o: crc32.c crc32.h
+ $(CC) $(CFLAGS) -c crc32.c -o crc32.o
+
+vpp_cset.o: vpp_cset.c vpp_cset.h
+ $(CC) $(CFLAGS) -c vpp_cset.c -o vpp_cset.o
+
+vpp.o: vpp.c vpp.h types.h vpp_cset.h vmachine.h vdc.h
+ $(CC) $(CFLAGS) -c vpp.c -o vpp.o
+
+score.o: score.c score.h vmachine.h types.h
+ $(CC) $(CFLAGS) -c score.c -o score.o
+
diff --git a/src/Makefile.mingw b/src/Makefile.mingw
new file mode 100755
index 0000000..3f25bda
--- /dev/null
+++ b/src/Makefile.mingw
@@ -0,0 +1,69 @@
+CC = gcc
+WINDRES = windres
+
+CFLAGS = -mno-cygwin -O3 -fomit-frame-pointer -Wall -I/usr/local/include
+LFLAGS = -mno-cygwin -s
+LIBALLEG = -L/usr/local/lib -lalleg
+
+
+all: o2em.exe dis48.exe
+
+clean:
+ rm -f audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o dis48.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o o2em.res
+
+
+o2em.exe: audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o o2em.res
+ $(CC) $(LFLAGS) audio.o cpu.o cset.o keyboard.o main.o table.o vdc.o vmachine.o debug.o timefunc.o voice.o crc32.o vpp_cset.o vpp.o o2em.res -o o2em.exe $(LIBALLEG)
+
+dis48.exe: dis48.o table.o
+ $(CC) $(LFLAGS) dis48.o table.o -o dis48.exe
+
+
+audio.o: audio.c audio.h cpu.h types.h config.h vmachine.h
+ $(CC) $(CFLAGS) -c audio.c -o audio.o
+
+cpu.o: cpu.c cpu.h types.h vmachine.h keyboard.h voice.h vdc.h vpp.h
+ $(CC) $(CFLAGS) -c cpu.c -o cpu.o
+
+cset.o: cset.c cset.h types.h
+ $(CC) $(CFLAGS) -c cset.c -o cset.o
+
+debug.o: debug.c debug.h cpu.h keyboard.h vmachine.h audio.h vdc.h table.h
+ $(CC) $(CFLAGS) -c debug.c -o debug.o
+
+dis48.o: dis48.c types.h table.h
+ $(CC) $(CFLAGS) -c dis48.c -o dis48.o
+
+keyboard.o: keyboard.c keyboard.h types.h cpu.h vmachine.h vdc.h audio.h voice.h vpp.h
+ $(CC) $(CFLAGS) -c keyboard.c -o keyboard.o
+
+main.o: main.c crc32.h audio.h vmachine.h config.h vdc.h cpu.h debug.h keyboard.h voice.h
+ $(CC) $(CFLAGS) -c main.c -o main.o
+
+table.o: table.c table.h cpu.h
+ $(CC) $(CFLAGS) -c table.c -o table.o
+
+vdc.o: vdc.c vdc.h types.h vmachine.h config.h keyboard.h cset.h timefunc.h cpu.h vpp.h
+ $(CC) $(CFLAGS) -c vdc.c -o vdc.o
+
+vmachine.o: vmachine.c vmachine.h audio.h types.h cpu.h keyboard.h config.h debug.h vdc.h vpp.h timefunc.h voice.h
+ $(CC) $(CFLAGS) -c vmachine.c -o vmachine.o
+
+timefunc.o: timefunc.c timefunc.h
+ $(CC) $(CFLAGS) -c timefunc.c -o timefunc.o
+
+voice.o: voice.c voice.h vmachine.h cpu.h
+ $(CC) $(CFLAGS) -c voice.c -o voice.o
+
+crc32.o: crc32.c crc32.h
+ $(CC) $(CFLAGS) -c crc32.c -o crc32.o
+
+vpp_cset.o: vpp_cset.c vpp_cset.h
+ $(CC) $(CFLAGS) -c vpp_cset.c -o vpp_cset.o
+
+vpp.o: vpp.c vpp.h types.h vpp_cset.h vmachine.h vdc.h
+ $(CC) $(CFLAGS) -c vpp.c -o vpp.o
+
+o2em.res: o2em.rc o2em.ico
+ $(WINDRES) -O coff -o o2em.res -i o2em.rc
+
diff --git a/src/Makefile.win b/src/Makefile.win
new file mode 100755
index 0000000..08ae56b
--- /dev/null
+++ b/src/Makefile.win
@@ -0,0 +1,35 @@
+# Project: Project1
+# Makefile created by Dev-C++ 4.9.9.1
+
+CPP = g++.exe
+CC = gcc.exe
+WINDRES = windres.exe
+RES = ../OBJ/file_private.res
+OBJ = ../OBJ/get_file.o ../OBJ/crc32.o $(RES)
+LINKOBJ = ../OBJ/get_file.o ../OBJ/crc32.o $(RES)
+LIBS = -L"C:/Dev-Cpp/lib" -L"C:/Dev-Cpp/lib"
+INCS = -I"C:/Dev-Cpp/include" -I"C:/Dev-Cpp/include"
+CXXINCS = -I"C:/Dev-Cpp/include/c++/3.3.1" -I"C:/Dev-Cpp/include/c++/3.3.1/mingw32" -I"C:/Dev-Cpp/include/c++/3.3.1/backward" -I"C:/Dev-Cpp/lib/gcc-lib/mingw32/3.3.1/include" -I"C:/Dev-Cpp/include" -I"C:/Dev-Cpp/include"
+BIN = file.exe
+CXXFLAGS = $(CXXINCS)
+CFLAGS = $(INCS)
+
+.PHONY: all all-before all-after clean clean-custom
+
+all: all-before file.exe all-after
+
+
+clean: clean-custom
+ rm -f $(OBJ) $(BIN)
+
+$(BIN): $(OBJ)
+ $(CPP) $(LINKOBJ) -o "file.exe" $(LIBS)
+
+../OBJ/get_file.o: get_file.cpp
+ $(CPP) -c get_file.cpp -o ../OBJ/get_file.o $(CXXFLAGS)
+
+../OBJ/crc32.o: crc32.c
+ $(CPP) -c crc32.c -o ../OBJ/crc32.o $(CXXFLAGS)
+
+../OBJ/file_private.res: file_private.rc
+ $(WINDRES) -i file_private.rc --input-format=rc -o ../OBJ/file_private.res -O coff --include-dir C:/Dev-Cpp/Projetos/o2em-win
diff --git a/src/O2EM.ICO b/src/O2EM.ICO
new file mode 100755
index 0000000..f867aac
Binary files /dev/null and b/src/O2EM.ICO differ
diff --git a/src/O2EM.RC b/src/O2EM.RC
new file mode 100755
index 0000000..fbba6bf
--- /dev/null
+++ b/src/O2EM.RC
@@ -0,0 +1,3 @@
+#include
+
+allegro_icon ICON DISCARDABLE "o2em.ico"
diff --git a/src/O2EM.RES b/src/O2EM.RES
new file mode 100755
index 0000000..6c5d4e1
Binary files /dev/null and b/src/O2EM.RES differ
diff --git a/src/O2EM116_private.h b/src/O2EM116_private.h
new file mode 100755
index 0000000..9bdaf83
--- /dev/null
+++ b/src/O2EM116_private.h
@@ -0,0 +1,23 @@
+/* THIS FILE WILL BE OVERWRITTEN BY DEV-C++ */
+/* DO NOT EDIT ! */
+
+#ifndef O2EM116_PRIVATE_H
+#define O2EM116_PRIVATE_H
+
+/* VERSION DEFINITIONS */
+#define VER_STRING "0.1.1.1"
+#define VER_MAJOR 0
+#define VER_MINOR 1
+#define VER_RELEASE 1
+#define VER_BUILD 1
+#define COMPANY_NAME ""
+#define FILE_VERSION ""
+#define FILE_DESCRIPTION "Developed using the Dev-C++ IDE"
+#define INTERNAL_NAME ""
+#define LEGAL_COPYRIGHT ""
+#define LEGAL_TRADEMARKS ""
+#define ORIGINAL_FILENAME ""
+#define PRODUCT_NAME ""
+#define PRODUCT_VERSION ""
+
+#endif /*O2EM116_PRIVATE_H*/
diff --git a/src/O2EM116_private.rc b/src/O2EM116_private.rc
new file mode 100755
index 0000000..c87d7f0
--- /dev/null
+++ b/src/O2EM116_private.rc
@@ -0,0 +1,5 @@
+/* THIS FILE WILL BE OVERWRITTEN BY DEV-C++ */
+/* DO NOT EDIT! */
+
+#include "o2em.rc"
+
diff --git a/src/O2em118.dev b/src/O2em118.dev
new file mode 100755
index 0000000..c2a7d33
--- /dev/null
+++ b/src/O2em118.dev
@@ -0,0 +1,378 @@
+[Project]
+FileName=O2em118.dev
+Name=O2EM118
+UnitCount=33
+Type=1
+Ver=1
+ObjFiles=
+Includes=C:\Dev-Cpp\include
+Libs=C:\Dev-Cpp\lib
+PrivateResource=O2EM116_private.rc
+ResourceIncludes=C:\Dev-Cpp\Projetos\Res
+MakeIncludes=
+Compiler=
+CppCompiler=
+Linker=../../lib/liballeg.a_@@_
+IsCpp=1
+Icon=
+ExeOutput=..\Exe
+ObjectOutput=..\OBJ
+OverrideOutput=1
+OverrideOutputName=O2EM.exe
+HostApplication=
+Folders=Resource
+CommandLine=
+UseCustomMakefile=1
+CustomMakefile=Makefile.djgpp
+IncludeVersionInfo=0
+SupportXPThemes=0
+CompilerSet=0
+CompilerSettings=0000000000000000000000
+
+[Unit1]
+FileName=vpp_cset.c
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit2]
+FileName=audio.c
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit3]
+FileName=cpu.c
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit4]
+FileName=crc32.c
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit5]
+FileName=cset.c
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit6]
+FileName=debug.c
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit7]
+FileName=dis48.c
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit8]
+FileName=keyboard.c
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit9]
+FileName=main.c
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit10]
+FileName=table.c
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit11]
+FileName=timefunc.c
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit12]
+FileName=vdc.c
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit13]
+FileName=vmachine.c
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit14]
+FileName=voice.c
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit15]
+FileName=vpp.c
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit16]
+FileName=vpp_cset.h
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit17]
+FileName=audio.h
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit18]
+FileName=config.h
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit19]
+FileName=cpu.h
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit20]
+FileName=crc32.h
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit21]
+FileName=cset.h
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit22]
+FileName=debug.h
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit23]
+FileName=keyboard.h
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit24]
+FileName=table.h
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit25]
+FileName=timefunc.h
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit26]
+FileName=types.h
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit27]
+FileName=vdc.h
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit28]
+FileName=vmachine.h
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit29]
+FileName=voice.h
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit30]
+FileName=vpp.h
+CompileCpp=1
+Folder=
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit31]
+FileName=o2em.rc
+Folder=Resource
+Compile=1
+Link=0
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[VersionInfo]
+Major=0
+Minor=1
+Release=1
+Build=1
+LanguageID=1033
+CharsetID=1252
+CompanyName=
+FileVersion=
+FileDescription=Developed using the Dev-C++ IDE
+InternalName=
+LegalCopyright=
+LegalTrademarks=
+OriginalFilename=
+ProductName=
+ProductVersion=
+AutoIncBuildNr=0
+
+[Unit32]
+FileName=..\..\..\..\O2EM-WIN\SCORE.C
+CompileCpp=1
+Folder=O2EM118
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
+[Unit33]
+FileName=..\..\..\..\O2EM-WIN\SCORE.H
+CompileCpp=1
+Folder=O2EM118
+Compile=1
+Link=1
+Priority=1000
+OverrideBuildCmd=0
+BuildCmd=
+
diff --git a/src/O2em118.layout b/src/O2em118.layout
new file mode 100755
index 0000000..897ad19
--- /dev/null
+++ b/src/O2em118.layout
@@ -0,0 +1,267 @@
+[Editor_8]
+CursorCol=20
+CursorRow=310
+TopLine=301
+LeftChar=1
+Open=1
+Top=0
+
+[Editors]
+Order=8,1,16,2,-1
+Focused=-1
+
+[Editor_0]
+Open=0
+Top=0
+CursorCol=1
+CursorRow=1
+TopLine=266
+LeftChar=1
+
+[Editor_1]
+Open=1
+Top=0
+CursorCol=19
+CursorRow=18
+TopLine=1
+LeftChar=1
+
+[Editor_2]
+Open=1
+Top=0
+CursorCol=1
+CursorRow=1568
+TopLine=28
+LeftChar=1
+
+[Editor_3]
+Open=0
+Top=0
+CursorCol=1
+CursorRow=79
+TopLine=94
+LeftChar=1
+
+[Editor_4]
+Open=0
+Top=0
+CursorCol=8
+CursorRow=82
+TopLine=67
+LeftChar=1
+
+[Editor_5]
+Open=0
+Top=0
+CursorCol=5
+CursorRow=814
+TopLine=1026
+LeftChar=1
+
+[Editor_6]
+Open=0
+Top=0
+CursorCol=2
+CursorRow=134
+TopLine=132
+LeftChar=1
+
+[Editor_7]
+Open=0
+Top=0
+CursorCol=21
+CursorRow=255
+TopLine=238
+LeftChar=1
+
+[Editor_9]
+Open=0
+Top=0
+CursorCol=27
+CursorRow=59
+TopLine=322
+LeftChar=1
+
+[Editor_10]
+Open=0
+Top=0
+CursorCol=3
+CursorRow=11
+TopLine=1
+LeftChar=1
+
+[Editor_11]
+Open=0
+Top=0
+CursorCol=33
+CursorRow=601
+TopLine=583
+LeftChar=1
+
+[Editor_12]
+Open=0
+Top=0
+CursorCol=21
+CursorRow=79
+TopLine=67
+LeftChar=1
+
+[Editor_13]
+Open=0
+Top=0
+CursorCol=2
+CursorRow=41
+TopLine=137
+LeftChar=1
+
+[Editor_14]
+Open=0
+Top=0
+CursorCol=9
+CursorRow=38
+TopLine=481
+LeftChar=1
+
+[Editor_15]
+Open=0
+Top=0
+CursorCol=1
+CursorRow=1
+TopLine=1
+LeftChar=1
+
+[Editor_16]
+Open=1
+Top=0
+CursorCol=1
+CursorRow=1
+TopLine=1
+LeftChar=1
+
+[Editor_17]
+Open=0
+Top=0
+CursorCol=27
+CursorRow=5
+TopLine=1
+LeftChar=1
+
+[Editor_18]
+Open=0
+Top=0
+CursorCol=1
+CursorRow=62
+TopLine=1
+LeftChar=1
+
+[Editor_19]
+Open=0
+Top=0
+CursorCol=1
+CursorRow=1
+TopLine=1
+LeftChar=1
+
+[Editor_20]
+Open=0
+Top=0
+CursorCol=1
+CursorRow=1
+TopLine=1
+LeftChar=1
+
+[Editor_21]
+Open=0
+Top=0
+CursorCol=1
+CursorRow=1
+TopLine=1
+LeftChar=1
+
+[Editor_22]
+Open=0
+Top=0
+CursorCol=15
+CursorRow=22
+TopLine=11
+LeftChar=1
+
+[Editor_23]
+Open=0
+Top=0
+CursorCol=1
+CursorRow=1
+TopLine=1
+LeftChar=1
+
+[Editor_24]
+Open=0
+Top=0
+CursorCol=1
+CursorRow=1
+TopLine=1
+LeftChar=1
+
+[Editor_25]
+Open=0
+Top=0
+CursorCol=18
+CursorRow=6
+TopLine=1
+LeftChar=1
+
+[Editor_26]
+Open=0
+Top=0
+CursorCol=1
+CursorRow=31
+TopLine=26
+LeftChar=1
+
+[Editor_27]
+Open=0
+Top=0
+CursorCol=1
+CursorRow=3
+TopLine=1
+LeftChar=1
+
+[Editor_28]
+Open=0
+Top=0
+CursorCol=30
+CursorRow=6
+TopLine=1
+LeftChar=1
+
+[Editor_29]
+Open=0
+Top=0
+CursorCol=1
+CursorRow=1
+TopLine=1
+LeftChar=1
+
+[Editor_30]
+Open=0
+Top=0
+CursorCol=1
+CursorRow=4
+TopLine=1
+LeftChar=1
+
+[Editor_31]
+Open=1
+Top=1
+CursorCol=1
+CursorRow=123
+TopLine=114
+LeftChar=1
+
+[Editor_32]
+Open=1
+Top=0
+CursorCol=9
+CursorRow=4
+TopLine=1
+LeftChar=1
diff --git a/src/audio.c b/src/audio.c
new file mode 100755
index 0000000..433d5d0
--- /dev/null
+++ b/src/audio.c
@@ -0,0 +1,219 @@
+
+/*
+ * O2EM Free Odyssey2 / Videopac+ Emulator
+ *
+ * Created by Daniel Boris (c) 1997,1998
+ *
+ * Developed by Andre de la Rocha
+ * Arlindo M. de Oliveira
+ *
+ * http://o2em.sourceforge.net
+ *
+ *
+ *
+ * O2 audio emulation
+ */
+
+
+#include
+#include
+#include
+#include
+#include "cpu.h"
+#include "types.h"
+#include "config.h"
+#include "vmachine.h"
+#include "audio.h"
+
+#ifndef __LIBRETRO__
+#include "allegro.h"
+#else
+extern int SND;
+extern uint8_t soundBuffer[1056];
+#endif
+
+#define SAMPLE_RATE 44100
+#define PERIOD1 11
+#define PERIOD2 44
+
+#define SOUND_BUFFER_LEN 1056
+
+#define AUD_CTRL 0xAA
+#define AUD_D0 0xA7
+#define AUD_D1 0xA8
+#define AUD_D2 0xA9
+
+
+int sound_IRQ;
+#ifndef __LIBRETRO__
+static AUDIOSTREAM *stream=NULL;
+#endif
+FILE *sndlog=NULL;
+
+static double flt_a=0.0, flt_b=0.0;
+static unsigned char flt_prv = 0;
+
+
+static void filter(unsigned char *buf, unsigned long len);
+
+
+void audio_process(unsigned char *buffer){
+ unsigned long aud_data;
+ int volume, re_circ, noise, enabled, intena, period, pnt, cnt, rndbit, pos;
+
+ aud_data = (VDCwrite[AUD_D2] | (VDCwrite[AUD_D1] << 8) | (VDCwrite[AUD_D0] << 16));
+
+ intena = VDCwrite[0xA0] & 0x04;
+
+ pnt = cnt = 0;
+
+ noise = VDCwrite[AUD_CTRL] & 0x10;
+ enabled = VDCwrite[AUD_CTRL] & 0x80;
+ rndbit = (enabled && noise) ? (rand()%2) : 0;
+
+ while (pnt < SOUND_BUFFER_LEN) {
+ pos = (tweakedaudio) ? (pnt/3) : (MAXLINES-1);
+ volume = AudioVector[pos] & 0x0F;
+ enabled = AudioVector[pos] & 0x80;
+ period = (AudioVector[pos] & 0x20) ? PERIOD1 : PERIOD2;
+ re_circ = AudioVector[pos] & 0x40;
+
+ buffer[pnt++] = (enabled) ? ((aud_data & 0x01)^rndbit) * (0x10 * volume) : 0;
+ cnt++;
+
+ if (cnt >= period) {
+ cnt=0;
+ aud_data = (re_circ) ? ((aud_data >> 1) | ((aud_data & 1) << 23)) : (aud_data >> 1);
+ rndbit = (enabled && noise) ? (rand()%2) : 0;
+
+ if (enabled && intena && (!sound_IRQ)) {
+ sound_IRQ = 1;
+ ext_IRQ();
+ }
+ }
+ }
+
+ if (app_data.filter) filter(buffer, SOUND_BUFFER_LEN);
+}
+
+
+
+void update_audio(void) {
+#ifndef __LIBRETRO__
+ unsigned char *p;
+ if (app_data.sound_en) {
+ p = (unsigned char *)get_audio_stream_buffer(stream);
+ if (p) {
+ audio_process(p);
+ if (sndlog) fwrite(p,1,SOUND_BUFFER_LEN,sndlog);
+ free_audio_stream_buffer(stream);
+ }
+ }
+#else
+ //unsigned char *p;
+ //p = (unsigned char *)SNDBUF;
+ //if (p) {
+ // audio_process(p);
+ audio_process(soundBuffer);
+ //}
+#endif
+}
+
+
+void init_audio(void) {
+ int i;
+
+ sound_IRQ=0;
+ if ((app_data.sound_en) || (app_data.voice)) {
+ printf("Initializing sound system...\n");
+#ifndef __LIBRETRO__
+ i = install_sound(DIGI_AUTODETECT, MIDI_NONE, NULL);
+ if (i != 0) {
+ printf(" ERROR: could not initialize sound card\n %s\n",allegro_error);
+ printf(" Sound system disabled\n");
+ app_data.sound_en = 0;
+ app_data.voice = 0;
+ }
+ else {
+ if (digi_driver->name && (strlen(digi_driver->name)>0)){
+ printf(" Sound system initialized ok\n");
+ printf(" Sound driver [%s] detected\n",digi_driver->name);
+ set_volume(-1,-1);
+ init_sound_stream();
+ } else {
+ printf(" ERROR: could not initialize sound card\n");
+ printf(" Sound system disabled\n");
+ app_data.sound_en = 0;
+ app_data.voice = 0;
+ }
+ }
+#else
+ init_sound_stream();
+#endif
+ }
+
+ sndlog = NULL;
+}
+
+
+void init_sound_stream(void){
+ int vol;
+ if (app_data.sound_en){
+ if (app_data.filter)
+ vol = (255*app_data.svolume)/100;
+ else
+ vol = (255*app_data.svolume)/200;
+#ifndef __LIBRETRO__
+ stream = play_audio_stream(SOUND_BUFFER_LEN,8,0,SAMPLE_RATE,vol,128);
+ if (!stream) {
+ printf("Error creating audio stream!\n");
+ app_data.sound_en=0;
+ }
+#endif
+ flt_a = flt_b = 0.0;
+ flt_prv = 0;
+ }
+}
+
+
+void mute_audio(void){
+#ifndef __LIBRETRO__
+ if (app_data.sound_en && stream){
+ stop_audio_stream(stream);
+ stream=NULL;
+ }
+#else
+ SND=0;
+#endif
+}
+
+
+void close_audio(void) {
+#ifndef __LIBRETRO__
+ if (app_data.sound_en && stream) {
+ stop_audio_stream(stream);
+ }
+#endif
+ if (sndlog) fclose(sndlog);
+ app_data.sound_en=0;
+}
+
+
+static void filter(unsigned char *buffer, unsigned long len){
+ static unsigned char buf[SOUND_BUFFER_LEN];
+ int t;
+ unsigned long i;
+ if (len>SOUND_BUFFER_LEN) return;
+ memcpy(buf,buffer,len);
+ for (i=0; i255.0)||(flt_a<-255.0)) flt_a=0.0;
+ buffer[i] = (unsigned char)((flt_a+255.0)/2.0);
+ }
+ flt_prv = buf[len-1];
+}
+
+
diff --git a/src/audio.h b/src/audio.h
new file mode 100755
index 0000000..1ce60a6
--- /dev/null
+++ b/src/audio.h
@@ -0,0 +1,17 @@
+#ifndef __AUDIO_H
+#define __AUDIO_H
+
+void update_audio(void);
+void init_audio(void);
+void close_audio(void);
+void init_sound_stream(void);
+void mute_audio(void);
+
+
+extern int sound_IRQ;
+extern FILE *sndlog;
+
+
+#endif
+
+
diff --git a/src/config.h b/src/config.h
new file mode 100755
index 0000000..eec37a7
--- /dev/null
+++ b/src/config.h
@@ -0,0 +1,14 @@
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#define O2EM_VERSION "1.18"
+#define RELEASE_DATE "(Jan/2007)"
+
+#define ROM_O2 1
+#define ROM_G7400 2
+#define ROM_C52 3
+#define ROM_JOPAC 4
+#define ROM_UNKNOWN 99
+
+#endif
+
diff --git a/src/cpu.c b/src/cpu.c
new file mode 100755
index 0000000..235956e
--- /dev/null
+++ b/src/cpu.c
@@ -0,0 +1,1586 @@
+
+/*
+ * O2EM Free Odyssey2 / Videopac+ Emulator
+ *
+ * Created by Daniel Boris (c) 1997,1998
+ *
+ ** Developed by Andre de la Rocha
+ * Arlindo M. de Oliveira
+ *
+ * http://o2em.sourceforge.net
+ *
+ *
+ *
+ * 8048 microcontroller emulation
+ */
+
+
+#include
+#include "types.h"
+#include "vmachine.h"
+#include "keyboard.h"
+#include "voice.h"
+#include "vdc.h"
+#include "vpp.h"
+#include "cpu.h"
+
+#define push(d) {intRAM[sp++] = (d); if (sp > 23) sp = 8;}
+#define pull() (sp--, (sp < 8)?(sp=23):0, intRAM[sp])
+#define make_psw() {psw = (cy << 7) | ac | f0 | bs | 0x08; psw = psw | ((sp - 8) >> 1);}
+#define illegal(o) {}
+#define undef(i) {printf("** unimplemented instruction %x, %x**\n",i,pc);}
+#define ROM(adr) (rom[(adr) & 0xfff])
+
+
+void init_cpu(void){
+ pc=0;
+ sp=8;
+ bs=0;
+ p1=p2=0xFF;
+ ac=cy=f0=0;
+ A11=A11ff=0;
+ timer_on=0;
+ count_on=0;
+ reg_pnt=0;
+ tirq_en=xirq_en=irq_ex=xirq_pend=tirq_pend=0;
+}
+
+
+void ext_IRQ(void){
+ int_clk = 5; /* length of pulse on /INT */
+ if (xirq_en && !irq_ex) {
+ irq_ex=1;
+ xirq_pend=0;
+ clk+=2;
+ make_psw();
+ push(pc & 0xFF);
+ push(((pc & 0xF00) >> 8) | (psw & 0xF0));
+ pc = 0x03;
+ A11ff=A11;
+ A11=0;
+ }
+ if (pendirq && (!xirq_en)) xirq_pend=1;
+}
+
+
+void tim_IRQ(void){
+ if (tirq_en && !irq_ex) {
+ irq_ex=2;
+ tirq_pend=0;
+ clk+=2;
+ make_psw();
+ push(pc & 0xFF);
+ push(((pc & 0xF00) >> 8) | (psw & 0xF0));
+ pc = 0x07;
+ A11ff=A11;
+ A11=0;
+ }
+ if (pendirq && (!tirq_en)) tirq_pend=1;
+}
+
+
+void make_psw_debug(void){
+ make_psw();
+}
+
+#ifdef __LIBRETRO__
+extern int RLOOP;
+#endif
+
+void cpu_exec(void) {
+ Byte op;
+ ADDRESS adr;
+ Byte dat;
+ int temp;
+
+ #ifndef __LIBRETRO__
+ for (;;)
+ #else
+ while(RLOOP==1)
+ #endif
+ {
+
+ clk=0;
+
+ lastpc=pc;
+ op=ROM(pc++);
+
+ switch (op) {
+ case 0x00: /* NOP */
+ clk++;
+ break;
+ case 0x01: /* ILL */
+ illegal(op);
+ clk++;
+ break;
+ case 0x02: /* OUTL BUS,A */
+ clk+=2;
+ undef(0x02);
+ break;
+ case 0x03: /* ADD A,#data */
+ clk+=2;
+ cy=ac=0;
+ dat=ROM(pc++);
+ if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40;
+ temp=acc+dat;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+ case 0x04: /* JMP */
+ pc=ROM(pc) | A11;
+ clk+=2;
+ break;
+ case 0x05: /* EN I */
+ xirq_en=1;
+ clk++;
+ break;
+ case 0x06: /* ILL */
+ clk++;
+ illegal(op);
+ break;
+ case 0x07: /* DEC A */
+ acc--;
+ clk++;
+ break;
+ case 0x08: /* INS A,BUS*/
+ clk+=2;
+ acc=in_bus();
+ break;
+ case 0x09: /* IN A,Pp */
+ acc=p1;
+ clk+=2;
+ break;
+ case 0x0A: /* IN A,Pp */
+ acc=read_P2();
+ clk+=2;
+ break;
+ case 0x0B: /* ILL */
+ clk++;
+ illegal(op);
+ break;
+ case 0x0C: /* MOVD A,P4 */
+ clk+=2;
+ acc=read_PB(0);
+ break;
+ case 0x0D: /* MOVD A,P5 */
+ clk+=2;
+ acc=read_PB(1);
+ break;
+ case 0x0E: /* MOVD A,P6 */
+ clk+=2;
+ acc=read_PB(2);
+ break;
+ case 0x0F: /* MOVD A,P7 */
+ clk+=2;
+ acc=read_PB(3);
+ break;
+ case 0x10: /* INC @Ri */
+ intRAM[intRAM[reg_pnt] & 0x3F]++;
+ clk++;
+ break;
+ case 0x11: /* INC @Ri */
+ intRAM[intRAM[reg_pnt+1] & 0x3F]++;
+ clk++;
+ break;
+ case 0x12: /* JBb address */
+ clk+=2;
+ dat = ROM(pc);
+ if (acc & 0x01)
+ pc=(pc & 0xF00) | dat;
+ else
+ pc++;
+ break;
+ case 0x13: /* ADDC A,#data */
+ clk+=2;
+ dat=ROM(pc++);
+ ac=0;
+ if (((acc & 0x0f) + (dat & 0x0f) + cy) > 0x0f) ac=0x40;
+ temp=acc+dat+cy;
+ cy=0;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+
+ case 0x14: /* CALL */
+ make_psw();
+ adr = ROM(pc) | A11;
+ pc++;
+ clk+=2;
+ push(pc & 0xFF);
+ push(((pc & 0xF00) >> 8) | (psw & 0xF0));
+ pc = adr;
+ break;
+ case 0x15: /* DIS I */
+ xirq_en=0;
+ clk++;
+ break;
+ case 0x16: /* JTF */
+ clk+=2;
+ dat = ROM(pc);
+ if (t_flag)
+ pc=(pc & 0xF00) | dat;
+ else
+ pc++;
+ t_flag=0;
+ break;
+ case 0x17: /* INC A */
+ acc++;
+ clk++;
+ break;
+ case 0x18: /* INC Rr */
+ intRAM[reg_pnt]++;
+ clk++;
+ break;
+ case 0x19: /* INC Rr */
+ intRAM[reg_pnt+1]++;
+ clk++;
+ break;
+ case 0x1A: /* INC Rr */
+ intRAM[reg_pnt+2]++;
+ clk++;
+ break;
+ case 0x1B: /* INC Rr */
+ intRAM[reg_pnt+3]++;
+ clk++;
+ break;
+ case 0x1C: /* INC Rr */
+ intRAM[reg_pnt+4]++;
+ clk++;
+ break;
+ case 0x1D: /* INC Rr */
+ intRAM[reg_pnt+5]++;
+ clk++;
+ break;
+ case 0x1E: /* INC Rr */
+ intRAM[reg_pnt+6]++;
+ clk++;
+ break;
+ case 0x1F: /* INC Rr */
+ intRAM[reg_pnt+7]++;
+ clk++;
+ break;
+ case 0x20: /* XCH A,@Ri */
+ clk++;
+ dat=acc;
+ acc=intRAM[intRAM[reg_pnt] & 0x3F];
+ intRAM[intRAM[reg_pnt] & 0x3F] = dat;
+ break;
+ case 0x21: /* XCH A,@Ri */
+ clk++;
+ dat=acc;
+ acc=intRAM[intRAM[reg_pnt+1] & 0x3F];
+ intRAM[intRAM[reg_pnt+1] & 0x3F] = dat;
+ break;
+ case 0x22: /* ILL */
+ clk++;
+ illegal(op);
+ break;
+ case 0x23: /* MOV a,#data */
+ clk+=2;
+ acc = ROM(pc++);
+ break;
+
+ case 0x24: /* JMP */
+ pc=ROM(pc) | 0x100 | A11;
+ clk+=2;
+ break;
+ case 0x25: /* EN TCNTI */
+ tirq_en=1;
+ clk++;
+ break;
+ case 0x26: /* JNT0 */
+ clk+=2;
+ dat = ROM(pc);
+ if (!get_voice_status())
+ pc=(pc & 0xF00) | dat;
+ else
+ pc++;
+ break;
+ case 0x27: /* CLR A */
+ clk++;
+ acc=0;
+ break;
+ case 0x28: /* XCH A,Rr */
+ dat=acc;
+ acc=intRAM[reg_pnt];
+ intRAM[reg_pnt]=dat;
+ clk++;
+ break;
+ case 0x29: /* XCH A,Rr */
+ dat=acc;
+ acc=intRAM[reg_pnt+1];
+ intRAM[reg_pnt+1]=dat;
+ clk++;
+ break;
+ case 0x2A: /* XCH A,Rr */
+ dat=acc;
+ acc=intRAM[reg_pnt+2];
+ intRAM[reg_pnt+2]=dat;
+ clk++;
+ break;
+ case 0x2B: /* XCH A,Rr */
+ dat=acc;
+ acc=intRAM[reg_pnt+3];
+ intRAM[reg_pnt+3]=dat;
+ clk++;
+ break;
+ case 0x2C: /* XCH A,Rr */
+ dat=acc;
+ acc=intRAM[reg_pnt+4];
+ intRAM[reg_pnt+4]=dat;
+ clk++;
+ break;
+ case 0x2D: /* XCH A,Rr */
+ dat=acc;
+ acc=intRAM[reg_pnt+5];
+ intRAM[reg_pnt+5]=dat;
+ clk++;
+ break;
+ case 0x2E: /* XCH A,Rr */
+ dat=acc;
+ acc=intRAM[reg_pnt+6];
+ intRAM[reg_pnt+6]=dat;
+ clk++;
+ break;
+ case 0x2F: /* XCH A,Rr */
+ dat=acc;
+ acc=intRAM[reg_pnt+7];
+ intRAM[reg_pnt+7]=dat;
+ clk++;
+ break;
+ case 0x30: /* XCHD A,@Ri */
+ clk++;
+ adr=intRAM[reg_pnt] & 0x3F;
+ dat=acc & 0x0F;
+ acc=acc & 0xF0;
+ acc=acc | (intRAM[adr] & 0x0F);
+ intRAM[adr] &= 0xF0;
+ intRAM[adr] |= dat;
+ break;
+ case 0x31: /* XCHD A,@Ri */
+ clk++;
+ adr=intRAM[reg_pnt+1] & 0x3F;
+ dat=acc & 0x0F;
+ acc=acc & 0xF0;
+ acc=acc | (intRAM[adr] & 0x0F);
+ intRAM[adr] &= 0xF0;
+ intRAM[adr] |= dat;
+ break;
+ case 0x32: /* JBb address */
+ clk+=2;
+ dat=ROM(pc);
+ if (acc & 0x02)
+ pc=(pc & 0xF00) | dat;
+ else
+ pc++;
+ break;
+ case 0x33: /* ILL */
+ clk++;
+ illegal(op);
+ break;
+ case 0x34: /* CALL */
+ make_psw();
+ adr = ROM(pc) | 0x100 | A11;
+ pc++;
+ clk+=2;
+ push(pc & 0xFF);
+ push(((pc & 0xF00) >> 8) | (psw & 0xF0));
+ pc = adr;
+ break;
+ case 0x35: /* DIS TCNTI */
+ tirq_en=0;
+ tirq_pend=0;
+ clk++;
+ break;
+ case 0x36: /* JT0 */
+ clk+=2;
+ dat=ROM(pc);
+ if (get_voice_status())
+ pc=(pc & 0xF00) | dat;
+ else
+ pc++;
+ break;
+ case 0x37: /* CPL A */
+ acc = acc ^ 0xFF;
+ clk++;
+ break;
+ case 0x38: /* ILL */
+ clk++;
+ illegal(op);
+ break;
+ case 0x39: /* OUTL P1,A */
+ clk+=2;
+ write_p1(acc);
+ break;
+ case 0x3A: /* OUTL P2,A */
+ clk+=2;
+ p2=acc;
+ break;
+ case 0x3B: /* ILL */
+ clk++;
+ illegal(op);
+ break;
+ case 0x3C: /* MOVD P4,A */
+ clk+=2;
+ write_PB(0,acc);
+ break;
+ case 0x3D: /* MOVD P5,A */
+ clk+=2;
+ write_PB(1,acc);
+ break;
+ case 0x3E: /* MOVD P6,A */
+ clk+=2;
+ write_PB(2,acc);
+ break;
+ case 0x3F: /* MOVD P7,A */
+ clk+=2;
+ write_PB(3,acc);
+ break;
+ case 0x40: /* ORL A,@Ri */
+ clk++;
+ acc = acc | intRAM[intRAM[reg_pnt] & 0x3F];
+ break;
+ case 0x41: /* ORL A,@Ri */
+ clk++;
+ acc = acc | intRAM[intRAM[reg_pnt+1] & 0x3F];
+ break;
+ case 0x42: /* MOV A,T */
+ clk++;
+ acc = itimer;
+ break;
+ case 0x43: /* ORL A,#data */
+ clk+=2;
+ acc = acc | ROM(pc++);
+ break;
+ case 0x44: /* JMP */
+ pc=ROM(pc) | 0x200 | A11;
+ clk+=2;
+ break;
+ case 0x45: /* STRT CNT */
+ /* printf("START: %d=%d\n",master_clk/22,itimer); */
+ count_on=1;
+ clk++;
+ break;
+ case 0x46: /* JNT1 */
+ clk+=2;
+ dat = ROM(pc);
+ if (!read_t1())
+ pc=(pc & 0xF00) | dat;
+ else
+ pc++;
+ break;
+ case 0x47: /* SWAP A */
+ clk++;
+ dat=(acc & 0xF0) >> 4;
+ acc = acc << 4;
+ acc = acc | dat;
+ break;
+ case 0x48: /* ORL A,Rr */
+ clk++;
+ acc = acc | intRAM[reg_pnt];
+ break;
+ case 0x49: /* ORL A,Rr */
+ clk++;
+ acc = acc | intRAM[reg_pnt+1];
+ break;
+ case 0x4A: /* ORL A,Rr */
+ clk++;
+ acc = acc | intRAM[reg_pnt+2];
+ break;
+ case 0x4B: /* ORL A,Rr */
+ clk++;
+ acc = acc | intRAM[reg_pnt+3];
+ break;
+ case 0x4C: /* ORL A,Rr */
+ clk++;
+ acc = acc | intRAM[reg_pnt+4];
+ break;
+ case 0x4D: /* ORL A,Rr */
+ clk++;
+ acc = acc | intRAM[reg_pnt+5];
+ break;
+ case 0x4E: /* ORL A,Rr */
+ clk++;
+ acc = acc | intRAM[reg_pnt+6];
+ break;
+ case 0x4F: /* ORL A,Rr */
+ clk++;
+ acc = acc | intRAM[reg_pnt+7];
+ break;
+
+ case 0x50: /* ANL A,@Ri */
+ acc = acc & intRAM[intRAM[reg_pnt] & 0x3F];
+ clk++;
+ break;
+ case 0x51: /* ANL A,@Ri */
+ acc = acc & intRAM[intRAM[reg_pnt+1] & 0x3F];
+ clk++;
+ break;
+ case 0x52: /* JBb address */
+ clk+=2;
+ dat=ROM(pc);
+ if (acc & 0x04)
+ pc=(pc & 0xF00) | dat;
+ else
+ pc++;
+ break;
+ case 0x53: /* ANL A,#data */
+ clk+=2;
+ acc = acc & ROM(pc++);
+ break;
+ case 0x54: /* CALL */
+ make_psw();
+ adr = ROM(pc) | 0x200 | A11;
+ pc++;
+ clk+=2;
+ push(pc & 0xFF);
+ push(((pc & 0xF00) >> 8) | (psw & 0xF0));
+ pc = adr;
+ break;
+ case 0x55: /* STRT T */
+ timer_on=1;
+ clk++;
+ break;
+ case 0x56: /* JT1 */
+ clk+=2;
+ dat = ROM(pc);
+ if (read_t1())
+ pc=(pc & 0xF00) | dat;
+ else
+ pc++;
+ break;
+ case 0x57: /* DA A */
+ clk++;
+ if (((acc & 0x0F) > 0x09) || ac) {
+ if (acc>0xf9) cy=1;
+ acc += 6;
+ }
+ dat = (acc & 0xF0) >> 4;
+ if ((dat > 9) || cy) {
+ dat+=6;
+ cy=1;
+ }
+ acc = (acc & 0x0F) | (dat << 4);
+ break;
+ case 0x58: /* ANL A,Rr */
+ clk++;
+ acc = acc & intRAM[reg_pnt];
+ break;
+ case 0x59: /* ANL A,Rr */
+ clk++;
+ acc = acc & intRAM[reg_pnt+1];
+ break;
+ case 0x5A: /* ANL A,Rr */
+ clk++;
+ acc = acc & intRAM[reg_pnt+2];
+ break;
+ case 0x5B: /* ANL A,Rr */
+ clk++;
+ acc = acc & intRAM[reg_pnt+3];
+ break;
+ case 0x5C: /* ANL A,Rr */
+ clk++;
+ acc = acc & intRAM[reg_pnt+4];
+ break;
+ case 0x5D: /* ANL A,Rr */
+ clk++;
+ acc = acc & intRAM[reg_pnt+5];
+ break;
+ case 0x5E: /* ANL A,Rr */
+ clk++;
+ acc = acc & intRAM[reg_pnt+6];
+ break;
+ case 0x5F: /* ANL A,Rr */
+ clk++;
+ acc = acc & intRAM[reg_pnt+7];
+ break;
+
+ case 0x60: /* ADD A,@Ri */
+ clk++;
+ cy=ac=0;
+ dat=intRAM[intRAM[reg_pnt] & 0x3F];
+ if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40;
+ temp=acc+dat;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+ case 0x61: /* ADD A,@Ri */
+ clk++;
+ cy=ac=0;
+ dat=intRAM[intRAM[reg_pnt+1] & 0x3F];
+ if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40;
+ temp=acc+dat;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+ case 0x62: /* MOV T,A */
+ clk++;
+ itimer=acc;
+ break;
+ case 0x63: /* ILL */
+ clk++;
+ illegal(op);
+ break;
+ case 0x64: /* JMP */
+ pc=ROM(pc) | 0x300 | A11;
+ clk+=2;
+ break;
+ case 0x65: /* STOP TCNT */
+ clk++;
+ /* printf("STOP %d\n",master_clk/22); */
+ count_on=timer_on=0;
+ break;
+ case 0x66: /* ILL */
+ clk++;
+ illegal(op);
+ break;
+ case 0x67: /* RRC A */
+ dat=cy;
+ cy=acc & 0x01;
+ acc = acc >> 1;
+ if (dat)
+ acc = acc | 0x80;
+ else
+ acc = acc & 0x7F;
+ clk++;
+ break;
+ case 0x68: /* ADD A,Rr */
+ clk++;
+ cy=ac=0;
+ dat=intRAM[reg_pnt];
+ if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40;
+ temp=acc+dat;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+ case 0x69: /* ADD A,Rr */
+ clk++;
+ cy=ac=0;
+ dat=intRAM[reg_pnt+1];
+ if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40;
+ temp=acc+dat;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+ case 0x6A: /* ADD A,Rr */
+ clk++;
+ cy=ac=0;
+ dat=intRAM[reg_pnt+2];
+ if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40;
+ temp=acc+dat;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+ case 0x6B: /* ADD A,Rr */
+ clk++;
+ cy=ac=0;
+ dat=intRAM[reg_pnt+3];
+ if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40;
+ temp=acc+dat;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+ case 0x6C: /* ADD A,Rr */
+ clk++;
+ cy=ac=0;
+ dat=intRAM[reg_pnt+4];
+ if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40;
+ temp=acc+dat;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+ case 0x6D: /* ADD A,Rr */
+ clk++;
+ cy=ac=0;
+ dat=intRAM[reg_pnt+5];
+ if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40;
+ temp=acc+dat;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+ case 0x6E: /* ADD A,Rr */
+ clk++;
+ cy=ac=0;
+ dat=intRAM[reg_pnt+6];
+ if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40;
+ temp=acc+dat;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+ case 0x6F: /* ADD A,Rr */
+ clk++;
+ cy=ac=0;
+ dat=intRAM[reg_pnt+7];
+ if (((acc & 0x0f) + (dat & 0x0f)) > 0x0f) ac=0x40;
+ temp=acc+dat;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+ case 0x70: /* ADDC A,@Ri */
+ clk++;
+ ac=0;
+ dat=intRAM[intRAM[reg_pnt] & 0x3F];
+ if (((acc & 0x0f) + (dat & 0x0f) + cy) > 0x0f) ac=0x40;
+ temp=acc+dat+cy;
+ cy=0;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+ case 0x71: /* ADDC A,@Ri */
+ clk++;
+ ac=0;
+ dat=intRAM[intRAM[reg_pnt+1] & 0x3F];
+ if (((acc & 0x0f) + (dat & 0x0f) + cy) > 0x0f) ac=0x40;
+ temp=acc+dat+cy;
+ cy=0;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+
+ case 0x72: /* JBb address */
+ clk+=2;
+ dat=ROM(pc);
+ if (acc & 0x08)
+ pc=(pc & 0xF00) | dat;
+ else
+ pc++;
+ break;
+ case 0x73: /* ILL */
+ clk++;
+ illegal(op);
+ break;
+ case 0x74: /* CALL */
+ make_psw();
+ adr = ROM(pc) | 0x300 | A11;
+ pc++;
+ clk+=2;
+ push(pc & 0xFF);
+ push(((pc & 0xF00) >> 8) | (psw & 0xF0));
+ pc = adr;
+ break;
+ case 0x75: /* EN CLK */
+ clk++;
+ undef(op);
+ break;
+ case 0x76: /* JF1 address */
+ clk+=2;
+ dat=ROM(pc);
+ if (f1)
+ pc=(pc & 0xF00) | dat;
+ else
+ pc++;
+ break;
+ case 0x77: /* RR A */
+ clk++;
+ dat=acc & 0x01;
+ acc = acc >> 1;
+ if (dat)
+ acc = acc | 0x80;
+ else
+ acc = acc & 0x7f;
+ break;
+
+ case 0x78: /* ADDC A,Rr */
+ clk++;
+ ac=0;
+ dat=intRAM[reg_pnt];
+ if (((acc & 0x0f) + (dat & 0x0f)+cy) > 0x0f) ac=0x40;
+ temp=acc+dat+cy;
+ cy=0;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+ case 0x79: /* ADDC A,Rr */
+ clk++;
+ ac=0;
+ dat=intRAM[reg_pnt+1];
+ if (((acc & 0x0f) + (dat & 0x0f)+cy) > 0x0f) ac=0x40;
+ temp=acc+dat+cy;
+ cy=0;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+ case 0x7A: /* ADDC A,Rr */
+ clk++;
+ ac=0;
+ dat=intRAM[reg_pnt+2];
+ if (((acc & 0x0f) + (dat & 0x0f)+cy) > 0x0f) ac=0x40;
+ temp=acc+dat+cy;
+ cy=0;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+ case 0x7B: /* ADDC A,Rr */
+ clk++;
+ ac=0;
+ dat=intRAM[reg_pnt+3];
+ if (((acc & 0x0f) + (dat & 0x0f)+cy) > 0x0f) ac=0x40;
+ temp=acc+dat+cy;
+ cy=0;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+ case 0x7C: /* ADDC A,Rr */
+ clk++;
+ ac=0;
+ dat=intRAM[reg_pnt+4];
+ if (((acc & 0x0f) + (dat & 0x0f)+cy) > 0x0f) ac=0x40;
+ temp=acc+dat+cy;
+ cy=0;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+ case 0x7D: /* ADDC A,Rr */
+ clk++;
+ ac=0;
+ dat=intRAM[reg_pnt+5];
+ if (((acc & 0x0f) + (dat & 0x0f)+cy) > 0x0f) ac=0x40;
+ temp=acc+dat+cy;
+ cy=0;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+ case 0x7E: /* ADDC A,Rr */
+ clk++;
+ ac=0;
+ dat=intRAM[reg_pnt+6];
+ if (((acc & 0x0f) + (dat & 0x0f)+cy) > 0x0f) ac=0x40;
+ temp=acc+dat+cy;
+ cy=0;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+ case 0x7F: /* ADDC A,Rr */
+ clk++;
+ ac=0;
+ dat=intRAM[reg_pnt+7];
+ if (((acc & 0x0f) + (dat & 0x0f)+cy) > 0x0f) ac=0x40;
+ temp=acc+dat+cy;
+ cy=0;
+ if (temp > 0xFF) cy=1;
+ acc=(temp & 0xFF);
+ break;
+
+ case 0x80: /* MOVX A,@Ri */
+ acc=ext_read(intRAM[reg_pnt]);
+ clk+=2;
+ break;
+ case 0x81: /* MOVX A,@Ri */
+ acc=ext_read(intRAM[reg_pnt+1]);
+ clk+=2;
+ break;
+ case 0x82: /* ILL */
+ clk++;
+ illegal(op);
+ break;
+ case 0x83: /* RET */
+ clk+=2;
+ pc = ((pull() & 0x0F) << 8);
+ pc = pc | pull();
+ break;
+ case 0x84: /* JMP */
+ pc=ROM(pc) | 0x400 | A11;
+ clk+=2;
+ break;
+ case 0x85: /* CLR F0 */
+ clk++;
+ f0=0;
+ break;
+ case 0x86: /* JNI address */
+ clk+=2;
+ dat=ROM(pc);
+ if (int_clk > 0)
+ pc=(pc & 0xF00) | dat;
+ else
+ pc++;
+ break;
+ case 0x87: /* ILL */
+ illegal(op);
+ clk++;
+ break;
+ case 0x88: /* BUS,#data */
+ clk+=2;
+ undef(op);
+ break;
+ case 0x89: /* ORL Pp,#data */
+ write_p1(p1 | ROM(pc++));
+ clk+=2;
+ break;
+ case 0x8A: /* ORL Pp,#data */
+ p2 = p2 | ROM(pc++);
+ clk+=2;
+ break;
+ case 0x8B: /* ILL */
+ illegal(op);
+ clk++;
+ break;
+ case 0x8C: /* ORLD P4,A */
+ write_PB(0,read_PB(0)|acc);
+ clk+=2;
+ break;
+ case 0x8D: /* ORLD P5,A */
+ write_PB(1,read_PB(1)|acc);
+ clk+=2;
+ break;
+ case 0x8E: /* ORLD P6,A */
+ write_PB(2,read_PB(2)|acc);
+ clk+=2;
+ break;
+ case 0x8F: /* ORLD P7,A */
+ write_PB(3,read_PB(3)|acc);
+ clk+=2;
+ break;
+ case 0x90: /* MOVX @Ri,A */
+ ext_write(acc,intRAM[reg_pnt]);
+ clk+=2;
+ break;
+ case 0x91: /* MOVX @Ri,A */
+ ext_write(acc,intRAM[reg_pnt+1]);
+ clk+=2;
+ break;
+ case 0x92: /* JBb address */
+ clk+=2;
+ dat=ROM(pc);
+ if (acc & 0x10)
+ pc=(pc & 0xF00) | dat;
+ else
+ pc++;
+ break;
+ case 0x93: /* RETR*/
+ /* printf("RETR %d\n",master_clk/22); */
+ clk+=2;
+ dat=pull();
+ pc = (dat & 0x0F) << 8;
+ cy = (dat & 0x80) >> 7;
+ ac = dat & 0x40;
+ f0 = dat & 0x20;
+ bs = dat & 0x10;
+ if (bs)
+ reg_pnt=24;
+ else
+ reg_pnt=0;
+ pc = pc | pull();
+ irq_ex=0;
+ A11=A11ff;
+ break;
+ case 0x94: /* CALL */
+ make_psw();
+ adr = ROM(pc) | 0x400 | A11;
+ pc++;
+ clk+=2;
+ push(pc & 0xFF);
+ push(((pc & 0xF00) >> 8) | (psw & 0xF0));
+ pc = adr;
+ break;
+ case 0x95: /* CPL F0 */
+ f0 = f0 ^ 0x20;
+ clk++;
+ break;
+ case 0x96: /* JNZ address */
+ clk+=2;
+ dat=ROM(pc);
+ if (acc != 0)
+ pc=(pc & 0xF00) | dat;
+ else
+ pc++;
+ break;
+ case 0x97: /* CLR C */
+ cy=0;
+ clk++;
+ break;
+ case 0x98: /* ANL BUS,#data */
+ clk+=2;
+ undef(op);
+ break;
+ case 0x99: /* ANL Pp,#data */
+ write_p1(p1 & ROM(pc++));
+ clk+=2;
+ break;
+ case 0x9A: /* ANL Pp,#data */
+ p2 = p2 & ROM(pc++);
+ clk+=2;
+ break;
+ case 0x9B: /* ILL */
+ illegal(op);
+ clk++;
+ break;
+ case 0x9C: /* ANLD P4,A */
+ write_PB(0,read_PB(0)&acc);
+ clk+=2;
+ break;
+ case 0x9D: /* ANLD P5,A */
+ write_PB(1,read_PB(1)&acc);
+ clk+=2;
+ break;
+ case 0x9E: /* ANLD P6,A */
+ write_PB(2,read_PB(2)&acc);
+ clk+=2;
+ break;
+ case 0x9F: /* ANLD P7,A */
+ write_PB(3,read_PB(3)&acc);
+ clk+=2;
+ break;
+ case 0xA0: /* MOV @Ri,A */
+ intRAM[intRAM[reg_pnt] & 0x3F]=acc;
+ clk++;
+ break;
+ case 0xA1: /* MOV @Ri,A */
+ intRAM[intRAM[reg_pnt+1] & 0x3F]=acc;
+ clk++;
+ break;
+ case 0xA2: /* ILL */
+ clk++;
+ illegal(op);
+ break;
+ case 0xA3: /* MOVP A,@A */
+ acc=ROM((pc & 0xF00) | acc);
+ clk+=2;
+ break;
+ case 0xA4: /* JMP */
+ pc=ROM(pc) | 0x500 | A11;
+ clk+=2;
+ break;
+ case 0xA5: /* CLR F1 */
+ clk++;
+ f1=0;
+ break;
+ case 0xA6: /* ILL */
+ illegal(op);
+ clk++;
+ break;
+ case 0xA7: /* CPL C */
+ cy = cy ^ 0x01;
+ clk++;
+ break;
+ case 0xA8: /* MOV Rr,A */
+ intRAM[reg_pnt] = acc;
+ clk++;
+ break;
+ case 0xA9: /* MOV Rr,A */
+ intRAM[reg_pnt+1] = acc;
+ clk++;
+ break;
+ case 0xAA: /* MOV Rr,A */
+ intRAM[reg_pnt+2] = acc;
+ clk++;
+ break;
+ case 0xAB: /* MOV Rr,A */
+ intRAM[reg_pnt+3] = acc;
+ clk++;
+ break;
+ case 0xAC: /* MOV Rr,A */
+ intRAM[reg_pnt+4] = acc;
+ clk++;
+ break;
+ case 0xAD: /* MOV Rr,A */
+ intRAM[reg_pnt+5] = acc;
+ clk++;
+ break;
+ case 0xAE: /* MOV Rr,A */
+ intRAM[reg_pnt+6] = acc;
+ clk++;
+ break;
+ case 0xAF: /* MOV Rr,A */
+ intRAM[reg_pnt+7] = acc;
+ clk++;
+ break;
+ case 0xB0: /* MOV @Ri,#data */
+ intRAM[intRAM[reg_pnt] & 0x3F]=ROM(pc++);
+ clk+=2;
+ break;
+ case 0xB1: /* MOV @Ri,#data */
+ intRAM[intRAM[reg_pnt+1] & 0x3F]=ROM(pc++);
+ clk+=2;
+ break;
+ case 0xB2: /* JBb address */
+ clk+=2;
+ dat=ROM(pc);
+ if (acc & 0x20)
+ pc=(pc & 0xF00) | dat;
+ else
+ pc++;
+ break;
+ case 0xB3: /* JMPP @A */
+ adr = (pc & 0xF00) | acc;
+ pc=(pc & 0xF00) | ROM(adr);
+ clk+=2;
+ break;
+ case 0xB4: /* CALL */
+ make_psw();
+ adr = ROM(pc) | 0x500 | A11;
+ pc++;
+ clk+=2;
+ push(pc & 0xFF);
+ push(((pc & 0xF00) >> 8) | (psw & 0xF0));
+ pc = adr;
+ break;
+ case 0xB5: /* CPL F1 */
+ f1 = f1 ^ 0x01;
+ clk++;
+ break;
+ case 0xB6: /* JF0 address */
+ clk+=2;
+ dat=ROM(pc);
+ if (f0)
+ pc=(pc & 0xF00) | dat;
+ else
+ pc++;
+ break;
+ case 0xB7: /* ILL */
+ clk++;
+ illegal(op);
+ break;
+ case 0xB8: /* MOV Rr,#data */
+ intRAM[reg_pnt]=ROM(pc++);
+ clk+=2;
+ break;
+ case 0xB9: /* MOV Rr,#data */
+ intRAM[reg_pnt+1]=ROM(pc++);
+ clk+=2;
+ break;
+ case 0xBA: /* MOV Rr,#data */
+ intRAM[reg_pnt+2]=ROM(pc++);
+ clk+=2;
+ break;
+ case 0xBB: /* MOV Rr,#data */
+ intRAM[reg_pnt+3]=ROM(pc++);
+ clk+=2;
+ break;
+ case 0xBC: /* MOV Rr,#data */
+ intRAM[reg_pnt+4]=ROM(pc++);
+ clk+=2;
+ break;
+ case 0xBD: /* MOV Rr,#data */
+ intRAM[reg_pnt+5]=ROM(pc++);
+ clk+=2;
+ break;
+ case 0xBE: /* MOV Rr,#data */
+ intRAM[reg_pnt+6]=ROM(pc++);
+ clk+=2;
+ break;
+ case 0xBF: /* MOV Rr,#data */
+ intRAM[reg_pnt+7]=ROM(pc++);
+ clk+=2;
+ break;
+ case 0xC0: /* ILL */
+ illegal(op);
+ clk++;
+ break;
+ case 0xC1: /* ILL */
+ illegal(op);
+ clk++;
+ break;
+ case 0xC2: /* ILL */
+ illegal(op);
+ clk++;
+ break;
+ case 0xC3: /* ILL */
+ illegal(op);
+ clk++;
+ break;
+ case 0xC4: /* JMP */
+ pc=ROM(pc) | 0x600 | A11;
+ clk+=2;
+ break;
+ case 0xC5: /* SEL RB0 */
+ bs=reg_pnt=0;
+ clk++;
+ break;
+ case 0xC6: /* JZ address */
+ clk+=2;
+ dat=ROM(pc);
+ if (acc == 0)
+ pc=(pc & 0xF00) | dat;
+ else
+ pc++;
+ break;
+ case 0xC7: /* MOV A,PSW */
+ clk++;
+ make_psw();
+ acc=psw;
+ break;
+ case 0xC8: /* DEC Rr */
+ intRAM[reg_pnt]--;
+ clk++;
+ break;
+ case 0xC9: /* DEC Rr */
+ intRAM[reg_pnt+1]--;
+ clk++;
+ break;
+ case 0xCA: /* DEC Rr */
+ intRAM[reg_pnt+2]--;
+ clk++;
+ break;
+ case 0xCB: /* DEC Rr */
+ intRAM[reg_pnt+3]--;
+ clk++;
+ break;
+ case 0xCC: /* DEC Rr */
+ intRAM[reg_pnt+4]--;
+ clk++;
+ break;
+ case 0xCD: /* DEC Rr */
+ intRAM[reg_pnt+5]--;
+ clk++;
+ break;
+ case 0xCE: /* DEC Rr */
+ intRAM[reg_pnt+6]--;
+ clk++;
+ break;
+ case 0xCF: /* DEC Rr */
+ intRAM[reg_pnt+7]--;
+ clk++;
+ break;
+ case 0xD0: /* XRL A,@Ri */
+ acc = acc ^ intRAM[intRAM[reg_pnt] & 0x3F];
+ clk++;
+ break;
+ case 0xD1: /* XRL A,@Ri */
+ acc = acc ^ intRAM[intRAM[reg_pnt+1] & 0x3F];
+ clk++;
+ break;
+ case 0xD2: /* JBb address */
+ clk+=2;
+ dat = ROM(pc);
+ if (acc & 0x40)
+ pc=(pc & 0xF00) | dat;
+ else
+ pc++;
+ break;
+ case 0xD3: /* XRL A,#data */
+ clk+=2;
+ acc = acc ^ ROM(pc++);
+ break;
+ case 0xD4: /* CALL */
+ make_psw();
+ adr = ROM(pc) | 0x600 | A11;
+ pc++;
+ clk+=2;
+ push(pc & 0xFF);
+ push(((pc & 0xF00) >> 8) | (psw & 0xF0));
+ pc = adr;
+ break;
+ case 0xD5: /* SEL RB1 */
+ bs=0x10;
+ reg_pnt=24;
+ clk++;
+ break;
+ case 0xD6: /* ILL */
+ illegal(op);
+ clk++;
+ break;
+ case 0xD7: /* MOV PSW,A */
+ psw=acc;
+ clk++;
+ cy = (psw & 0x80) >> 7;
+ ac = psw & 0x40;
+ f0 = psw & 0x20;
+ bs = psw & 0x10;
+ if (bs)
+ reg_pnt = 24;
+ else
+ reg_pnt = 0;
+ sp = (psw & 0x07) << 1;
+ sp+=8;
+ break;
+ case 0xD8: /* XRL A,Rr */
+ acc = acc ^ intRAM[reg_pnt];
+ clk++;
+ break;
+ case 0xD9: /* XRL A,Rr */
+ acc = acc ^ intRAM[reg_pnt+1];
+ clk++;
+ break;
+ case 0xDA: /* XRL A,Rr */
+ acc = acc ^ intRAM[reg_pnt+2];
+ clk++;
+ break;
+ case 0xDB: /* XRL A,Rr */
+ acc = acc ^ intRAM[reg_pnt+3];
+ clk++;
+ break;
+ case 0xDC: /* XRL A,Rr */
+ acc = acc ^ intRAM[reg_pnt+4];
+ clk++;
+ break;
+ case 0xDD: /* XRL A,Rr */
+ acc = acc ^ intRAM[reg_pnt+5];
+ clk++;
+ break;
+ case 0xDE: /* XRL A,Rr */
+ acc = acc ^ intRAM[reg_pnt+6];
+ clk++;
+ break;
+ case 0xDF: /* XRL A,Rr */
+ acc = acc ^ intRAM[reg_pnt+7];
+ clk++;
+ break;
+ case 0xE0: /* ILL */
+ clk++;
+ illegal(op);
+ break;
+ case 0xE1: /* ILL */
+ clk++;
+ illegal(op);
+ break;
+ case 0xE2: /* ILL */
+ clk++;
+ illegal(op);
+ break;
+ case 0xE3: /* MOVP3 A,@A */
+
+ adr = 0x300 | acc;
+ acc=ROM(adr);
+ clk+=2;
+ break;
+ case 0xE4: /* JMP */
+ pc=ROM(pc) | 0x700 | A11;
+ clk+=2;
+ break;
+ case 0xE5: /* SEL MB0 */
+ A11=0;
+ A11ff = 0;
+ clk++;
+ break;
+ case 0xE6: /* JNC address */
+ clk+=2;
+ dat=ROM(pc);
+ if (!cy)
+ pc=(pc & 0xF00) | dat;
+ else
+ pc++;
+ break;
+ case 0xE7: /* RL A */
+ clk++;
+ dat=acc & 0x80;
+ acc = acc << 1;
+ if (dat)
+ acc = acc | 0x01;
+ else
+ acc = acc & 0xFE;
+ break;
+ case 0xE8: /* DJNZ Rr,address */
+ clk+=2;
+ intRAM[reg_pnt]--;
+ dat=ROM(pc);
+ if (intRAM[reg_pnt] != 0) {
+ pc = pc & 0xF00;
+ pc = pc | dat;
+ } else pc++;
+ break;
+ case 0xE9: /* DJNZ Rr,address */
+ clk+=2;
+ intRAM[reg_pnt+1]--;
+ dat=ROM(pc);
+ if (intRAM[reg_pnt+1] != 0) {
+ pc = pc & 0xF00;
+ pc = pc | dat;
+ } else pc++;
+ break;
+ case 0xEA: /* DJNZ Rr,address */
+ clk+=2;
+ intRAM[reg_pnt+2]--;
+ dat=ROM(pc);
+ if (intRAM[reg_pnt+2] != 0) {
+ pc = pc & 0xF00;
+ pc = pc | dat;
+ } else pc++;
+ break;
+ case 0xEB: /* DJNZ Rr,address */
+ clk+=2;
+ intRAM[reg_pnt+3]--;
+ dat=ROM(pc);
+ if (intRAM[reg_pnt+3] != 0) {
+ pc = pc & 0xF00;
+ pc = pc | dat;
+ } else pc++;
+ break;
+ case 0xEC: /* DJNZ Rr,address */
+ clk+=2;
+ intRAM[reg_pnt+4]--;
+ dat=ROM(pc);
+ if (intRAM[reg_pnt+4] != 0) {
+ pc = pc & 0xF00;
+ pc = pc | dat;
+ } else pc++;
+ break;
+ case 0xED: /* DJNZ Rr,address */
+ clk+=2;
+ intRAM[reg_pnt+5]--;
+ dat=ROM(pc);
+ if (intRAM[reg_pnt+5] != 0) {
+ pc = pc & 0xF00;
+ pc = pc | dat;
+ } else pc++;
+ break;
+ case 0xEE: /* DJNZ Rr,address */
+ clk+=2;
+ intRAM[reg_pnt+6]--;
+ dat=ROM(pc);
+ if (intRAM[reg_pnt+6] != 0) {
+ pc = pc & 0xF00;
+ pc = pc | dat;
+ } else pc++;
+ break;
+ case 0xEF: /* DJNZ Rr,address */
+ clk+=2;
+ intRAM[reg_pnt+7]--;
+ dat=ROM(pc);
+ if (intRAM[reg_pnt+7] != 0) {
+ pc = pc & 0xF00;
+ pc = pc | dat;
+ } else pc++;
+ break;
+ case 0xF0: /* MOV A,@Ri */
+ clk++;
+ acc=intRAM[intRAM[reg_pnt] & 0x3F];
+ break;
+ case 0xF1: /* MOV A,@Ri */
+ clk++;
+ acc=intRAM[intRAM[reg_pnt + 1] & 0x3F];
+ break;
+ case 0xF2: /* JBb address */
+ clk+=2;
+ dat=ROM(pc);
+ if (acc & 0x80)
+ pc=(pc & 0xF00) | dat;
+ else
+ pc++;
+ break;
+ case 0xF3: /* ILL */
+ illegal(op);
+ clk++;
+ break;
+ case 0xF4: /* CALL */
+ clk+=2;
+ make_psw();
+ adr = ROM(pc) | 0x700 | A11;
+ pc++;
+ push(pc & 0xFF);
+ push(((pc & 0xF00) >> 8) | (psw & 0xF0));
+ pc = adr;
+ break;
+ case 0xF5: /* SEL MB1 */
+ if (irq_ex) {
+ A11ff = 0x800;
+ }
+ else
+ {
+ A11=0x800;
+ A11ff = 0x800;
+ }
+ clk++;
+ break;
+ case 0xF6: /* JC address */
+ clk+=2;
+ dat=ROM(pc);
+ if (cy)
+ pc=(pc & 0xF00) | dat;
+ else
+ pc++;
+ break;
+ case 0xF7: /* RLC A */
+ dat=cy;
+ cy=(acc & 0x80) >> 7;
+ acc = acc << 1;
+ if (dat)
+ acc = acc | 0x01;
+ else
+ acc = acc & 0xFE;
+ clk++;
+ break;
+ case 0xF8: /* MOV A,Rr */
+ clk++;
+ acc = intRAM[reg_pnt];
+ break;
+ case 0xF9: /* MOV A,Rr */
+ clk++;
+ acc = intRAM[reg_pnt + 1];
+ break;
+ case 0xFA: /* MOV A,Rr */
+ clk++;
+ acc = intRAM[reg_pnt + 2];
+ break;
+ case 0xFB: /* MOV A,Rr */
+ clk++;
+ acc = intRAM[reg_pnt + 3];
+ break;
+ case 0xFC: /* MOV A,Rr */
+ clk++;
+ acc = intRAM[reg_pnt + 4];
+ break;
+ case 0xFD: /* MOV A,Rr */
+ clk++;
+ acc = intRAM[reg_pnt + 5];
+ break;
+ case 0xFE: /* MOV A,Rr */
+ clk++;
+ acc = intRAM[reg_pnt + 6];
+ break;
+ case 0xFF: /* MOV A,Rr */
+ clk++;
+ acc = intRAM[reg_pnt + 7];
+ break;
+ }
+
+
+ master_clk+=clk;
+ h_clk+=clk;
+ clk_counter+=clk;
+
+ /* flag for JNI */
+ if (int_clk > clk)
+ int_clk -= clk;
+ else
+ int_clk = 0;
+
+ /* pending IRQs */
+ if (xirq_pend) ext_IRQ();
+ if (tirq_pend) tim_IRQ();
+
+ if (h_clk > LINECNT-1) {
+ h_clk-=LINECNT;
+ if (enahirq && (VDCwrite[0xA0] & 0x01)) ext_IRQ();
+ if (count_on && mstate == 0) {
+ itimer++;
+ if (itimer == 0) {
+ t_flag=1;
+ tim_IRQ();
+ draw_region();
+ }
+ }
+ }
+
+ if (timer_on) {
+ master_count+=clk;
+ if (master_count > 31) {
+ master_count-=31;
+ itimer++;
+ if (itimer == 0) {
+ t_flag=1;
+ tim_IRQ();
+ }
+ }
+ }
+
+ if ((mstate==0) && (master_clk > VBLCLK)){
+ handle_vbl();
+ }
+ if ((mstate==1) && (master_clk > evblclk)) {
+ handle_evbl();
+#ifdef __LIBRETRO__
+ RLOOP=0;
+#endif
+ if (app_data.crc == 0xA7344D1F) handle_evbll(); /* Atlantis */
+ break;
+ }
+
+#ifndef __LIBRETRO__
+ if (app_data.debug) break;
+
+ if (pc==app_data.breakpoint) break;
+#endif
+ }
+
+}
+
diff --git a/src/cpu.h b/src/cpu.h
new file mode 100755
index 0000000..ef0c5f0
--- /dev/null
+++ b/src/cpu.h
@@ -0,0 +1,65 @@
+#ifndef CPU_H
+#define CPU_H
+
+#include "types.h"
+
+extern Byte acc; /* Accumulator */
+extern ADDRESS pc; /* Program counter */
+extern long clk; /* clock */
+
+extern Byte itimer; /* Internal timer */
+extern Byte reg_pnt; /* pointer to register bank */
+extern Byte timer_on; /* 0=timer off/1=timer on */
+extern Byte count_on; /* 0=count off/1=count on */
+
+extern Byte t_flag; /* Timer flag */
+
+extern Byte psw; /* Processor status word */
+extern Byte sp; /* Stack pointer (part of psw) */
+
+extern Byte p1; /* I/O port 1 */
+extern Byte p2; /* I/O port 2 */
+
+extern Byte xirq_pend;
+extern Byte tirq_pend;
+
+void init_cpu(void);
+void cpu_exec(void);
+void ext_IRQ(void);
+void tim_IRQ(void);
+void make_psw_debug(void);
+
+Byte acc; /* Accumulator */
+ADDRESS pc; /* Program counter */
+long clk; /* clock */
+
+Byte itimer; /* Internal timer */
+Byte reg_pnt; /* pointer to register bank */
+Byte timer_on; /* 0=timer off/1=timer on */
+Byte count_on; /* 0=count off/1=count on */
+Byte psw; /* Processor status word */
+Byte sp; /* Stack pointer (part of psw) */
+
+Byte p1; /* I/O port 1 */
+Byte p2; /* I/O port 2 */
+Byte xirq_pend; /* external IRQ pending */
+Byte tirq_pend; /* timer IRQ pending */
+Byte t_flag; /* Timer flag */
+
+ADDRESS lastpc;
+ADDRESS A11; /* PC bit 11 */
+ADDRESS A11ff;
+Byte bs; /* Register Bank (part of psw) */
+Byte f0; /* Flag Bit (part of psw) */
+Byte f1; /* Flag Bit 1 */
+Byte ac; /* Aux Carry (part of psw) */
+Byte cy; /* Carry flag (part of psw) */
+Byte xirq_en; /* external IRQ's enabled */
+Byte tirq_en; /* Timer IRQ enabled */
+Byte irq_ex; /* IRQ executing */
+
+int master_count;
+
+
+#endif /* CPU_H */
+
diff --git a/src/crc32.c b/src/crc32.c
new file mode 100755
index 0000000..0baebeb
--- /dev/null
+++ b/src/crc32.c
@@ -0,0 +1,110 @@
+
+/*
+ * O2EM Free Odyssey2 / Videopac+ Emulator
+ *
+ * Created by Daniel Boris (c) 1997,1998
+ *
+ * Developed by Andre de la Rocha
+ * Arlindo M. de Oliveira
+ *
+ * http://o2em.sourceforge.net
+ *
+ *
+ *
+ * CRC32 functions used to identify files
+ */
+
+
+#include
+#include
+#include "crc32.h"
+
+static unsigned long crc32tab[256] = {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
+ 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+ 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+ 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+ 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+ 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
+ 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
+ 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+ 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+ 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
+ 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
+ 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+ 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
+ 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+ 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+ 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
+ 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
+ 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+ 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+ 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
+ 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+ 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
+ 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
+ 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+ 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+ 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
+ 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+ 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+ 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
+ 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+ 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+ 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
+ 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
+ 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+ 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
+};
+
+unsigned long crc32_buf(const void *buf, long len){
+ unsigned /*long*/ crc = crc ^ 0xffffffffUL;//~0;
+ unsigned char *p = (unsigned char*)buf;
+
+ while (len--) crc = (crc >> 8) ^ crc32tab[(crc ^ (*p++)) & 0xff];
+ return ~crc;
+}
+
+
+unsigned long crc32_file(const char *filename){
+ unsigned /*long*/ crc = crc ^ 0xffffffffUL;//crc = ~0;
+ FILE *f;
+ int c;
+ f = fopen(filename,"rb");
+ if (f){
+ while ((c=fgetc(f)) != EOF) crc = (crc >> 8) ^ crc32tab[(crc ^ c) & 0xff];
+ fclose(f);
+
+ }
+ return ~crc;
+ }
+
diff --git a/src/crc32.h b/src/crc32.h
new file mode 100755
index 0000000..e00c9a2
--- /dev/null
+++ b/src/crc32.h
@@ -0,0 +1,7 @@
+#ifndef __CRC32_H
+#define __CRC32_H
+
+unsigned long crc32_buf(const void *buf, long len);
+unsigned long crc32_file(const char *filename);
+
+#endif
diff --git a/src/cset.c b/src/cset.c
new file mode 100755
index 0000000..bab86cf
--- /dev/null
+++ b/src/cset.c
@@ -0,0 +1,86 @@
+/*
+ * O2EM Free Odyssey2 / Videopac+ Emulator
+ *
+ * Created by Daniel Boris (c) 1997,1998
+ *
+ * Developed by Andre de la Rocha
+ * Arlindo M. de Oliveira
+ *
+ * http://o2em.sourceforge.net
+ *
+ *
+ *
+ * O2 character table
+ */
+
+
+#include "types.h"
+#include "cset.h"
+
+
+Byte cset[512]= {
+0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,
+0x18,0x38,0x18,0x18,0x18,0x18,0x3C,0x00,
+0x3C,0x66,0x0C,0x18,0x30,0x60,0x7E,0x00,
+0x7C,0xC6,0x06,0x3C,0x06,0xC6,0x7C,0x00,
+0xCC,0xCC,0xCC,0xFE,0x0C,0x0C,0x0C,0x00,
+0xFE,0xC0,0xC0,0x7C,0x06,0xC6,0x7C,0x00,
+0x7C,0xC6,0xC0,0xFC,0xC6,0xC6,0x7C,0x00,
+0xFE,0x06,0x0C,0x18,0x30,0x60,0xC0,0x00,
+0x7C,0xC6,0xC6,0x7C,0xC6,0xC6,0x7C,0x00,
+0x7C,0xC6,0xC6,0x7E,0x06,0xC6,0x7C,0x00,
+0x00,0x18,0x18,0x00,0x18,0x18,0x00,0x00,
+0x18,0x7E,0x58,0x7E,0x1A,0x7E,0x18,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x3C,0x66,0x0C,0x18,0x18,0x00,0x18,0x00,
+0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xFE,0x00,
+0xFC,0xC6,0xC6,0xFC,0xC0,0xC0,0xC0,0x00,
+0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,
+0xC6,0xC6,0xC6,0xD6,0xFE,0xEE,0xC6,0x00,
+0xFE,0xC0,0xC0,0xF8,0xC0,0xC0,0xFE,0x00,
+0xFC,0xC6,0xC6,0xFC,0xD8,0xCC,0xC6,0x00,
+0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x00,
+0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,
+0x3C,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,
+0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,
+0x7C,0xC6,0xC6,0xC6,0xDE,0xCC,0x76,0x00,
+0x7C,0xC6,0xC0,0x7C,0x06,0xC6,0x7C,0x00,
+0xFC,0xC6,0xC6,0xC6,0xC6,0xC6,0xFC,0x00,
+0xFE,0xC0,0xC0,0xF8,0xC0,0xC0,0xC0,0x00,
+0x7C,0xC6,0xC0,0xC0,0xCE,0xC6,0x7E,0x00,
+0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,
+0x06,0x06,0x06,0x06,0x06,0xC6,0x7C,0x00,
+0xC6,0xCC,0xD8,0xF0,0xD8,0xCC,0xC6,0x00,
+0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0x00,
+0x7E,0x06,0x0C,0x18,0x30,0x60,0x7E,0x00,
+0xC6,0xC6,0x6C,0x38,0x6C,0xC6,0xC6,0x00,
+0x7C,0xC6,0xC0,0xC0,0xC0,0xC6,0x7C,0x00,
+0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x00,
+0xFC,0xC6,0xC6,0xFC,0xC6,0xC6,0xFC,0x00,
+0xC6,0xEE,0xFE,0xD6,0xC6,0xC6,0xC6,0x00,
+0x00,0x00,0x00,0x00,0x00,0x38,0x38,0x00,
+0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,
+0x00,0x66,0x3C,0x18,0x3C,0x66,0x00,0x00,
+0x00,0x18,0x00,0x7E,0x00,0x18,0x00,0x00,
+0x00,0x00,0x7C,0x00,0x7C,0x00,0x00,0x00,
+0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x00,
+0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0x00,
+0x03,0x06,0x0C,0x18,0x30,0x60,0xC0,0x00,
+0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,
+0xCE,0xDB,0xDB,0xDB,0xDB,0xDB,0xCE,0x00,
+0x00,0x00,0x3C,0x7E,0x7E,0x7E,0x3C,0x00,
+0x1C,0x1C,0x18,0x1E,0x18,0x18,0x1C,0x00,
+0x1C,0x1C,0x18,0x1E,0x18,0x34,0x26,0x00,
+0x38,0x38,0x18,0x78,0x18,0x2C,0x64,0x00,
+0x38,0x38,0x18,0x78,0x18,0x18,0x38,0x00,
+0x00,0x18,0x0C,0xFE,0x0C,0x18,0x00,0x00,
+0x18,0x3C,0x7E,0xFF,0xFF,0x18,0x18,0x00,
+0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,0x00,
+0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF,0x00,
+0x38,0x38,0x12,0xFE,0xB8,0x28,0x6C,0x00,
+0xC0,0x60,0x30,0x18,0x0C,0x06,0x03,0x00,
+0x00,0x00,0x0C,0x08,0x08,0xFF,0x7E,0x00,
+0x00,0x03,0x63,0xFF,0xFF,0x18,0x08,0x00,
+0x00,0x00,0x00,0x10,0x38,0xFF,0x7E,0x00,
+0x00,0x00,0x00,0x06,0x6E,0xFF,0x7E,0x00};
+
diff --git a/src/cset.h b/src/cset.h
new file mode 100755
index 0000000..90ff411
--- /dev/null
+++ b/src/cset.h
@@ -0,0 +1,6 @@
+#ifndef __CSET_H
+#define __CSET_H
+
+extern Byte cset[512];
+
+#endif
diff --git a/src/debug.c b/src/debug.c
new file mode 100755
index 0000000..7d4cfd0
--- /dev/null
+++ b/src/debug.c
@@ -0,0 +1,1056 @@
+/*
+ * O2EM Free Odyssey2 / Videopac+ Emulator
+ *
+ * Created by Daniel Boris (c) 1997,1998
+ *
+ * Developed by Andre de la Rocha
+ * Arlindo M. de Oliveira
+ *
+ * http://o2em.sourceforge.net
+ *
+ *
+ *
+ * O2EM built-in debugger
+ */
+
+
+#include
+#include
+#include "cpu.h"
+#include "keyboard.h"
+#include "vmachine.h"
+#include "audio.h"
+#include "vdc.h"
+#include "table.h"
+#include "debug.h"
+
+#ifndef __LIBRETRO__
+#include "allegro.h"
+#else
+#include "wrapalleg.h"
+#include
+#endif
+
+#include "vpp.h"
+#include "score.h"
+
+#if defined(ALLEGRO_WINDOWS)
+#include "winalleg.h"
+#include
+#define KBHIT _kbhit
+#elif defined(ALLEGRO_DOS)
+#include
+#define KBHIT kbhit
+#else
+#define KBHIT() 0
+#endif
+
+static int assemble(char *opcode, int p);
+static int disasm(ADDRESS p);
+static int spriteprint(ADDRESS p);
+static void show_reg(void);
+int nMemDump;
+int nDisAsm;
+int nSprite;
+void decimal2binary(int decimal_value, char binary_value[32], short digits);
+
+
+void debug(void) {
+ int done,i,go,j;
+ char inp[80];
+ char *tok;
+ ADDRESS ad,run_to;
+ char cr[2],ff[2];
+ Byte d,a;
+
+ dbstick1=dbstick2=0;
+ cr[0]=13;
+ cr[1]=0;
+ ff[0]=0x0c;
+ ff[1]=0;
+
+ done=go=0;
+
+#ifndef __LIBRETRO__
+ set_display_switch_mode(SWITCH_BACKGROUND);
+#endif
+ if (sndlog) fclose(sndlog);
+
+ #ifdef ALLEGRO_WINDOWS
+ FreeConsole();
+ AllocConsole();
+ #endif
+
+ printf("\nDebug mode\n\n");
+
+ if (pc==app_data.breakpoint)
+ {
+ printf("Breakpoint reached at %x\n",pc);
+ }
+
+ nMemDump=pc;
+ nDisAsm=pc;
+ nSprite=0;
+ show_reg();
+
+ while (!done) {
+ while (go > 0) {
+ disasm(pc);
+ cpu_exec();
+ go--;
+ if (KBHIT()) {
+ go=0;
+ cpu_exec();
+ show_reg();
+ }
+ }
+ printf("> ");
+ fgets(inp,76,stdin);
+ if ((strlen(inp)>0) && (inp[strlen(inp)-1]=='\n')) inp[strlen(inp)-1]=0;
+ strlwr(inp);
+ strcat(inp," \n");
+ tok=strtok(inp," ");
+ if (!tok) tok="";
+ if (!strcmp(tok,"h") || !strcmp(tok,"?") || !strcmp(tok,"help")) {
+ printf("display - show display\n");
+ printf("viewsprite # - show memory # as sprite\n");
+// printf("editsprite # - edit memory # as sprite\n");
+ printf("showfps - display the number of frames per second\n");
+
+ #ifdef ALLEGRO_DOS
+ printf("cls - clear screen\n");
+ #endif
+
+ printf("clrkey - clear keypresses\n");
+ printf("setkey n - set key n pressed\n");
+ printf("stick1 # - set stick1 to #\n");
+ printf("stick2 # - set stick2 to #\n");
+
+ printf("reg - display registers\n");
+ printf("stack - display stack\n");
+ printf("col - display collision table\n");
+ printf("video (a d) - display VDC registers (or write data d to a)\n");
+ printf("extram (a d) - display external RAM (or write data d to a)\n");
+ printf("intram (a d) - display internal ram (or write data d to a)\n");
+
+ printf("s - step\n");
+ printf("so - step over\n");
+ printf("go # - execute # instructions\n");
+ printf("run # - run to address #\n");
+ printf("runvb - run to VBL\n");
+ printf("runnvb - run to no VBL\n");
+ printf("bp # - breakpoint at address #\n");
+ printf("bpc - clear breakpoint\n");
+ printf("reset - reset the machine\n");
+
+ printf("load file a - load file to memory to address\n");
+ printf("save file a n - save memory to file from address n Bytes\n");
+ printf("savedatah file a n - save memory to file from address a n Bytes format hex\n");
+ printf("savedatab file a n - save memory to file from address a n Bytes format binary\n");
+ printf("savevdc file a n - save VDC to file from address a n Bytes format hex\n");
+ printf("saveext file a n - save ExtRam to file from address a n Bytes format hex\n");
+ printf("savevpp file - save the VPP to file\n");
+
+ printf("as # - assemble memory #\n");
+ printf("di # - disassemble memory #\n");
+ printf("md # - display memory #\n");
+ printf("c # - change memory from location #\n");
+
+ printf("sndlog [file] - log raw sound to file\n");
+ printf("ss [file] - save state [to file]\n");
+ printf("ls [file] - load state [from file]\n");
+
+ printf("q - quit debugger and return to emulation\n");
+ printf("\n");
+ } else if (!strcmp(tok,"display")) {
+ grmode();
+ clip_low = 0;
+ clip_high = 85000;
+ draw_display();
+ finish_display();
+ init_keyboard();
+ do {
+ rest(1);
+ } while((key_done==0) && (!keypressed()));
+ set_textmode();
+#ifndef __LIBRETRO__
+ set_display_switch_mode(SWITCH_BACKGROUND);
+#endif
+ } else if (!strcmp(tok,"viewsprite")) {
+ if (tok){
+ tok=strtok(NULL," ");
+ ad=65535;
+ sscanf(tok,"%hx",&ad);
+ if (ad==65535) ad=nSprite;
+
+ for(i=0; i<8; i++)
+ {
+ if (ad<32768) ad = ad + spriteprint(ad); else ad=0;
+ }
+ nSprite=ad;
+ printf("\n");
+ }
+//TODO !!!! ----------------------------------------------------------------------------------------------------
+ } else if (!strcmp(tok,"editsprite")) {
+ if (tok){
+ tok=strtok(NULL," ");
+ ad=65535;
+ sscanf(tok,"%hx",&ad);
+ if (ad!=65535)
+ {
+ for(i=0; i<8; i++)
+ {
+ if (ad<32768) ad = ad + spriteprint(ad); else ad=0;
+ }
+ printf("\n");
+ }
+ }
+//----------------------------------------------------------------------------------------------------
+ } else if (!strcmp(tok,"cls")) {
+ #ifdef ALLEGRO_DOS
+ clrscr();
+ #endif
+ } else if (!strcmp(tok,"clrkey")) {
+ for(i=0; i<128; i++) key2[i]=0;
+ } else if (!strcmp(tok,"setkey")) {
+ tok=strtok(NULL," ");
+ if (tok){
+ sscanf(tok,"%d",&i);
+ if ((i>0) && (i<128)){
+ printf("Key %d set to pressed\n",i);
+ key2[i]=1;
+ }
+ key2vcnt=0;
+ }
+ } else if (!strcmp(tok,"stick1")) {
+ tok=strtok(NULL," ");
+ if (tok) {
+ i=0;
+ sscanf(tok,"%x",&i);
+ printf("Stick 1 set to %d\n",i);
+ dbstick1=i;
+ key2vcnt=0;
+ }
+ } else if (!strcmp(tok,"stick2")) {
+ tok=strtok(NULL," ");
+ if (tok) {
+ i=0;
+ sscanf(tok,"%x",&i);
+ printf("Stick 2 set to %d\n",i);
+ dbstick2=i;
+ key2vcnt=0;
+ }
+ } else if (!strcmp(tok,"s")) {
+ cpu_exec();
+ show_reg();
+ } else if (!strcmp(tok,"so")) {
+ run_to = pc+lookup[rom[pc]].bytes;
+ printf("%hx\n",run_to);
+ while (pc != run_to) {
+ cpu_exec();
+ if (KBHIT()) break;
+ }
+ show_reg();
+ } else if (!strcmp(tok,"reset")) {
+ init_cpu();
+ init_roms();
+ init_vpp();
+ } else if (!strcmp(tok,"reg")) {
+ show_reg();
+ } else if (!strcmp(tok,"stack")) {
+ for(i=8; i<24; i+=2) {
+ ad = intRAM[i];
+ d = intRAM[i+1];
+ ad = ad | ((d & 0x0F) << 8);
+ printf("%x: PC=%x PSW=%x",i,ad,d);
+ if (i == sp) printf(" <0)
+ {
+ tok=strtok(NULL," ");
+ if (tok)
+ {
+ sscanf(tok,"%x",&adr);
+ tok=strtok(NULL," ");
+ if (tok)
+ {
+ sscanf(tok,"%i",&t);
+ fn = fopen(file,"wb");
+ if (fn==NULL) {
+ fprintf(stderr,"Error opening save-file %s: %i\n",file,errno);
+ }
+ else
+ {
+ fwrite ((rom+adr),t,1,fn);
+ fclose(fn);
+ printf("File %s saved: %i bytes from address:%x\n",file,t,adr);
+ }
+ }
+ }
+
+ }
+ }
+ } else if (!strcmp(tok,"savedatah"))
+ {
+ int t;
+ int adr;
+ FILE *fn;
+ tok=strtok(NULL," ");
+ if (tok){
+ char file[80]="";
+ sscanf(tok,"%79s",file);
+ if (strlen(file)>0)
+ {
+ tok=strtok(NULL," ");
+ if (tok)
+ {
+ sscanf(tok,"%x",&adr);
+ tok=strtok(NULL," ");
+ if (tok)
+ {
+ sscanf(tok,"%i",&t);
+ fn = fopen(file,"wt");
+ if (fn==NULL) {
+ fprintf(stderr,"Error opening save-data file %s: %i\n",file,errno);
+ }
+ else
+ {
+ // write format "db 0XXh[,0XXh]" 8 Zeichen pro Zeile
+ int j=0;
+ for (i=0; i<((int) ((t-1)/8))+1; i++)
+ {
+ fprintf(fn,"db ");
+ for (j=0;j<8 && i*8+j0)
+ {
+ tok=strtok(NULL," ");
+ if (tok)
+ {
+ sscanf(tok,"%x",&adr);
+ tok=strtok(NULL," ");
+ if (tok)
+ {
+ sscanf(tok,"%i",&t);
+ fn = fopen(file,"wt");
+ if (fn==NULL) {
+ fprintf(stderr,"Error opening save-data file %s: %i\n",file,errno);
+ }
+ else
+ {
+ // write format "db 0XXh[,0XXh]" 8 Zeichen pro Zeile
+ int j=0;
+ for (i=0; i<((int) ((t-1)/8))+1; i++)
+ {
+ fprintf(fn,"db ");
+ for (j=0;j<8 && i*8+j0)
+ {
+ tok=strtok(NULL," ");
+ if (tok)
+ {
+ sscanf(tok,"%x",&adr);
+ tok=strtok(NULL," ");
+ if (tok)
+ {
+ sscanf(tok,"%i",&t);
+ fn = fopen(file,"wt");
+ if (fn==NULL) {
+ fprintf(stderr,"Error opening save-data file %s: %i\n",file,errno);
+ }
+ else
+ {
+ // write format "db 0XXh[,0XXh]" 8 Zeichen pro Zeile
+ int j=0;
+ for (i=0; i<((int) ((t-1)/8))+1; i++)
+ {
+ fprintf(fn,"db ");
+ for (j=0;j<8 && i*8+j0)
+ {
+ tok=strtok(NULL," ");
+ if (tok)
+ {
+ sscanf(tok,"%x",&adr);
+ tok=strtok(NULL," ");
+ if (tok)
+ {
+ sscanf(tok,"%i",&t);
+ fn = fopen(file,"wt");
+ if (fn==NULL) {
+ fprintf(stderr,"Error opening save-data file %s: %i\n",file,errno);
+ }
+ else
+ {
+ char binary_value[32];
+ // write format "db xxxxxxxxb" 1 Zeichen pro Zeile
+ for (i=0; i0) {
+ fn = fopen(file,"wt");
+ if (fn==NULL) {
+ fprintf(stderr,"Error opening vpp data file %s: %i\n",file,errno);
+ } else {
+ /* write char/attribute data */
+ for(i = 0; i < 25; i++) {
+ /* service row is 24 in file, 31 in memory */
+ if (i == 24) i = 31;
+ for(j = 0; j < 40; j++) {
+ if (fwrite(&vpp_mem[j][i][0], 1, 1, fn) != 1) {
+ fprintf(stderr,"Error writing vpp data file %s: %i\n",file,errno);
+ break;
+ }
+ if (fwrite(&vpp_mem[j][i][1], 1, 1, fn) != 1) {
+ fprintf(stderr,"Error writing vpp data file %s: %i\n",file,errno);
+ break;
+ }
+ }
+ /* mirror slice bits */
+ for(i = 0; i < 2; i++) for(j = 0; j < 960; j++) {
+ mchars[i][j] = ((dchars[i][j] & 0x80) >> 7) | ((dchars[i][j] & 0x40) >> 5) | ((dchars[i][j] & 0x20) >> 3) | ((dchars[i][j] & 0x10) >> 1) | ((dchars[i][j] & 0x08) << 1) | ((dchars[i][j] & 0x04) << 3) | ((dchars[i][j] & 0x02) << 5) | ((dchars[i][j] & 0x01) << 7);
+ }
+ /* write slice data */
+ if (fwrite(mchars, 960, 2, fn) != 2) {
+ fprintf(stderr,"Error Writing vpp data file %s: %i\n",file,errno);
+ break;
+ }
+ fclose(fn);
+ }
+
+ }
+ }
+ }
+ } else if (!strcmp(tok,"load"))
+ {
+ int adr;
+ FILE *fn;
+ tok=strtok(NULL," ");
+ if (tok){
+ char file[80]="";
+ sscanf(tok,"%79s",file);
+ if (strlen(file)>0)
+ {
+ tok=strtok(NULL," ");
+ if (tok)
+ {
+ sscanf(tok,"%x",&adr);
+ fn = fopen(file,"rb");
+ if (fn==NULL) {
+ fprintf(stderr,"Error opening load-file %s: %i\n",file,errno);
+ }
+ else
+ {
+ int length;
+ fseek(fn,0L,SEEK_END);
+ length = ftell(fn);
+ rewind(fn);
+ fread ((rom+adr),length,1,fn);
+ fclose(fn);
+ printf("File %s loaded to address:%x (%i bytes)\n",file,adr,length);
+ }
+ }
+
+ }
+ }
+ } else if (!strcmp(tok,"keys")) {
+ j=0;
+ printf("%02x:",0);
+ for(i=0; i<128; i++) {
+ printf("%02x,",key2[i]);
+ j++;
+ if (j == 16) {
+ printf("\n");
+ printf("%02x:",i+1);
+
+ j=0;
+ }
+ }
+ printf("\n");
+ } else if (!strcmp(tok,"col")) {
+ j=0;
+ printf("%02x:",0);
+ for(i=0; i<256; i++) {
+ printf("%02x,",coltab[i]);
+ j++;
+ if (j == 16) {
+ printf("\n");
+ printf("%02x:",i+1);
+ j=0;
+ }
+ }
+ printf("\n");
+ printf("Colreg: %x\n ",ext_read(0xA2));
+ } else if (!strcmp(tok,"extram")) {
+ int t;
+ tok=strtok(NULL," ");
+ if (tok){
+ sscanf(tok,"%x",&t);
+ a = (Byte)t;
+ tok=strtok(NULL," ");
+ if (tok){
+ sscanf(tok,"%x",&t);
+ d = (Byte)t;
+ extRAM[a] = d;
+ }
+ else
+ {
+ j=0;
+ printf("%02x:",0);
+ for(i=0; i<256; i++) {
+ printf("%02x",extRAM[i]);
+ if (j < 15) printf(",");
+ j++;
+ if (j == 16 && i !=255) {
+ printf("\n");
+ printf("%02x:",i+1);
+
+ j=0;
+ }
+ }
+}
+}
+ printf("\n\n");
+ } else if (!strcmp(tok,"intram")) {
+ int t;
+ tok=strtok(NULL," ");
+ if (tok){
+ sscanf(tok,"%x",&t);
+ a = (Byte)t;
+ tok=strtok(NULL," ");
+ if (tok)
+ {
+ sscanf(tok,"%x",&t);
+ d = (Byte)t;
+ intRAM[a] = d;
+ }
+ else
+ {
+ j=0;
+ printf("%02x:",0);
+ for(i=0; i<64; i++) {
+ printf("%02x",intRAM[i]);
+ if (j < 15) printf(",");
+ j++;
+ if (j == 16 && i != 63) {
+ printf("\n");
+ printf("%02x:",i+1);
+ j=0;
+ }
+ }
+ printf("\n\n");
+ }
+ }
+ } else if (!strcmp(tok,"run")) {
+ tok=strtok(NULL," ");
+ if (tok){
+ sscanf(tok,"%hx",&run_to);
+ printf("Run to %x\n",run_to);
+ while (pc != run_to) {
+ cpu_exec();
+ if (KBHIT()) break;
+ }
+ show_reg();
+ }
+ } else if (!strcmp(tok,"bp")) {
+ int bp;
+ tok=strtok(NULL," ");
+ bp=65535;
+ sscanf(tok,"%x",&bp);
+ if (bp==65535)
+ {
+ if (app_data.breakpoint==65535)
+ printf("No Breakpoint set.\n");
+ else printf("Breakpoint at %x\n",app_data.breakpoint);
+ }
+ else
+ {
+ sscanf(tok,"%x",&bp);
+ app_data.breakpoint = bp;
+ printf("Breakpoint set to %x\n",app_data.breakpoint);
+ }
+ } else if (!strcmp(tok,"bpc")) {
+ if (app_data.breakpoint==65535)
+ printf("No Breakpoint set.\n");
+ else
+ {
+ app_data.breakpoint = 65535;
+ printf("Breakpoint cleared.\n");
+ }
+ } else if (!strcmp(tok,"runvb")) {
+ printf("Run to VBL\n");
+ while (master_clk < 5500) {
+ cpu_exec();
+ if (KBHIT()) break;
+ }
+ show_reg();
+ } else if (!strcmp(tok,"runnvb")) {
+ printf("Run to no VBL\n");
+ while (master_clk > 5500) {
+ cpu_exec();
+ if (KBHIT()) break;
+ }
+ show_reg();
+ } else if (!strcmp(tok,"go")) {
+ tok=strtok(NULL," ");
+ if (tok) sscanf(tok,"%d",&go);
+ } else if (!strcmp(tok,"di")) {
+ if (tok){
+ tok=strtok(NULL," ");
+ ad=65535;
+ sscanf(tok,"%hx",&ad);
+ if (ad==65535) ad=nDisAsm;
+
+ for(i=0; i<20; i++)
+ {
+ if (ad<32768) ad = ad + disasm(ad); else ad=0;
+ }
+ nDisAsm=ad;
+ printf("\n");
+ }
+ } else if (!strcmp(tok,"md")) {
+ tok=strtok(NULL," ");
+ if (tok){
+ ad=65535;
+ sscanf(tok,"%hx",&ad);
+ if (ad==65535) ad=nMemDump;
+ printf("\n");
+
+ for (j=0; j<10; j++){
+ if (ad+j*16<32768) {
+ printf("%04x : ",ad+j*16);
+ for (i=0; i<16; i++) printf("%02x ",rom[ad+j*16+i]);
+ printf("\n");
+ }
+ else
+ {
+ ad = 0;
+ }
+ }
+ nMemDump = ad+10*16;
+ printf("\n\n");
+ }
+ } else if (!strcmp(tok,"sndlog")) {
+ if (app_data.sound_en) {
+ tok=strtok(NULL," ");
+ if (tok){
+ char file[80]="";
+ sscanf(tok,"%79s",file);
+ if (strlen(file)>0){
+ sndlog = fopen(file,"wb");
+ if (sndlog)
+ printf("Sound log file created\n");
+ else
+ printf("Sound log file creation failed\n");
+ }
+ }
+ printf("\n");
+ } else printf("Sound emulation disabled\n\n");
+
+ } else if (!strcmp(tok,"ss")) {
+ tok=strtok(NULL," ");
+ if (tok){
+ char file[80]="";
+ sscanf(tok,"%79s",file);
+ if (strlen(file)>0){
+ savestate(file);
+ }
+ }
+ printf("\n");
+
+ } else if (!strcmp(tok,"ls")) {
+ tok=strtok(NULL," ");
+ if (tok){
+ char file[80]="";
+ sscanf(tok,"%79s",file);
+ if (strlen(file)>0){
+ loadstate(file);
+ }
+ }
+ printf("\n");
+
+ } else if (!strcmp(tok,"showfps")) {
+ show_fps=1;
+
+ } else if (!strcmp(tok,"c"))
+ {
+ int t;
+ tok=strtok(NULL," ");
+ if (tok)
+ {
+ sscanf(tok,"%hx",&ad);
+ printf("Addr Old New (enter to exit)\n"); // Header
+
+ do
+ {
+ printf("%.4X %.2X ?",ad,rom[ad]); // Memory Position, Old Value
+
+ fgets(inp,80,stdin);
+ if (inp[0]!=10)
+ {
+ t=65535;
+ sscanf(inp,"%x",&t);
+ if (t<256)
+ {
+ d = (Byte) t;
+ rom[ad]=d;
+ ad=(ad==32768)?0:ad+1;
+ }
+ else
+ {
+ printf("wrong value, try again\n");
+ }
+ }
+ }
+ while (inp[0]!=10);
+ }
+ printf("\n");
+
+ } else if (!strcmp(tok,"as")) {
+ tok=strtok(NULL," ");
+ if (tok)
+ {
+ sscanf(tok,"%hx",&ad);
+
+ printf("Addr Instruction (enter to exit)\n"); // Header
+ do
+ {
+ printf("%.4X ",ad); // Memory Position
+ fgets(inp,80,stdin);
+
+ if (inp[0]!=10)
+ {
+ ad = ad + assemble(inp,ad);
+ }
+ }
+ while (inp[0]!=10);
+ }
+ printf("\n");
+
+
+ } else if ((strlen(tok)>0) && (strcmp(tok,"\n"))) {
+ printf("Unknown command\n\n");
+ }
+
+ }
+
+ #ifdef ALLEGRO_WINDOWS
+ FreeConsole();
+ #endif
+
+}
+
+
+static void show_reg(void) {
+ int i;
+
+ make_psw_debug();
+ printf("PC=%.3X A=%.2X PSW=%.2X P1=%.2X P2=%.2X",pc,acc,psw,p1,p2);
+ printf(" clk: %d reg:%d count:%x f:%x\n",master_clk,reg_pnt,itimer,frame);
+ disasm(pc);
+ printf("\n");
+
+ printf("R%d: %02x R%d': %02x PSW: ",0,intRAM[0],0,intRAM[24]);
+ printf("%sC %sAC %sF0 %sF1 SP:%.2X\n",psw&0x80?"":"!",psw&0x40?"":"!",psw&0x20?"":"!",psw&0x10?"":"!",psw&0x07);
+
+ printf("R%d: %02x R%d': %02x P1: ",1,intRAM[1],1,intRAM[25]);
+ printf("%sLum %sCopy %sVP+ %sExtRam %sVDC %sKeyB Bank:%i\n",p1&0x80?"":"!",p1&0x40?"":"!",p1&0x20?"":"!",p1&0x10?"":"!",p1&0x08?"":"!",p1&0x04?"":"!",p1&0x03);
+
+ printf("R%d: %02x R%d': %02x ",2,intRAM[2],2,intRAM[26]);
+ printf("MB%i RB%i\n",A11ff>>11,reg_pnt>4);
+
+ for (i=3; i<8; i++) {
+ printf("R%d: %02x R%d': %02x\n",i,intRAM[i],i,intRAM[i+24]);
+ }
+}
+
+
+static int disasm(ADDRESS p) {
+ Byte op,d;
+ ADDRESS adr;
+
+ op=rom[p++];
+ printf("%04x %02x",p-1,op);
+ if (lookup[op].bytes == 2) printf(" %02x",rom[p]); else printf(" ");
+ printf(" %s",lookup[op].mnemonic);
+ switch(lookup[op].type) {
+ case 0:
+ printf("\n");
+ break;
+ case 1:
+ d=rom[p];
+ printf(" #%02x\n",d);
+ break;
+ case 2:
+ adr=rom[p];
+ adr = adr | ((op & 0xE0) << 3);
+ printf(" $%03x\n",adr);
+ break;
+ case 3:
+ printf(" $%02x\n",rom[p]);
+ break;
+ }
+ return lookup[op].bytes;
+}
+
+static int assemble(char *opcode, int p)
+{
+ char *str_value;
+ int op=0;
+ int value;
+ int t;
+
+ while((op<256)&&(strncasecmp(opcode,lookup[op].mnemonic,strlen(lookup[op].mnemonic))!=0)) op++;
+
+ if (op==256)
+ {
+ printf("Wrong opcode, please try again.\n");
+ return(0);
+ }
+
+ str_value = opcode+strlen(lookup[op].mnemonic);
+ while (str_value[0]==' ') str_value++;
+
+ switch(lookup[op].type)
+ {
+ case 0: // no other value needed
+ rom[p]=op;
+ break;
+ case 1: // #value needed
+ if (str_value[0]!='#')
+ {
+ printf("Error: #xx expected\n");
+ return(0);
+ }
+ t=65335;
+ sscanf(str_value+1,"%2x",&t);
+ if (t>=256)
+ {
+ printf("Error: #xx expected (value #00-#FF)\n");
+ return(0);
+ }
+ else value = (Byte) t;
+ rom[p]=op;
+ rom[p+1]=value;
+ break;
+ case 2: // $addresss needed (max. 7FF)
+ if (str_value[0]!='$')
+ {
+ printf("Error: $xxx expected %s\n",str_value);
+ return(0);
+ }
+ t=65335;
+ sscanf(str_value+1,"%x",&t);
+ if (t>=2048)
+ {
+ printf("Error: $xxx expected (value below $800)\n");
+ return(0);
+ }
+ else value = (Byte) t;
+ rom[p]=op | ((t&1792)>>3);
+ rom[p+1]=value;
+ break;
+
+ case 3: // $address needed (max. FF)
+ if (str_value[0]!='$')
+ {
+ printf("Error: $xx expected\n");
+ return(0);
+ }
+ t=65335;
+ sscanf(str_value+1,"%x",&t);
+ if (t>=256)
+ {
+ printf("Error: $xx expected (value $00-$FF)\n");
+ return(0);
+ }
+ else value = (Byte) t;
+ rom[p]=op;
+ rom[p+1]=value;
+ break;
+
+ }
+ return lookup[op].bytes;
+}
+
+void decimal2binary(int decimal_value, char binary_value[32], short digits)
+{
+ short i;
+ for(i=digits;i>=0;i--)
+ {
+ binary_value[i]=(char)('0'+(int) (decimal_value/(1<=0;i--)
+ {
+ if (binary_value[i]=='0') printf(" ");
+ else printf("%c",178);
+ }
+
+ printf("\n");
+ return 1;
+}
diff --git a/src/debug.h b/src/debug.h
new file mode 100755
index 0000000..00bad38
--- /dev/null
+++ b/src/debug.h
@@ -0,0 +1,14 @@
+#ifndef DEBUG_H
+#define DEBUG_H
+
+void debug(void);
+
+#endif /* DEBUG_H */
+
+
+
+
+
+
+
+
diff --git a/src/dis48.c b/src/dis48.c
new file mode 100755
index 0000000..b08e530
--- /dev/null
+++ b/src/dis48.c
@@ -0,0 +1,151 @@
+
+/*
+ * O2/8048 disassembler
+ */
+
+
+#include
+#include
+#include
+#include
+#include "types.h"
+#include "table.h"
+#include "debug.h"
+
+#define BIOSLEN 1024
+#define MAXLEN 8192
+
+
+Byte rom[MAXLEN+BIOSLEN];
+ADDRESS pc;
+
+int parse_option(char *attr, char *val);
+
+static int disasm(ADDRESS p) {
+ Byte op,d;
+ ADDRESS adr;
+
+ op=rom[p++];
+ printf("%04x %02x",p-1,op);
+ if (lookup[op].bytes == 2) printf(" %02x",rom[p]); else printf(" ");
+ printf(" %s",lookup[op].mnemonic);
+ switch(lookup[op].type) {
+ case 0:
+ printf("\n");
+ break;
+ case 1:
+ d=rom[p];
+ printf(" #%02x\n",d);
+ break;
+ case 2:
+ adr=rom[p];
+ adr = adr | ((op & 0xE0) << 3);
+ printf(" $%03x\n",adr);
+ break;
+ case 3:
+ printf(" $%02x\n",rom[p]);
+ break;
+ }
+ if (op == 0x83 || op == 0x93 || (((p-2+lookup[op].bytes) & 0xff) == 0xff)) printf("\n"); // Linebreak after ret, retr and end of page
+ return lookup[op].bytes;
+}
+
+
+int main(int argc, char **argv){
+ int n;
+ int i,j;
+ int start;
+ long len;
+ FILE *fn;
+ static char file[MAXC], attr[MAXC], val[MAXC], *p;
+ pc = BIOSLEN;
+ if (argc<2) {
+ printf("Usage: dis48 [file] [-bios]\n");
+ exit(0);
+ }
+
+ /* load image */
+
+ for(i=1; iMAXLEN) {
+ printf("Invalid image size");
+ fclose(fn);
+ exit(0);
+ }
+
+ rewind(fn);
+ if (fread(&rom[pc],1,len,fn) != (size_t)len) {
+ printf("Error loading %s\n",argv[1]);
+ fclose(fn);
+ exit(0);
+ }
+ fclose(fn);
+
+ start = pc;
+ while (pc < start+len) {
+ n = disasm(pc);
+ pc = pc + n;
+ }
+ exit(0);
+}
+
+int parse_option(char *attr, char *val){
+
+ if (!strcmp(attr,"bios"))
+ {
+ pc = 0;
+ }
+ else
+ {
+ fprintf(stderr,"Invalid option : %s\n",attr);
+ return 0;
+ }
+ return 1;
+}
+
+
+
diff --git a/src/keyboard.c b/src/keyboard.c
new file mode 100755
index 0000000..fc4a50e
--- /dev/null
+++ b/src/keyboard.c
@@ -0,0 +1,583 @@
+
+/*
+ * O2EM Free Odyssey2 / Videopac+ Emulator
+ *
+ * Created by Daniel Boris (c) 1997,1998
+ *
+ * Developed by Andre de la Rocha
+ * Arlindo M. de Oliveira
+ *
+ * http://o2em.sourceforge.net
+ *
+ *
+ *
+ * Keyboard emulation
+ */
+
+
+#include
+#include
+#include
+#include "types.h"
+#include "cpu.h"
+#include "config.h"
+#include "vmachine.h"
+#include "vdc.h"
+#include "audio.h"
+#include "voice.h"
+#include "vpp.h"
+#include "keyboard.h"
+
+#ifndef __LIBRETRO__
+#include "allegro.h"
+#else
+#include "libretro.h"
+#include "wrapalleg.h"
+#endif
+
+#include "score.h"
+
+int NeedsPoll = 0;
+
+Byte keycode;
+Byte last_key;
+Byte new_int=0; /* Is new interrupt installed */
+
+Byte key_done=0;
+Byte key_debug=0;
+#ifndef __LIBRETRO__
+
+struct keyb keybtab[] = {
+ {KEY_A,"A"},
+ {KEY_B,"B"},
+ {KEY_C,"C"},
+ {KEY_D,"D"},
+ {KEY_E,"E"},
+ {KEY_F,"F"},
+ {KEY_G,"G"},
+ {KEY_H,"H"},
+ {KEY_I,"I"},
+ {KEY_J,"J"},
+ {KEY_K,"K"},
+ {KEY_L,"L"},
+ {KEY_M,"M"},
+ {KEY_N,"N"},
+ {KEY_O,"O"},
+ {KEY_P,"P"},
+ {KEY_Q,"Q"},
+ {KEY_R,"R"},
+ {KEY_S,"S"},
+ {KEY_T,"T"},
+ {KEY_U,"U"},
+ {KEY_V,"V"},
+ {KEY_W,"W"},
+ {KEY_X,"X"},
+ {KEY_Y,"Y"},
+ {KEY_Z,"Z"},
+ {KEY_0,"0"},
+ {KEY_1,"1"},
+ {KEY_2,"2"},
+ {KEY_3,"3"},
+ {KEY_4,"4"},
+ {KEY_5,"5"},
+ {KEY_6,"6"},
+ {KEY_7,"7"},
+ {KEY_8,"8"},
+ {KEY_9,"9"},
+ {KEY_0_PAD,"0_PAD"},
+ {KEY_1_PAD,"1_PAD"},
+ {KEY_2_PAD,"2_PAD"},
+ {KEY_3_PAD,"3_PAD"},
+ {KEY_4_PAD,"4_PAD"},
+ {KEY_5_PAD,"5_PAD"},
+ {KEY_6_PAD,"6_PAD"},
+ {KEY_7_PAD,"7_PAD"},
+ {KEY_8_PAD,"8_PAD"},
+ {KEY_9_PAD,"9_PAD"},
+ {KEY_TILDE,"TILDE"},
+ {KEY_MINUS,"MINUS"},
+ {KEY_EQUALS,"EQUALS"},
+ {KEY_BACKSPACE,"BACKSPACE"},
+ {KEY_TAB,"TAB"},
+ {KEY_OPENBRACE,"OPENBRACE"},
+ {KEY_CLOSEBRACE,"CLOSEBRACE"},
+ {KEY_ENTER,"ENTER"},
+ {KEY_COLON,"COLON"},
+ {KEY_QUOTE,"QUOTE"},
+ {KEY_BACKSLASH,"BACKSLASH"},
+ {KEY_BACKSLASH2,"BACKSLASH2"},
+ {KEY_COMMA,"COMMA"},
+ {KEY_STOP,"STOP"},
+ {KEY_SLASH,"SLASH"},
+ {KEY_SPACE,"SPACE"},
+ {KEY_INSERT,"INSERT"},
+ {KEY_DEL,"DEL"},
+ {KEY_HOME,"HOME"},
+ {KEY_END,"END"},
+ {KEY_PGUP,"PGUP"},
+ {KEY_PGDN,"PGDN"},
+ {KEY_LEFT,"LEFT"},
+ {KEY_RIGHT,"RIGHT"},
+ {KEY_UP,"UP"},
+ {KEY_DOWN,"DOWN"},
+ {KEY_SLASH_PAD,"SLASH_PAD"},
+ {KEY_ASTERISK,"ASTERISK"},
+ {KEY_MINUS_PAD,"MINUS_PAD"},
+ {KEY_PLUS_PAD,"PLUS_PAD"},
+ {KEY_DEL_PAD,"DEL_PAD"},
+ {KEY_ENTER_PAD,"ENTER_PAD"},
+ {KEY_PRTSCR,"PRTSCR"},
+ {KEY_PAUSE,"PAUSE"},
+ {KEY_ABNT_C1,"ABNT_C1"},
+ {KEY_YEN,"YEN"},
+ {KEY_KANA,"KANA"},
+ {KEY_AT,"AT"},
+ {KEY_CIRCUMFLEX,"CIRCUMFLEX"},
+ {KEY_COLON2,"COLON2"},
+ {KEY_KANJI,"KANJI"},
+ {KEY_LSHIFT,"LSHIFT"},
+ {KEY_RSHIFT,"RSHIFT"},
+ {KEY_LCONTROL,"LCONTROL"},
+ {KEY_RCONTROL,"RCONTROL"},
+ {KEY_ALT,"ALT"},
+ {KEY_ALTGR,"ALTGR"},
+ {KEY_LWIN,"LWIN"},
+ {KEY_RWIN,"RWIN"},
+ {KEY_MENU,"MENU"},
+ {KEY_SCRLOCK,"SCRLOCK"},
+ {KEY_NUMLOCK,"NUMLOCK"},
+ {KEY_F1,"F1"},
+ {KEY_F2,"F2"},
+ {KEY_F3,"F3"},
+ {KEY_F4,"F4"},
+ {KEY_F5,"F5"},
+ {KEY_F6,"F6"},
+ {KEY_F7,"F7"},
+ {KEY_F8,"F8"},
+ {KEY_F9,"F9"},
+ {KEY_F10,"F10"},
+ {KEY_F11,"F11"},
+ {KEY_F12,"F12"},
+ {KEY_ESC,"ESC"},
+ {0,""}
+};
+#else
+#define RETROK_TILDE 178
+
+struct keyb keybtab[] = {
+ {RETROK_a,"A"},
+ {RETROK_b,"B"},
+ {RETROK_c,"C"},
+ {RETROK_d,"D"},
+ {RETROK_e,"E"},
+ {RETROK_f,"F"},
+ {RETROK_g,"G"},
+ {RETROK_h,"H"},
+ {RETROK_i,"I"},
+ {RETROK_j,"J"},
+ {RETROK_k,"K"},
+ {RETROK_l,"L"},
+ {RETROK_m,"M"},
+ {RETROK_n,"N"},
+ {RETROK_o,"O"},
+ {RETROK_p,"P"},
+ {RETROK_q,"Q"},
+ {RETROK_r,"R"},
+ {RETROK_s,"S"},
+ {RETROK_t,"T"},
+ {RETROK_u,"U"},
+ {RETROK_v,"V"},
+ {RETROK_w,"W"},
+ {RETROK_x,"X"},
+ {RETROK_y,"Y"},
+ {RETROK_z,"Z"},
+ {RETROK_0,"0"},
+ {RETROK_1,"1"},
+ {RETROK_2,"2"},
+ {RETROK_3,"3"},
+ {RETROK_4,"4"},
+ {RETROK_5,"5"},
+ {RETROK_6,"6"},
+ {RETROK_7,"7"},
+ {RETROK_8,"8"},
+ {RETROK_9,"9"},
+ {RETROK_KP0,"0_PAD"},
+ {RETROK_KP1,"1_PAD"},
+ {RETROK_KP2,"2_PAD"},
+ {RETROK_KP3,"3_PAD"},
+ {RETROK_KP4,"4_PAD"},
+ {RETROK_KP5,"5_PAD"},
+ {RETROK_KP6,"6_PAD"},
+ {RETROK_KP7,"7_PAD"},
+ {RETROK_KP8,"8_PAD"},
+ {RETROK_KP9,"9_PAD"},
+ {RETROK_TILDE,"TILDE"},
+ {RETROK_MINUS,"MINUS"},
+ {RETROK_EQUALS,"EQUALS"},
+ {RETROK_BACKSPACE,"BACKSPACE"},
+ {RETROK_TAB,"TAB"},
+ {RETROK_LEFTBRACKET,"OPENBRACE"},
+ {RETROK_RIGHTBRACKET,"CLOSEBRACE"},
+ {RETROK_RETURN,"ENTER"},
+ {RETROK_COLON,"COLON"},
+ {RETROK_QUOTE,"QUOTE"},
+ {RETROK_BACKSLASH,"BACKSLASH"},
+// {RETROK_BACKSLASH2,"BACKSLASH2"},
+ {RETROK_COMMA,"COMMA"},
+// {RETROK_STOP,"STOP"},
+ {RETROK_SLASH,"SLASH"},
+ {RETROK_SPACE,"SPACE"},
+ {RETROK_INSERT,"INSERT"},
+ {RETROK_DELETE,"DEL"},
+ {RETROK_HOME,"HOME"},
+ {RETROK_END,"END"},
+ {RETROK_PAGEUP,"PGUP"},
+ {RETROK_PAGEDOWN,"PGDN"},
+ {RETROK_LEFT,"LEFT"},
+ {RETROK_RIGHT,"RIGHT"},
+ {RETROK_UP,"UP"},
+ {RETROK_DOWN,"DOWN"},
+ {RETROK_KP_DIVIDE,"SLASH_PAD"},
+ {RETROK_KP_MULTIPLY,"ASTERISK"},
+ {RETROK_KP_MINUS,"MINUS_PAD"},
+ {RETROK_KP_PLUS,"PLUS_PAD"},
+ {RETROK_KP_PERIOD,"DEL_PAD"},
+ {RETROK_KP_ENTER,"ENTER_PAD"},
+ {RETROK_PRINT,"PRTSCR"},
+ {RETROK_PAUSE,"PAUSE"},
+// {RETROK_ABNT_C1,"ABNT_C1"},
+// {RETROK_YEN,"YEN"},
+// {RETROK_KANA,"KANA"},
+ {RETROK_AT,"AT"},
+ {RETROK_CARET,"CIRCUMFLEX"},
+// {RETROK_COLON2,"COLON2"},
+// {RETROK_KANJI,"KANJI"},
+ {RETROK_LSHIFT,"LSHIFT"},
+ {RETROK_RSHIFT,"RSHIFT"},
+ {RETROK_LCTRL,"LCONTROL"},
+ {RETROK_RCTRL,"RCONTROL"},
+ {RETROK_LALT,"ALT"},
+ {RETROK_RALT,"ALTGR"},
+ {RETROK_LMETA,"LWIN"},
+ {RETROK_RMETA,"RWIN"},
+ {RETROK_MENU,"MENU"},
+ {RETROK_SCROLLOCK,"SCRLOCK"},
+ {RETROK_NUMLOCK,"NUMLOCK"},
+ {RETROK_F1,"F1"},
+ {RETROK_F2,"F2"},
+ {RETROK_F3,"F3"},
+ {RETROK_F4,"F4"},
+ {RETROK_F5,"F5"},
+ {RETROK_F6,"F6"},
+ {RETROK_F7,"F7"},
+ {RETROK_F8,"F8"},
+ {RETROK_F9,"F9"},
+ {RETROK_F10,"F10"},
+ {RETROK_F11,"F11"},
+ {RETROK_F12,"F12"},
+ {RETROK_ESCAPE,"ESC"},
+ {0,""}
+};
+#endif
+
+int joykeys[2][5] = {{0,0,0,0,0},{0,0,0,0,0}};
+int joykeystab[128];
+int syskeys[8] = {0,0,0,0,0,0,0,0};
+
+
+void set_defjoykeys(int jn, int sc){
+ //if (sc)
+ // set_joykeys(jn,RETROK_w,RETROK_s,RETROK_a,RETROK_d,RETROK_SPACE);
+ //else
+ // set_joykeys(jn,RETROK_UP,RETROK_DOWN,RETROK_LEFT,RETROK_RIGHT,RETROK_l);
+}
+
+
+void set_defsystemkeys(void){
+ set_systemkeys(RETROK_F12,RETROK_F1,RETROK_F4,RETROK_F5,RETROK_F8,RETROK_F2,RETROK_F3,RETROK_F6);
+}
+
+
+
+void set_joykeys(int jn, int up, int down, int left, int right, int fire){
+ int i,j;
+ if ((jn<0) || (jn>1)) return;
+ joykeys[jn][0] = up;
+ joykeys[jn][1] = down;
+ joykeys[jn][2] = left;
+ joykeys[jn][3] = right;
+ joykeys[jn][4] = fire;
+
+ for (i=0; i<128; i++) joykeystab[i]=0;
+
+ for (j=0; j<2; j++)
+ for (i=0; i<5; i++) {
+ if ((joykeys[j][i]<1) || (joykeys[j][i]>127))
+ joykeys[j][i] = 0;
+ else
+ joykeystab[joykeys[j][i]] = 1;
+ }
+}
+
+void set_systemkeys(int k_quit,int k_pause,int k_debug,int k_reset,int k_screencap,int k_save,int k_load,int k_inject)
+{
+ syskeys[0] = k_quit;
+ syskeys[1] = k_pause;
+ syskeys[2] = k_debug;
+ syskeys[3] = k_reset;
+ syskeys[4] = k_screencap;
+ syskeys[5] = k_save;
+ syskeys[6] = k_load;
+ syskeys[7] = k_inject;
+}
+
+#ifdef __LIBRETRO__
+unsigned char key[256*2];
+
+void rloadstate(){
+
+ int stateError;
+ if ((stateError=loadstate(app_data.statefile))==0)
+ {
+ printf("Savefile loaded.\n");
+ }
+ else if (stateError>=199)
+ {
+ if (stateError==199) printf("Wrong ROM-File for Savefile.\n");
+ else if (stateError==200+ROM_O2) printf("Wrong BIOS for Savefile: O2ROM needed.\n");
+ else if (stateError==200+ROM_G7400) printf("Wrong BIOS for Savefile: G7400 ROM needed.\n");
+ else if (stateError==200+ROM_C52) printf("Wrong BIOS for Savefile: C52 ROM needed.\n");
+ else if (stateError==200+ROM_JOPAC) printf("Wrong BIOS for Savefile: JOPAC ROM needed.\n");
+ else printf("Wrong BIOS for Savefile: UNKNOWN ROM needed.\n");
+ }
+
+}
+
+void rsavestate(){
+
+ if (savestate(app_data.statefile)==0)
+ {
+ printf("Savefile saved.\n");
+ }
+}
+
+void rscore(){
+
+ set_score(app_data.scoretype, app_data.scoreaddress, app_data.default_highscore);
+}
+
+#endif
+
+void handle_key(void){
+
+ if (NeedsPoll)
+ poll_keyboard();
+
+ if (key[syskeys[0]] || key[RETROK_ESCAPE]) {
+ do {
+ rest(5);
+ if (NeedsPoll)
+ poll_keyboard();
+
+ } while (key[syskeys[0]] || key[RETROK_ESCAPE]);
+ key_done=1;
+ }
+
+ if (key[syskeys[1]]) {
+ do {
+ rest(5);
+ if (NeedsPoll)
+ poll_keyboard();
+
+ } while (key[syskeys[1]]);
+
+ mute_audio();
+ mute_voice();
+ abaut();
+
+ do {
+ rest(5);
+ if (NeedsPoll)
+ poll_keyboard();
+
+ if (key[RETROK_LALT] && key[RETROK_RETURN]) {
+ app_data.fullscreen = app_data.fullscreen ? 0 : 1;
+ grmode();
+ abaut();
+ do {
+ rest(5);
+ if (NeedsPoll)
+ poll_keyboard();
+
+ } while (key[RETROK_RETURN]);
+ }
+
+ } while ((!key[syskeys[1]]) && (!key[RETROK_ESCAPE]) && (!key[syskeys[0]]));
+ do {
+ rest(5);
+ if (NeedsPoll)
+ poll_keyboard();
+
+ } while (key[syskeys[1]]);
+
+ init_sound_stream();
+ }
+
+ if (key[syskeys[5]])
+ {
+ if (savestate(app_data.statefile)==0)
+ {
+ display_msg("Savefile saved.",5);
+ }
+ do {
+ rest(5);
+ if (NeedsPoll)
+ poll_keyboard();
+
+ } while (key[syskeys[5]]);
+
+ }
+
+ /* LOAD STATE */
+ if (key[syskeys[6]])
+ {
+ int stateError;
+ if ((stateError=loadstate(app_data.statefile))==0)
+ {
+ display_msg("Savefile loaded.",5);
+ }
+ else if (stateError>=199)
+ {
+ if (stateError==199) display_msg("Wrong ROM-File for Savefile.",5);
+ else if (stateError==200+ROM_O2) display_msg("Wrong BIOS for Savefile: O2ROM needed.",5);
+ else if (stateError==200+ROM_G7400) display_msg("Wrong BIOS for Savefile: G7400 ROM needed.",5);
+ else if (stateError==200+ROM_C52) display_msg("Wrong BIOS for Savefile: C52 ROM needed.",5);
+ else if (stateError==200+ROM_JOPAC) display_msg("Wrong BIOS for Savefile: JOPAC ROM needed.",5);
+ else display_msg("Wrong BIOS for Savefile: UNKNOWN ROM needed.",5);
+ }
+ do {
+ rest(5);
+ if (NeedsPoll)
+ poll_keyboard();
+
+ } while (key[syskeys[6]]);
+ }
+
+ if (key[syskeys[2]]) key_debug=1;
+
+ if (key[syskeys[3]]) {
+ init_cpu();
+ init_roms();
+ init_vpp();
+ clearscr();
+ do {
+ rest(5);
+ if (NeedsPoll)
+ poll_keyboard();
+
+ } while (key[syskeys[3]]);
+ }
+
+ /* SET HIGHSCORE */
+ if (key[syskeys[7]])
+ {
+ set_score(app_data.scoretype, app_data.scoreaddress, app_data.default_highscore);
+ }
+
+
+ if (key[syskeys[4]]) {
+#ifndef __LIBRETRO__
+ BITMAP *bmp;
+ PALETTE pal;
+ char *p;
+ static char name[1024];
+ static int scshot_counter = 0;
+
+ if (strlen(app_data.scshot)>0){
+ if ((p=strchr(app_data.scshot,'@'))) {
+ *p = 0;
+ sprintf(name, "%s%02d%s", app_data.scshot, scshot_counter++, p+1);
+ *p = '@';
+ } else {
+ strcpy(name, app_data.scshot);
+ }
+ get_palette(pal);
+ bmp = create_sub_bitmap(screen, 0, 0, SCREEN_W, SCREEN_H);
+ save_bitmap(name, bmp, pal);
+ destroy_bitmap(bmp);
+ do {
+ rest(5);
+ if (NeedsPoll)
+ poll_keyboard();
+
+ } while (key[syskeys[4]]);
+ }
+#endif
+ }
+
+
+ if (key[RETROK_LALT] && key[RETROK_RETURN]) {
+ app_data.fullscreen = app_data.fullscreen ? 0 : 1;
+ grmode();
+ do {
+ rest(5);
+ if (NeedsPoll)
+ poll_keyboard();
+
+ } while (key[RETROK_RETURN]);
+ }
+
+}
+
+extern int joystick_data[2][5]; //Up, Down, Left, Right, "Action"
+
+Byte keyjoy(int jn){
+ Byte d;
+ d=0xFF;
+ if ((jn>=0) && (jn<=1)){
+#ifdef __LIBRETRO__
+ if (joystick_data[jn][0]) d &= 0xFE;
+ if (joystick_data[jn][1]) d &= 0xFB;
+ if (joystick_data[jn][2]) d &= 0xF7;
+ if (joystick_data[jn][3]) d &= 0xFD;
+ if (joystick_data[jn][4]) d &= 0xEF;
+#else
+ if (NeedsPoll)
+ poll_keyboard();
+
+ if (key[joykeys[jn][0]]) d &= 0xFE;
+ if (key[joykeys[jn][1]]) d &= 0xFB;
+ if (key[joykeys[jn][2]]) d &= 0xF7;
+ if (key[joykeys[jn][3]]) d &= 0xFD;
+ if (key[joykeys[jn][4]]) d &= 0xEF;
+#endif
+ }
+ return d;
+}
+
+
+void init_keyboard(void){
+ key_done=0;
+ key_debug=0;
+
+#ifndef __LIBRETRO__
+ install_keyboard();
+#else
+ memset(key,0,512);
+#endif
+ new_int=1;
+#ifndef __LIBRETRO__
+ NeedsPoll = keyboard_needs_poll();
+#else
+ NeedsPoll = 1;
+#endif
+}
+
+
+void Set_Old_Int9(void){
+#ifndef __LIBRETRO__
+ remove_keyboard();
+#endif
+ new_int=0;
+}
+
diff --git a/src/keyboard.h b/src/keyboard.h
new file mode 100755
index 0000000..da8daca
--- /dev/null
+++ b/src/keyboard.h
@@ -0,0 +1,29 @@
+#ifndef __KEYBOARD_H
+#define __KEYBOARD_H
+
+void Set_Old_Int9(void);
+void init_keyboard(void);
+void handle_key(void);
+void set_joykeys(int joy, int up, int down, int left, int right, int fire);
+void set_systemkeys(int k_quit,int k_pause,int k_debug,int k_reset,int k_screencap,int k_save,int k_load,int k_inject);
+void set_defjoykeys(int joy, int sc);
+void set_defsystemkeys(void);
+Byte keyjoy(int jn);
+
+extern Byte new_int;
+extern int NeedsPoll;
+extern Byte key_done;
+extern Byte key_debug;
+extern int joykeys[2][5];
+extern int joykeystab[128];
+extern int syskeys[8];
+
+struct keyb{
+ int keybcode;
+ char *keybname;
+};
+
+extern struct keyb keybtab[];
+
+#endif
+
diff --git a/src/main.c b/src/main.c
new file mode 100755
index 0000000..ebfeda9
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,962 @@
+
+/*
+ * O2EM Free Odyssey2 / Videopac+ Emulator
+ *
+ * Created by Daniel Boris (c) 1997,1998
+ *
+ * Developed by Andre de la Rocha
+ * Arlindo M. de Oliveira
+ *
+ * http://o2em.sourceforge.net
+ *
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#include "crc32.h"
+#include "audio.h"
+#include "vmachine.h"
+#include "config.h"
+#include "vdc.h"
+#include "cpu.h"
+#include "debug.h"
+#include "keyboard.h"
+#include "voice.h"
+
+#ifndef __LIBRETRO__
+#include "allegro.h"
+#else
+#include "wrapalleg.h"
+
+#ifdef AND
+#warning android log
+#include
+#define printf(...) __android_log_print(ANDROID_LOG_DEBUG, "TAG", __VA_ARGS__)
+#endif
+
+#endif
+
+#include "score.h"
+#ifdef ALLEGRO_WINDOWS
+#include "winalleg.h"
+#endif
+static char bios[MAXC], scshot[MAXC], xrom[MAXC], romdir[MAXC], xbios[MAXC],
+ biosdir[MAXC], arkivo[MAXC][MAXC], biossux[MAXC], romssux[MAXC],
+ odyssey2[MAXC], g7400[MAXC], c52[MAXC], jopac[MAXC], file_l[MAXC], bios_l[MAXC],
+ file_v[MAXC],scorefile[MAXC], statefile[MAXC], path[MAXC];
+FILE *f;
+char name_f, rom_f, c_j;
+char pathx, *k, *launcher_flag_r, *launcher_flag_b, identify;
+int file_name(char *pathx);
+int suck_bios();
+int suck_roms();
+int identify_bios(char *identify);
+int contax, o2flag, g74flag, c52flag, jopflag, helpflag;
+int j;
+unsigned long crcx = ~0;
+static long filesize(FILE *stream);
+static void load_bios(const char *biosname);
+static void load_cart(char *file);
+static void helpus(void);
+int parse_option(char *attr, char *val);
+void read_default_config(void);
+/********************* Main*/
+int omain(int argc, char *argv[]){
+ int i, cnt, cntt, cnttt, way;
+ static char file[MAXC], attr[MAXC], val[MAXC], *p, *binver;
+ #if defined(ALLEGRO_WINDOWS)
+ binver = "Windows binary";
+ #elif defined(ALLEGRO_DOS)
+ binver = "DOS binary";
+ #elif defined(ALLEGRO_LINUX)
+ binver = "Linux binary";
+ #elif defined(ALLEGRO_BEOS)
+ binver = "BEOS binary";
+ #elif defined(ALLEGRO_QNX)
+ binver = "QNX binary";
+ #elif defined(ALLEGRO_UNIX)
+ binver = "UNIX binary";
+ #elif defined(ALLEGRO_MPW)
+ binver = "MacOS binary";
+ #else
+ binver = "Unknown binary";
+ #endif
+ printf("%s %s\n","\nO2EM v" O2EM_VERSION " " RELEASE_DATE " - ", binver);
+ printf("Free Odyssey2 / Videopac+ Emulator - http://o2em.sourceforge.net\n");
+ printf("Created by Daniel Boris (c)1996/1998\n");
+ printf("Developed by:\n");
+ printf(" Andre de la Rocha since version 0.80\n");
+ printf(" Arlindo M. de Oliveira since version 1.16\n");
+ printf("\n");
+
+ app_data.debug = 0;
+ app_data.stick[0] = app_data.stick[1] = 1;
+ app_data.sticknumber[0] = app_data.sticknumber[1] = 0;
+ set_defjoykeys(0,0);
+ set_defjoykeys(1,1);
+ set_defsystemkeys();
+ app_data.bank = 0;
+ app_data.limit = 1;
+ app_data.sound_en = 1;
+ app_data.speed = 100;
+ app_data.wsize = 2;
+ #ifdef ALLEGRO_DOS
+ app_data.fullscreen = 1;
+ #else
+ app_data.fullscreen = 0;
+ #endif
+ app_data.scanlines = 0;
+ app_data.voice = 1;
+ app_data.window_title = "O2EM v" O2EM_VERSION;
+ app_data.svolume = 100;
+ app_data.vvolume = 100;
+ app_data.filter = 0;
+ app_data.exrom = 0;
+ app_data.three_k = 0;
+ app_data.crc = 0;
+ app_data.scshot = scshot;
+ app_data.statefile = statefile;
+ app_data.euro = 0;
+ app_data.openb = 0;
+ app_data.vpp = 0;
+ app_data.bios = 0;
+ app_data.scoretype = 0;
+ app_data.scoreaddress = 0;
+ app_data.default_highscore = 0;
+ app_data.breakpoint = 65535;
+ app_data.megaxrom = 0;
+ strcpy(file,"");
+ strcpy(file_l,"");
+ strcpy(bios_l,"");
+ strcpy(bios,"");
+ strcpy(scshot,"");
+ strcpy(statefile,"");
+ strcpy(xrom,"");
+ strcpy(scorefile,"highscore.txt");
+ read_default_config();
+ if (argc >= 2){
+ for(i=1; i=199)
+ {
+ if (stateError==199) fprintf(stderr,"Wrong ROM-File for Savefile.");
+ else if (stateError==200+ROM_O2) fprintf(stderr,"Wrong BIOS for Savefile: O2ROM needed.");
+ else if (stateError==200+ROM_G7400) fprintf(stderr,"Wrong BIOS for Savefile: G7400 ROM needed.");
+ else if (stateError==200+ROM_C52) fprintf(stderr,"Wrong BIOS for Savefile: C52 ROM needed.");
+ else if (stateError==200+ROM_JOPAC) fprintf(stderr,"Wrong BIOS for Savefile: JOPAC ROM needed.");
+ else fprintf(stderr,"Wrong BIOS for Savefile: UNKNOWN ROM needed.");
+ return(0);
+ }
+ if (app_data.debug) key_debug=1;
+ #ifndef _DEBUG
+ #ifdef ALLEGRO_WINDOWS
+ FreeConsole();
+ #endif
+ #endif
+
+#ifdef __LIBRETRO__
+return 1;
+#endif
+ run();
+
+ if (app_data.scoretype!=0) save_highscore(get_score(app_data.scoretype, app_data.scoreaddress), scorefile);
+ exit(EXIT_SUCCESS);
+ }
+if (!strcmp(attr,"help")||!strcmp(attr,"HELP")) helpus();
+printf("type o2em -help");
+exit(EXIT_SUCCESS);
+}
+END_OF_MAIN();
+/******************************************************/
+int parse_option(char *attr, char *val){
+ int t;
+ if (!strcmp(attr,"nolimit")) {
+ app_data.limit = !(val[0]!='0');
+ } else if (!strcmp(attr,"nosound")) {
+ app_data.sound_en = !(val[0]!='0');
+ } else if (!strcmp(attr,"novoice")) {
+ app_data.voice = !(val[0]!='0');
+ } else if (!strcmp(attr,"filter")) {
+ app_data.filter = (val[0]!='0');
+ } else if (!strcmp(attr,"debug")) {
+ app_data.debug = (val[0]!='0');
+ } else if ((!strcmp(attr,"s1")) || (!strcmp(attr,"s2"))) {
+ int sn;
+ sn = (!strcmp(attr,"s1"))? 0 : 1;
+ if (strlen(val)<2){
+ t = -1;
+ sscanf(val,"%d",&t);
+ if ((t>=0) && (t<=3)) {
+ if ((t==1)||(t==2)){
+ app_data.stick[sn] = 1;
+ set_defjoykeys(sn,t-1);
+ } else {
+ app_data.stick[sn] = (t==0) ? 0 : 2;
+ if (t==3)
+ {
+ app_data.sticknumber[sn] = app_data.sticknumber[0]+app_data.sticknumber[1]+1;
+ }
+ set_joykeys(sn,0,0,0,0,0);
+ }
+ } else {
+ fprintf(stderr,"Invalid value for option %s\n",attr);
+ return 0;
+ }
+ } else {
+ char *p,*s;
+ int i,k,code,nk,codes[5];
+ strupr(val);
+ nk = 0;
+ p = strtok(val,",");
+ while (p) {
+ i = code = 0;
+ k = keybtab[i].keybcode;
+ s = keybtab[i].keybname;
+ while (k && (code==0)) {
+ if (strcmp(s,p)==0) code = k;
+ i++;
+ k = keybtab[i].keybcode;
+ s = keybtab[i].keybname;
+ }
+ if (!code) {
+ fprintf(stderr,"Invalid value for option %s : key %s unknown\n",attr,p);
+ return 0;
+ }
+ codes[nk] = code;
+ p = strtok(NULL,",");
+ nk++;
+ if (nk>5) {
+ fprintf(stderr,"Invalid value for option %s : invalid number of keys\n",attr);
+ return 0;
+ }
+ }
+ if (nk != 5) {
+ fprintf(stderr,"Invalid value for option %s : invalid number of keys\n",attr);
+ return 0;
+ }
+ app_data.stick[sn] = 1;
+ set_joykeys(sn,codes[0],codes[1],codes[2],codes[3],codes[4]);
+ }
+
+
+
+
+ } else if (!strcmp(attr,"s0")) {
+ char *p,*s;
+ int i,k,code,nk,codes[8];
+ strupr(val);
+ nk = 0;
+ p = strtok(val,",");
+ while (p) {
+ i = code = 0;
+ k = keybtab[i].keybcode;
+ s = keybtab[i].keybname;
+ while (k && (code==0)) {
+ if (strcmp(s,p)==0) code = k;
+ i++;
+ k = keybtab[i].keybcode;
+ s = keybtab[i].keybname;
+ }
+ if (!code) {
+ fprintf(stderr,"Invalid value for option %s : key %s unknown\n",attr,p);
+ return 0;
+ }
+ codes[nk] = code;
+ p = strtok(NULL,",");
+ nk++;
+ if (nk>8) {
+ fprintf(stderr,"Invalid value for option %s : invalid number of keys\n",attr);
+ return 0;
+ }
+ }
+ if (nk != 8) {
+ fprintf(stderr,"Invalid value for option %s : invalid number of keys\n",attr);
+ return 0;
+ }
+ set_systemkeys(codes[0],codes[1],codes[2],codes[3],codes[4],codes[5],codes[6],codes[7]);
+
+} else if (!strcmp(attr,"speed")) {
+ t = -1;
+ sscanf(val,"%d",&t);
+ if ((t>0) && (t<=10000))
+ app_data.speed = t;
+ else {
+ fprintf(stderr,"Invalid value for option %s\n",attr);
+ return 0;
+ }
+ } else if (!strcmp(attr,"svolume")) {
+ t = -1;
+ sscanf(val,"%d",&t);
+ if ((t>=0) && (t<=100))
+ app_data.svolume = t;
+ else {
+ fprintf(stderr,"Invalid value for option %s\n",attr);
+ return 0;
+ }
+ if (t==0) app_data.sound_en=0;
+ } else if (!strcmp(attr,"vvolume")) {
+ t = -1;
+ sscanf(val,"%d",&t);
+ if ((t>=0) && (t<=100))
+ app_data.vvolume = t;
+ else {
+ fprintf(stderr,"Invalid value for option %s\n",attr);
+ return 0;
+ }
+ if (t==0) app_data.voice=0;
+ } else if (!strcmp(attr,"wsize")) {
+ t = -1;
+ sscanf(val,"%d",&t);
+ if ((t>0) && (t<5)) {
+ app_data.wsize = t;
+ app_data.fullscreen = 0;
+ } else {
+ fprintf(stderr,"Invalid value for option %s\n",attr);
+ return 0;
+ }
+ } else if (!strcmp(attr,"fullscreen")) {
+ app_data.fullscreen = (val[0]!='0');
+ } else if (!strcmp(attr,"scanlines")) {
+ app_data.scanlines = (val[0]!='0');
+ } else if (!strcmp(attr,"scshot")) {
+ strcpy(scshot,val);
+ } else if (!strcmp(attr,"savefile")) {
+ strcpy(statefile,val);
+ } else if (!strcmp(attr,"biosdir")) {
+ strcpy(xbios,val);
+ } else if (!strcmp(attr,"bios")) {
+ strcpy(bios,val);
+ } else if (!strcmp(attr,"romdir")) {
+ strcpy(xrom,val);
+ } else if (!strcmp(attr,"help")) {
+ helpflag = 1;
+ } else if (!strcmp(attr,"euro")) {
+ app_data.euro = (val[0]!='0');
+ } else if (!strcmp(attr,"exrom")) {
+ app_data.exrom = (val[0]!='0');
+ } else if (!strcmp(attr,"3k")) {
+ app_data.three_k = (val[0]!='0');
+ } else if (!strcmp(attr,"g7400")){
+ strcpy(bios,"g7400");
+ } else if (!strcmp(attr,"c52")) {
+ strcpy(bios,"c52");
+ } else if (!strcmp(attr,"jopac")) {
+ strcpy(bios,"jopac");
+ } else if (!strcmp(attr,"o2rom")) {
+ strcpy(bios,"o2rom");
+ } else if (!strcmp(attr,"scorefile")) {
+ strcpy(scorefile,val);
+ } else if (!strcmp(attr,"scoreadr")) {
+ t = -1;
+ sscanf(val,"%d",&t);
+ if ((t>=0) && (t<=255))
+ app_data.scoreaddress = t;
+ else {
+ fprintf(stderr,"Invalid value for option %s\n",attr);
+ return 0;
+ }
+ } else if (!strcmp(attr,"scoretype")) {
+ t = -1;
+ sscanf(val,"%d",&t);
+ if ((t>=0) && (t<=9999))
+ app_data.scoretype = t;
+ else {
+ fprintf(stderr,"Invalid value for option %s\n",attr);
+ return 0;
+ }
+ } else if (!strcmp(attr,"score")) {
+ t = -1;
+ sscanf(val,"%d",&t);
+ if ((t>=0) && (t<=999999))
+ app_data.default_highscore = t;
+ else {
+ fprintf(stderr,"Invalid value for option %s\n",attr);
+ return 0;
+ }
+ } else {
+ if (!helpflag){
+ fprintf(stderr,"Invalid option : %s\n",attr);
+ return 0;
+ }
+ }
+ return 1;
+}
+/****************************************************/
+void read_default_config(void){
+ FILE *f;
+ static char attr[MAXC], val[MAXC], s[MAXC];
+ char *p, *fn;
+ int i,l;
+ fn = "o2em_def.cfg";
+ f = fopen(fn,"r");
+ if (!f) {
+ fn = "O2EM_DEF.CFG";
+ f = fopen(fn,"r");
+ }
+ if (!f) return;
+
+ l=0;
+ while (fgets(s,MAXC-1,f)){
+ l++;
+ p=s;
+ while (*p && (isspace(*p))) p++;
+ if (*p && (*p != '#')) {
+ i=0;
+ while (*p && (!isspace(*p)) && (*p != '=')) attr[i++] = *p++;
+ attr[i]=0;
+ while (*p && (isspace(*p))) p++;
+ i=0;
+ if (*p == '='){
+ p++;
+ while (*p && (isspace(*p))) p++;
+ if (*p == '"'){
+ p++;
+ while (*p && (*p != '"') && (*p != '\n') && (*p != '\r')) val[i++] = *p++;
+ } else {
+ while (*p && (!isspace(*p))) val[i++] = *p++;
+ }
+ }
+ val[i]=0;
+ if (strlen(attr)>0) {
+ strlwr(attr);
+ if (!parse_option(attr,val)) {
+ printf("Error in the %s file at line number %d !\n\n",fn,l);
+ }
+ }
+ }
+ }
+ fclose(f);
+}
+/****************************************************/
+static long filesize(FILE *stream){
+ long curpos, length;
+ curpos = ftell(stream);
+ fseek(stream, 0L, SEEK_END);
+ length = ftell(stream);
+ fseek(stream, curpos, SEEK_SET);
+ return length;
+}
+/****************************************************/
+static void load_bios(const char *biosname){
+ FILE *fn;
+ static char s[MAXC+10];
+ unsigned long crc;
+ int i;
+
+ if ((biosname[strlen(biosname)-1]=='/') ||
+ (biosname[strlen(biosname)-1]=='\\') ||
+ (biosname[strlen(biosname)-1]==':')) {
+ strcpy(s,biosname);
+ strcat(s,odyssey2);
+ fn = fopen(s,"rb");
+
+ if (!fn) {
+ strcpy(s,biosname);
+ strcat(s,odyssey2);
+ fn = fopen(s,"rb");
+ }
+ } else {
+
+ strcpy(s,biosname);
+ fn = fopen(biosname,"rb");
+ }
+
+ if (!fn) {
+ fprintf(stderr,"Error loading bios ROM (%s)\n",s);
+ exit(EXIT_FAILURE);
+ }
+ if (fread(rom_table[0],1024,1,fn) != 1) {
+ fprintf(stderr,"Error loading bios ROM %s\n",odyssey2);
+ exit(EXIT_FAILURE);
+ }
+
+ strcpy(s,biosname);
+ fn = fopen(biosname,"rb");
+ if (!fn) {
+ fprintf(stderr,"Error loading bios ROM (%s)\n",s);
+ exit(EXIT_FAILURE);
+ }
+ if (fread(rom_table[0],1024,1,fn) != 1) {
+ fprintf(stderr,"Error loading bios ROM %s\n",odyssey2);
+ exit(EXIT_FAILURE);
+ }
+ fclose(fn);
+ for (i=1; i<8; i++) memcpy(rom_table[i],rom_table[0],1024);
+ crc = crc32_buf(rom_table[0],1024);
+ if (crc==0x8016A315) {
+ printf("Odyssey2 bios ROM loaded\n");
+ app_data.vpp = 0;
+ app_data.bios = ROM_O2;
+ } else if (crc==0xE20A9F41) {
+ printf("Videopac+ G7400 bios ROM loaded\n");
+ app_data.vpp = 1;
+ app_data.bios = ROM_G7400;
+ } else if (crc==0xA318E8D6) {
+ if (!((!o2flag)&&(c52flag))) printf("C52 bios ROM loaded\n"); else printf("Ok\n");
+ app_data.vpp = 0;
+ app_data.bios = ROM_C52;
+
+ } else if (crc==0x11647CA5) {
+ if (g74flag) printf("Jopac bios ROM loaded\n"); else printf(" Ok\n");
+ app_data.vpp = 1;
+ app_data.bios = ROM_JOPAC;
+ } else {
+ printf("Bios ROM loaded (unknown version)\n");
+ app_data.vpp = 0;
+ app_data.bios = ROM_UNKNOWN;
+ }
+}
+/****************************************************/
+static void load_cart(char *file){
+ FILE *fn;
+ long l;
+ int i, nb;
+
+ app_data.crc = crc32_file(file);
+ if (app_data.crc == 0xAFB23F89) app_data.exrom = 1; /* Musician */
+ if (app_data.crc == 0x3BFEF56B) app_data.exrom = 1; /* Four in 1 Row! */
+ if (app_data.crc == 0x9B5E9356) app_data.exrom = 1; /* Four in 1 Row! (french) */
+
+ if (((app_data.crc == 0x975AB8DA) || (app_data.crc == 0xE246A812)) && (!app_data.debug)) {
+ fprintf(stderr,"Error: file %s is an incomplete ROM dump\n",file_v);
+ exit(EXIT_FAILURE);
+ }
+
+ fn=fopen(file,"rb");
+ if (!fn) {
+ fprintf(stderr,"Error loading %s\n",file_v);
+ exit(EXIT_FAILURE);
+ }
+ printf("Loading: \"%s\" Size: ",file_v);
+ l = filesize(fn);
+
+ if ((l % 1024) != 0) {
+ fprintf(stderr,"Error: file %s is an invalid ROM dump\n",file_v);
+ exit(EXIT_FAILURE);
+ }
+
+ /* special MegaCART design by Soeren Gust */
+ if ((l == 32768) || (l == 65536) || (l == 131072) || (l == 262144) || (l == 524288) || (l == 1048576)) {
+ app_data.megaxrom = 1;
+ app_data.bank = 1;
+ megarom = malloc(1048576);
+ if (megarom == NULL) {
+ fprintf(stderr, "Out of memory loading %s\n", file);
+ exit(EXIT_FAILURE);
+ }
+ if (fread(megarom, l, 1, fn) != 1) {
+ fprintf(stderr,"Error loading %s\n",file);
+ exit(EXIT_FAILURE);
+ }
+
+ /* mirror shorter files into full megabyte */
+ if (l < 65536) memcpy(megarom+32768,megarom,32768);
+ if (l < 131072) memcpy(megarom+65536,megarom,65536);
+ if (l < 262144) memcpy(megarom+131072,megarom,131072);
+ if (l < 524288) memcpy(megarom+262144,megarom,262144);
+ if (l < 1048576) memcpy(megarom+524288,megarom,524288);
+ /* start in bank 0xff */
+ memcpy(&rom_table[0][1024], megarom + 4096*255 + 1024, 3072);
+ printf("MegaCart %ldK", l / 1024);
+ nb = 1;
+ } else if (((l % 3072) == 0))
+ {
+ app_data.three_k = 1;
+ nb = l/3072;
+
+ for (i=nb-1; i>=0; i--) {
+ if (fread(&rom_table[i][1024],3072,1,fn) != 1) {
+ fprintf(stderr,"Error loading %s\n",file);
+ exit(EXIT_FAILURE);
+ }
+ }
+ printf("%dK",nb*3);
+
+ } else {
+
+ nb = l/2048;
+
+ if ((nb == 2) && (app_data.exrom)) {
+
+ if (fread(&extROM[0], 1024,1,fn) != 1) {
+ fprintf(stderr,"Error loading %s\n",file);
+ exit(EXIT_FAILURE);
+ }
+ if (fread(&rom_table[0][1024],3072,1,fn) != 1) {
+ fprintf(stderr,"Error loading %s\n",file);
+ exit(EXIT_FAILURE);
+ }
+ printf("3K EXROM");
+
+ } else {
+
+ for (i=nb-1; i>=0; i--) {
+ if (fread(&rom_table[i][1024],2048,1,fn) != 1) {
+ fprintf(stderr,"Error loading %s\n",file);
+ exit(EXIT_FAILURE);
+ }
+ memcpy(&rom_table[i][3072],&rom_table[i][2048],1024); /* simulate missing A10 */
+ }
+ printf("%dK",nb*2);
+
+ }
+ }
+ fclose(fn);
+ rom = rom_table[0];
+ if (nb==1)
+ app_data.bank = 1;
+ else if (nb==2)
+ app_data.bank = app_data.exrom ? 1 : 2;
+ else if (nb==4)
+ app_data.bank = 3;
+ else
+ app_data.bank = 4;
+
+ if ((rom_table[nb-1][1024+12]=='O') && (rom_table[nb-1][1024+13]=='P') && (rom_table[nb-1][1024+14]=='N') && (rom_table[nb-1][1024+15]=='B')) app_data.openb=1;
+
+ printf(" CRC: %08lX\n",app_data.crc);
+}
+/*************************** Helpus*/
+void helpus(void){
+#ifndef __LIBRETRO__
+allegro_init();
+install_timer();
+#endif
+printf("here helpus\n");
+init_display();
+printf("here after init disp\n");
+init_system();
+#ifdef ALLEGRO_WINDOWS
+FreeConsole();
+#endif
+help();
+exit(EXIT_SUCCESS);
+}
+/*********************Open the directory `pathxŽ*/
+int file_name(char *pathx)
+{
+ DIR *dir_p;
+ struct dirent *dir_entry_p;
+ contax=0;
+ dir_p = opendir(pathx);
+
+ if (dir_p == NULL) { fprintf(stderr,"dir '%s' not found !\n", pathx); exit(-1); }
+while(0 != (dir_entry_p = readdir(dir_p)))
+ {
+#ifndef __LIBRETRO__
+ strcpy(arkivo[contax], dir_entry_p->d_name);
+#else
+ sprintf(arkivo[contax],"%s\0",dir_entry_p->d_name);
+#endif
+ contax++;
+ }
+ closedir(dir_p);
+ return(0);
+}
+/********************* Search BIOS */
+int suck_bios()
+{
+ int i;
+ for (i=0; i (c) 1997,1998
+ *
+ * Developed by Andre de la Rocha
+ *
+ * http://o2em.sourceforge.net
+ *
+ *
+ *
+ * Score loading/saving by manopac
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include "vmachine.h"
+#include "types.h"
+#include "score.h"
+
+#ifdef __LIBRETRO__
+#include
+#endif
+
+/*--------------------------------------------------
+ Calculate Score from given Values
+ Scoretype = abcd:
+ ramtype a = 1: ext ram / 2: int ram
+ valuetype b = 1: 1 Byte each Digit / 2: 1/2 Byte each Digit
+ directíon c = 1: higher value digits first / 2: low value digits first
+ count d = number of digits
+ --------------------------------------------------*/
+int get_score(int scoretype, int scoreaddress)
+{
+ int score=0;
+
+ if (scoretype!=0)
+ {
+ int position;
+ int i;
+ Byte *RAM;
+
+ int count = scoretype%10;
+ int direction = ((scoretype/10)%10)==1?1:-1;
+ float valuetype = (float) (3-((scoretype/100)%10))/2;
+ int ramtype = scoretype/1000;
+
+ position = scoreaddress+ (direction==1?0:(count*valuetype-1));
+ RAM = ramtype==1?extRAM:intRAM;
+
+ for(i=0;i