mirror of https://github.com/jeremysrand/BuGS.git
Compare commits
6 Commits
37faafb698
...
59dc11e516
Author | SHA1 | Date |
---|---|---|
Jeremy Rand | 59dc11e516 | |
Jeremy Rand | 6afbf4eb85 | |
Jeremy Rand | 2f53df9eb0 | |
Jeremy Rand | 3660b47fd3 | |
Jeremy Rand | 1be8d217f1 | |
Jeremy Rand | 0ae5fa1b54 |
1
BUGS.md
1
BUGS.md
|
@ -2,6 +2,7 @@ BUGS
|
||||||
=======
|
=======
|
||||||
|
|
||||||
This is a list of the software bugs (as opposed to the bugs in the game that you shoot) that still need attention:
|
This is a list of the software bugs (as opposed to the bugs in the game that you shoot) that still need attention:
|
||||||
|
* Should detect when running on system 5 or lower and quit gracefully. Today, the game crashes.
|
||||||
|
|
||||||
|
|
||||||
FIXED
|
FIXED
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
archiveVersion = 1;
|
archiveVersion = 1;
|
||||||
classes = {
|
classes = {
|
||||||
};
|
};
|
||||||
objectVersion = 50;
|
objectVersion = 53;
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
9DE37B742694E0B0005FC562 /* level.s in Sources */ = {isa = PBXBuildFile; fileRef = 9DE37B332694E0B0005FC562 /* level.s */; };
|
9DE37B742694E0B0005FC562 /* level.s in Sources */ = {isa = PBXBuildFile; fileRef = 9DE37B332694E0B0005FC562 /* level.s */; };
|
||||||
9DE37B752694E0B0005FC562 /* tileConvert.s in Sources */ = {isa = PBXBuildFile; fileRef = 9DE37B342694E0B0005FC562 /* tileConvert.s */; };
|
9DE37B752694E0B0005FC562 /* tileConvert.s in Sources */ = {isa = PBXBuildFile; fileRef = 9DE37B342694E0B0005FC562 /* tileConvert.s */; };
|
||||||
9DE37B762694E0B0005FC562 /* gameSpider.s in Sources */ = {isa = PBXBuildFile; fileRef = 9DE37B362694E0B0005FC562 /* gameSpider.s */; };
|
9DE37B762694E0B0005FC562 /* gameSpider.s in Sources */ = {isa = PBXBuildFile; fileRef = 9DE37B362694E0B0005FC562 /* gameSpider.s */; };
|
||||||
9DE37B772694E0B0005FC562 /* globalScores.c in Sources */ = {isa = PBXBuildFile; fileRef = 9DE37B372694E0B0005FC562 /* globalScores.c */; };
|
9DE37B772694E0B0005FC562 /* netScores.c in Sources */ = {isa = PBXBuildFile; fileRef = 9DE37B372694E0B0005FC562 /* netScores.c */; };
|
||||||
9DE37B782694E0B0005FC562 /* game.s in Sources */ = {isa = PBXBuildFile; fileRef = 9DE37B382694E0B0005FC562 /* game.s */; };
|
9DE37B782694E0B0005FC562 /* game.s in Sources */ = {isa = PBXBuildFile; fileRef = 9DE37B382694E0B0005FC562 /* game.s */; };
|
||||||
9DE37B792694E0B0005FC562 /* gameShot.s in Sources */ = {isa = PBXBuildFile; fileRef = 9DE37B3A2694E0B0005FC562 /* gameShot.s */; };
|
9DE37B792694E0B0005FC562 /* gameShot.s in Sources */ = {isa = PBXBuildFile; fileRef = 9DE37B3A2694E0B0005FC562 /* gameShot.s */; };
|
||||||
9DE37B7A2694E0B0005FC562 /* loadSounds.c in Sources */ = {isa = PBXBuildFile; fileRef = 9DE37B3B2694E0B0005FC562 /* loadSounds.c */; };
|
9DE37B7A2694E0B0005FC562 /* loadSounds.c in Sources */ = {isa = PBXBuildFile; fileRef = 9DE37B3B2694E0B0005FC562 /* loadSounds.c */; };
|
||||||
|
@ -106,14 +106,14 @@
|
||||||
9DE37B342694E0B0005FC562 /* tileConvert.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = tileConvert.s; sourceTree = "<group>"; };
|
9DE37B342694E0B0005FC562 /* tileConvert.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = tileConvert.s; sourceTree = "<group>"; };
|
||||||
9DE37B352694E0B0005FC562 /* main.rez */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.rez; path = main.rez; sourceTree = "<group>"; };
|
9DE37B352694E0B0005FC562 /* main.rez */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.rez; path = main.rez; sourceTree = "<group>"; };
|
||||||
9DE37B362694E0B0005FC562 /* gameSpider.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = gameSpider.s; sourceTree = "<group>"; };
|
9DE37B362694E0B0005FC562 /* gameSpider.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = gameSpider.s; sourceTree = "<group>"; };
|
||||||
9DE37B372694E0B0005FC562 /* globalScores.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = globalScores.c; sourceTree = "<group>"; };
|
9DE37B372694E0B0005FC562 /* netScores.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = netScores.c; sourceTree = "<group>"; };
|
||||||
9DE37B382694E0B0005FC562 /* game.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = game.s; sourceTree = "<group>"; };
|
9DE37B382694E0B0005FC562 /* game.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = game.s; sourceTree = "<group>"; };
|
||||||
9DE37B392694E0B0005FC562 /* main.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = main.h; sourceTree = "<group>"; };
|
9DE37B392694E0B0005FC562 /* main.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = main.h; sourceTree = "<group>"; };
|
||||||
9DE37B3A2694E0B0005FC562 /* gameShot.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = gameShot.s; sourceTree = "<group>"; };
|
9DE37B3A2694E0B0005FC562 /* gameShot.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = gameShot.s; sourceTree = "<group>"; };
|
||||||
9DE37B3B2694E0B0005FC562 /* loadSounds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = loadSounds.c; sourceTree = "<group>"; };
|
9DE37B3B2694E0B0005FC562 /* loadSounds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = loadSounds.c; sourceTree = "<group>"; };
|
||||||
9DE37B3C2694E0B0005FC562 /* loadSounds.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = loadSounds.h; sourceTree = "<group>"; };
|
9DE37B3C2694E0B0005FC562 /* loadSounds.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = loadSounds.h; sourceTree = "<group>"; };
|
||||||
9DE37B3D2694E0B0005FC562 /* gameMushroom.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = gameMushroom.s; sourceTree = "<group>"; };
|
9DE37B3D2694E0B0005FC562 /* gameMushroom.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = gameMushroom.s; sourceTree = "<group>"; };
|
||||||
9DE37B3E2694E0B0005FC562 /* globalScores.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = globalScores.h; sourceTree = "<group>"; };
|
9DE37B3E2694E0B0005FC562 /* netScores.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = netScores.h; sourceTree = "<group>"; };
|
||||||
9DE37B3F2694E0B0005FC562 /* globals.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = globals.s; sourceTree = "<group>"; };
|
9DE37B3F2694E0B0005FC562 /* globals.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = globals.s; sourceTree = "<group>"; };
|
||||||
9DE37B402694E0B0005FC562 /* gameSegments.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = gameSegments.s; sourceTree = "<group>"; };
|
9DE37B402694E0B0005FC562 /* gameSegments.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = gameSegments.s; sourceTree = "<group>"; };
|
||||||
9DE37B412694E0B0005FC562 /* score.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = score.s; sourceTree = "<group>"; };
|
9DE37B412694E0B0005FC562 /* score.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = score.s; sourceTree = "<group>"; };
|
||||||
|
@ -221,8 +221,8 @@
|
||||||
9DE37B732694E0B0005FC562 /* genData.pl */,
|
9DE37B732694E0B0005FC562 /* genData.pl */,
|
||||||
9DE37B442694E0B0005FC562 /* global.macros */,
|
9DE37B442694E0B0005FC562 /* global.macros */,
|
||||||
9DE37B3F2694E0B0005FC562 /* globals.s */,
|
9DE37B3F2694E0B0005FC562 /* globals.s */,
|
||||||
9DE37B372694E0B0005FC562 /* globalScores.c */,
|
9DE37B372694E0B0005FC562 /* netScores.c */,
|
||||||
9DE37B3E2694E0B0005FC562 /* globalScores.h */,
|
9DE37B3E2694E0B0005FC562 /* netScores.h */,
|
||||||
9DE37B332694E0B0005FC562 /* level.s */,
|
9DE37B332694E0B0005FC562 /* level.s */,
|
||||||
9DE37B3B2694E0B0005FC562 /* loadSounds.c */,
|
9DE37B3B2694E0B0005FC562 /* loadSounds.c */,
|
||||||
9DE37B3C2694E0B0005FC562 /* loadSounds.h */,
|
9DE37B3C2694E0B0005FC562 /* loadSounds.h */,
|
||||||
|
@ -412,7 +412,8 @@
|
||||||
9DE37ADF2694E070005FC562 /* Project object */ = {
|
9DE37ADF2694E070005FC562 /* Project object */ = {
|
||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
LastUpgradeCheck = 1240;
|
BuildIndependentTargetsInParallel = YES;
|
||||||
|
LastUpgradeCheck = 1430;
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
9DE37AE32694E070005FC562 = {
|
9DE37AE32694E070005FC562 = {
|
||||||
CreatedOnToolsVersion = 12.4;
|
CreatedOnToolsVersion = 12.4;
|
||||||
|
@ -478,7 +479,7 @@
|
||||||
9DE37B852694E0B0005FC562 /* solid.s in Sources */,
|
9DE37B852694E0B0005FC562 /* solid.s in Sources */,
|
||||||
9DE37B7C2694E0B0005FC562 /* globals.s in Sources */,
|
9DE37B7C2694E0B0005FC562 /* globals.s in Sources */,
|
||||||
9DE37B872694E0B0005FC562 /* symbols.s in Sources */,
|
9DE37B872694E0B0005FC562 /* symbols.s in Sources */,
|
||||||
9DE37B772694E0B0005FC562 /* globalScores.c in Sources */,
|
9DE37B772694E0B0005FC562 /* netScores.c in Sources */,
|
||||||
9DE37B8B2694E0B0005FC562 /* scores.s in Sources */,
|
9DE37B8B2694E0B0005FC562 /* scores.s in Sources */,
|
||||||
9DE37B932694E0B0005FC562 /* gameSound.s in Sources */,
|
9DE37B932694E0B0005FC562 /* gameSound.s in Sources */,
|
||||||
9DE37B922694E0B0005FC562 /* gameScorpion.s in Sources */,
|
9DE37B922694E0B0005FC562 /* gameScorpion.s in Sources */,
|
||||||
|
@ -531,6 +532,7 @@
|
||||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
|
DEAD_CODE_STRIPPING = YES;
|
||||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
ENABLE_TESTABILITY = YES;
|
ENABLE_TESTABILITY = YES;
|
||||||
|
@ -588,6 +590,7 @@
|
||||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
|
DEAD_CODE_STRIPPING = YES;
|
||||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
ENABLE_NS_ASSERTIONS = NO;
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
@ -608,6 +611,7 @@
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
DEAD_CODE_STRIPPING = YES;
|
||||||
DEBUGGING_SYMBOLS = YES;
|
DEBUGGING_SYMBOLS = YES;
|
||||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||||
DEVELOPMENT_TEAM = VD9FGCW36C;
|
DEVELOPMENT_TEAM = VD9FGCW36C;
|
||||||
|
@ -623,6 +627,7 @@
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
DEAD_CODE_STRIPPING = YES;
|
||||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
DEVELOPMENT_TEAM = VD9FGCW36C;
|
DEVELOPMENT_TEAM = VD9FGCW36C;
|
||||||
OTHER_CFLAGS = "";
|
OTHER_CFLAGS = "";
|
||||||
|
@ -635,6 +640,7 @@
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
DEAD_CODE_STRIPPING = YES;
|
||||||
DEVELOPMENT_TEAM = VD9FGCW36C;
|
DEVELOPMENT_TEAM = VD9FGCW36C;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
PRODUCT_NAME = BuGS;
|
PRODUCT_NAME = BuGS;
|
||||||
|
@ -645,6 +651,7 @@
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
DEAD_CODE_STRIPPING = YES;
|
||||||
DEVELOPMENT_TEAM = VD9FGCW36C;
|
DEVELOPMENT_TEAM = VD9FGCW36C;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
PRODUCT_NAME = BuGS;
|
PRODUCT_NAME = BuGS;
|
||||||
|
@ -655,6 +662,7 @@
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
DEAD_CODE_STRIPPING = YES;
|
||||||
DEVELOPMENT_TEAM = VD9FGCW36C;
|
DEVELOPMENT_TEAM = VD9FGCW36C;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
PRODUCT_NAME = BuGS.2mg;
|
PRODUCT_NAME = BuGS.2mg;
|
||||||
|
@ -665,6 +673,7 @@
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
DEAD_CODE_STRIPPING = YES;
|
||||||
DEVELOPMENT_TEAM = VD9FGCW36C;
|
DEVELOPMENT_TEAM = VD9FGCW36C;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
PRODUCT_NAME = BuGS.2mg;
|
PRODUCT_NAME = BuGS.2mg;
|
||||||
|
@ -675,6 +684,7 @@
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
DEAD_CODE_STRIPPING = YES;
|
||||||
DEVELOPMENT_TEAM = VD9FGCW36C;
|
DEVELOPMENT_TEAM = VD9FGCW36C;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
PRODUCT_NAME = BuGS.shk;
|
PRODUCT_NAME = BuGS.shk;
|
||||||
|
@ -685,6 +695,7 @@
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
DEAD_CODE_STRIPPING = YES;
|
||||||
DEVELOPMENT_TEAM = VD9FGCW36C;
|
DEVELOPMENT_TEAM = VD9FGCW36C;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
PRODUCT_NAME = BuGS.shk;
|
PRODUCT_NAME = BuGS.shk;
|
||||||
|
@ -695,6 +706,7 @@
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
DEAD_CODE_STRIPPING = YES;
|
||||||
DEVELOPMENT_TEAM = VD9FGCW36C;
|
DEVELOPMENT_TEAM = VD9FGCW36C;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||||
|
@ -717,6 +729,7 @@
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
DEAD_CODE_STRIPPING = YES;
|
||||||
DEVELOPMENT_TEAM = VD9FGCW36C;
|
DEVELOPMENT_TEAM = VD9FGCW36C;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<Scheme
|
<Scheme
|
||||||
LastUpgradeVersion = "0830"
|
LastUpgradeVersion = "1430"
|
||||||
version = "1.3">
|
version = "1.3">
|
||||||
<BuildAction
|
<BuildAction
|
||||||
parallelizeBuildables = "YES"
|
parallelizeBuildables = "YES"
|
||||||
|
@ -14,7 +14,7 @@
|
||||||
buildForAnalyzing = "YES">
|
buildForAnalyzing = "YES">
|
||||||
<BuildableReference
|
<BuildableReference
|
||||||
BuildableIdentifier = "primary"
|
BuildableIdentifier = "primary"
|
||||||
BlueprintIdentifier = "9D0B917C1F526C2D004D7E0B"
|
BlueprintIdentifier = "9DE37AE32694E070005FC562"
|
||||||
BuildableName = "BuGS"
|
BuildableName = "BuGS"
|
||||||
BlueprintName = "BuGS"
|
BlueprintName = "BuGS"
|
||||||
ReferencedContainer = "container:BuGS.xcodeproj">
|
ReferencedContainer = "container:BuGS.xcodeproj">
|
||||||
|
@ -29,8 +29,6 @@
|
||||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
<Testables>
|
<Testables>
|
||||||
</Testables>
|
</Testables>
|
||||||
<AdditionalOptions>
|
|
||||||
</AdditionalOptions>
|
|
||||||
</TestAction>
|
</TestAction>
|
||||||
<LaunchAction
|
<LaunchAction
|
||||||
buildConfiguration = "Debug"
|
buildConfiguration = "Debug"
|
||||||
|
@ -49,7 +47,7 @@
|
||||||
<MacroExpansion>
|
<MacroExpansion>
|
||||||
<BuildableReference
|
<BuildableReference
|
||||||
BuildableIdentifier = "primary"
|
BuildableIdentifier = "primary"
|
||||||
BlueprintIdentifier = "9D0B917C1F526C2D004D7E0B"
|
BlueprintIdentifier = "9DE37AE32694E070005FC562"
|
||||||
BuildableName = "BuGS"
|
BuildableName = "BuGS"
|
||||||
BlueprintName = "BuGS"
|
BlueprintName = "BuGS"
|
||||||
ReferencedContainer = "container:BuGS.xcodeproj">
|
ReferencedContainer = "container:BuGS.xcodeproj">
|
||||||
|
@ -81,8 +79,6 @@
|
||||||
isEnabled = "YES">
|
isEnabled = "YES">
|
||||||
</CommandLineArgument>
|
</CommandLineArgument>
|
||||||
</CommandLineArguments>
|
</CommandLineArguments>
|
||||||
<AdditionalOptions>
|
|
||||||
</AdditionalOptions>
|
|
||||||
</LaunchAction>
|
</LaunchAction>
|
||||||
<ProfileAction
|
<ProfileAction
|
||||||
buildConfiguration = "Release"
|
buildConfiguration = "Release"
|
||||||
|
@ -93,7 +89,7 @@
|
||||||
<MacroExpansion>
|
<MacroExpansion>
|
||||||
<BuildableReference
|
<BuildableReference
|
||||||
BuildableIdentifier = "primary"
|
BuildableIdentifier = "primary"
|
||||||
BlueprintIdentifier = "9D0B917C1F526C2D004D7E0B"
|
BlueprintIdentifier = "9DE37AE32694E070005FC562"
|
||||||
BuildableName = "BuGS"
|
BuildableName = "BuGS"
|
||||||
BlueprintName = "BuGS"
|
BlueprintName = "BuGS"
|
||||||
ReferencedContainer = "container:BuGS.xcodeproj">
|
ReferencedContainer = "container:BuGS.xcodeproj">
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<key>Binary.xcscheme_^#shared#^_</key>
|
<key>Binary.xcscheme_^#shared#^_</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>orderHint</key>
|
<key>orderHint</key>
|
||||||
<integer>4</integer>
|
<integer>1</integer>
|
||||||
</dict>
|
</dict>
|
||||||
<key>BuGS.xcscheme_^#shared#^_</key>
|
<key>BuGS.xcscheme_^#shared#^_</key>
|
||||||
<dict>
|
<dict>
|
||||||
|
@ -22,7 +22,7 @@
|
||||||
<key>DiskImage.xcscheme_^#shared#^_</key>
|
<key>DiskImage.xcscheme_^#shared#^_</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>orderHint</key>
|
<key>orderHint</key>
|
||||||
<integer>1</integer>
|
<integer>4</integer>
|
||||||
</dict>
|
</dict>
|
||||||
<key>doNotBuild.xcscheme_^#shared#^_</key>
|
<key>doNotBuild.xcscheme_^#shared#^_</key>
|
||||||
<dict>
|
<dict>
|
||||||
|
|
|
@ -97,7 +97,7 @@ gameLoop_skipPreload anop
|
||||||
; The following is the network poll code which runs when not playing a game
|
; The following is the network poll code which runs when not playing a game
|
||||||
lda gameState
|
lda gameState
|
||||||
bne gameLoop_skipNetwork
|
bne gameLoop_skipNetwork
|
||||||
jsl pollNetwork
|
jsl NSGS_PollNetwork
|
||||||
lda hasGlobalHighScores
|
lda hasGlobalHighScores
|
||||||
beq gameLoop_skipNetwork
|
beq gameLoop_skipNetwork
|
||||||
lda highScoreCountdown
|
lda highScoreCountdown
|
||||||
|
@ -247,7 +247,7 @@ startGame_singlePlayer anop
|
||||||
jsl spiderInitGame
|
jsl spiderInitGame
|
||||||
jsl levelInit
|
jsl levelInit
|
||||||
jsl soundInit
|
jsl soundInit
|
||||||
jsl disconnectNetwork
|
jsl NSGS_DisconnectNetwork
|
||||||
; Fall through intentionally here...
|
; Fall through intentionally here...
|
||||||
startLevel entry
|
startLevel entry
|
||||||
jsl segmentsInitLevel
|
jsl segmentsInitLevel
|
||||||
|
|
|
@ -224,53 +224,53 @@ _dirtyNonGameTile_skip&SYSCNT anop
|
||||||
|
|
||||||
macro
|
macro
|
||||||
_globalHighScoreRow &nthScore
|
_globalHighScoreRow &nthScore
|
||||||
ldy #2+&nthScore*SETTINGS_HIGH_SCORE_SIZE
|
ldy #&nthScore*SETTINGS_HIGH_SCORE_SIZE
|
||||||
lda highScoreResponse,y
|
lda globalHighScores,y
|
||||||
jsl asciiToTileType
|
jsl asciiToTileType
|
||||||
jsl setGameTile
|
jsl setGameTile
|
||||||
|
|
||||||
iny
|
iny
|
||||||
lda highScoreResponse,y
|
lda globalHighScores,y
|
||||||
jsl asciiToTileType
|
jsl asciiToTileType
|
||||||
jsl setGameTile
|
jsl setGameTile
|
||||||
|
|
||||||
iny
|
iny
|
||||||
lda highScoreResponse,y
|
lda globalHighScores,y
|
||||||
jsl asciiToTileType
|
jsl asciiToTileType
|
||||||
jsl setGameTile
|
jsl setGameTile
|
||||||
|
|
||||||
iny
|
iny
|
||||||
lda highScoreResponse,y
|
lda globalHighScores,y
|
||||||
jsl asciiToTileType
|
jsl asciiToTileType
|
||||||
jsl setGameTile
|
jsl setGameTile
|
||||||
|
|
||||||
iny
|
iny
|
||||||
lda highScoreResponse,y
|
lda globalHighScores,y
|
||||||
jsl asciiToTileType
|
jsl asciiToTileType
|
||||||
jsl setGameTile
|
jsl setGameTile
|
||||||
|
|
||||||
iny
|
iny
|
||||||
lda highScoreResponse,y
|
lda globalHighScores,y
|
||||||
jsl asciiToTileType
|
jsl asciiToTileType
|
||||||
jsl setGameTile
|
jsl setGameTile
|
||||||
|
|
||||||
iny
|
iny
|
||||||
lda highScoreResponse,y
|
lda globalHighScores,y
|
||||||
jsl asciiToTileType
|
jsl asciiToTileType
|
||||||
jsl setGameTile
|
jsl setGameTile
|
||||||
|
|
||||||
iny
|
iny
|
||||||
lda highScoreResponse,y
|
lda globalHighScores,y
|
||||||
jsl asciiToTileType
|
jsl asciiToTileType
|
||||||
jsl setGameTile
|
jsl setGameTile
|
||||||
|
|
||||||
iny
|
iny
|
||||||
lda highScoreResponse,y
|
lda globalHighScores,y
|
||||||
jsl asciiToTileType
|
jsl asciiToTileType
|
||||||
jsl setGameTile
|
jsl setGameTile
|
||||||
|
|
||||||
iny
|
iny
|
||||||
lda highScoreResponse,y
|
lda globalHighScores,y
|
||||||
jsl asciiToTileType
|
jsl asciiToTileType
|
||||||
jsl setGameTile
|
jsl setGameTile
|
||||||
|
|
||||||
|
@ -278,17 +278,17 @@ _dirtyNonGameTile_skip&SYSCNT anop
|
||||||
jsl setGameTile
|
jsl setGameTile
|
||||||
|
|
||||||
iny
|
iny
|
||||||
lda highScoreResponse,y
|
lda globalHighScores,y
|
||||||
jsl asciiToTileType
|
jsl asciiToTileType
|
||||||
jsl setGameTile
|
jsl setGameTile
|
||||||
|
|
||||||
iny
|
iny
|
||||||
lda highScoreResponse,y
|
lda globalHighScores,y
|
||||||
jsl asciiToTileType
|
jsl asciiToTileType
|
||||||
jsl setGameTile
|
jsl setGameTile
|
||||||
|
|
||||||
iny
|
iny
|
||||||
lda highScoreResponse,y
|
lda globalHighScores,y
|
||||||
jsl asciiToTileType
|
jsl asciiToTileType
|
||||||
jsl setGameTile
|
jsl setGameTile
|
||||||
mend
|
mend
|
||||||
|
|
|
@ -1,731 +0,0 @@
|
||||||
/*
|
|
||||||
* globalScores.c
|
|
||||||
* BuGS
|
|
||||||
*
|
|
||||||
* Created by Jeremy Rand on 2021-05-23.
|
|
||||||
* Copyright © 2021 Jeremy Rand. All rights reserved.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <Hash.h>
|
|
||||||
#include <locator.h>
|
|
||||||
#include <misctool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <tcpip.h>
|
|
||||||
#include <types.h>
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include "globalScores.h"
|
|
||||||
|
|
||||||
|
|
||||||
// Defines
|
|
||||||
|
|
||||||
#define REQUEST_TYPE_GET_HIGH_SCORES 0
|
|
||||||
#define REQUEST_TYPE_SET_SCORE 1
|
|
||||||
|
|
||||||
#define RESPONSE_TYPE_HELLO 0
|
|
||||||
#define RESPONSE_TYPE_SCORES 1
|
|
||||||
#define RESPONSE_TYPE_STATUS 2
|
|
||||||
|
|
||||||
#define GLOBAL_SCORE_REFRESH_TIME (15 * 60 * 60)
|
|
||||||
#define SHUTDOWN_NETWORK_TIMEOUT (2 * 60)
|
|
||||||
#define TCP_CONNECT_TIMEOUT (8 * 60)
|
|
||||||
#define READ_NETWORK_TIMEOUT (5 * 60)
|
|
||||||
#define NETWORK_RETRY_TIMEOUT (3 * 60 * 60)
|
|
||||||
|
|
||||||
|
|
||||||
// Types
|
|
||||||
|
|
||||||
typedef struct tSessionSecrets {
|
|
||||||
uint32_t secret;
|
|
||||||
uint32_t nonce;
|
|
||||||
} tSessionSecrets;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct tHighScoreRequest {
|
|
||||||
uint16_t requestType;
|
|
||||||
} tHighScoreRequest;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct tHighScoreRequestWithHash {
|
|
||||||
tHighScoreRequest highScoreRequest;
|
|
||||||
uint8_t md5Digest[16];
|
|
||||||
} tHighScoreRequestWithHash;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct tSetHighScoreRequest {
|
|
||||||
uint16_t requestType;
|
|
||||||
char who[4];
|
|
||||||
uint32_t score;
|
|
||||||
Word is60Hz;
|
|
||||||
} tSetHighScoreRequest;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct tSetHighScoreRequestWithHash {
|
|
||||||
tSetHighScoreRequest setHighScoreRequest;
|
|
||||||
uint8_t md5Digest[16];
|
|
||||||
} tSetHighScoreRequestWithHash;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct tHelloResponse {
|
|
||||||
uint16_t responseType;
|
|
||||||
uint32_t nonce;
|
|
||||||
} tHelloResponse;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct tScoresResponse {
|
|
||||||
uint16_t responseType;
|
|
||||||
tHighScore highScores[10];
|
|
||||||
} tScoresResponse;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct tStatusResponse {
|
|
||||||
uint16_t responseType;
|
|
||||||
Boolean success;
|
|
||||||
uint16_t position;
|
|
||||||
uint16_t numberOfScores;
|
|
||||||
} tStatusResponse;
|
|
||||||
|
|
||||||
|
|
||||||
typedef enum tProtocolErrors {
|
|
||||||
TCP_CONNECT_TIMEOUT_ERROR = 1,
|
|
||||||
HELLO_TIMEOUT_ERROR,
|
|
||||||
HELLO_TOO_BIG_ERROR,
|
|
||||||
HELLO_UNEXPECTED_RESPONSE_ERROR,
|
|
||||||
HIGH_SCORE_TIMEOUT_ERROR,
|
|
||||||
HIGH_SCORE_TOO_BIG_ERROR,
|
|
||||||
HIGH_SCORE_UNEXPECTED_RESPONSE_ERROR,
|
|
||||||
SET_SCORE_TIMEOUT_ERROR,
|
|
||||||
SET_SCORE_TOO_BIG_ERROR,
|
|
||||||
SET_SCORE_UNEXPECTED_RESPONSE_ERROR,
|
|
||||||
SET_SCORE_FAILED_ERROR,
|
|
||||||
} tProtocolErrors;
|
|
||||||
|
|
||||||
|
|
||||||
typedef enum tGameNetworkState {
|
|
||||||
GAME_NETWORK_CONNECT_FAILED = 0,
|
|
||||||
GAME_NETWORK_UNCONNECTED,
|
|
||||||
|
|
||||||
/* All states below this should have Marinetti disconnected */
|
|
||||||
GAME_NETWORK_CONNECTED,
|
|
||||||
GAME_NETWORK_RESOLVING_NAME,
|
|
||||||
|
|
||||||
/* These are all of the error states. Marinetti is still connected but the
|
|
||||||
TCP connection is closed and ipid released. */
|
|
||||||
GAME_NETWORK_LOOKUP_FAILED,
|
|
||||||
GAME_NETWORK_SOCKET_ERROR,
|
|
||||||
GAME_NETWORK_PROTOCOL_FAILED,
|
|
||||||
GAME_NETWORK_FAILURE,
|
|
||||||
|
|
||||||
/* This is the state we are in during a game on a machine with a working network
|
|
||||||
(other possible states are fail states). */
|
|
||||||
GAME_NETWORK_TCP_UNCONNECTED,
|
|
||||||
|
|
||||||
/* All of these states below here have an ipid open and the TCP connection is
|
|
||||||
open and in some state. */
|
|
||||||
GAME_NETWORK_WAITING_FOR_TCP,
|
|
||||||
|
|
||||||
/* All of these states below this point have the TCP connection established
|
|
||||||
and the score protocol is exchanging information. */
|
|
||||||
GAME_NETWORK_WAITING_FOR_HELLO,
|
|
||||||
GAME_NETWORK_REQUEST_SCORES,
|
|
||||||
GAME_NETWORK_WAITING_FOR_SCORES,
|
|
||||||
GAME_NETWORK_SET_HIGH_SCORE,
|
|
||||||
GAME_NETWORK_WAITING_FOR_SCORE_ACK,
|
|
||||||
|
|
||||||
GAME_NETWORK_CLOSING_TCP,
|
|
||||||
} tGameNetworkState;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct tGameNetworkGlobals {
|
|
||||||
Boolean networkStartedConnected;
|
|
||||||
tHighScoreInitParams initParams;
|
|
||||||
tGameNetworkState gameNetworkState;
|
|
||||||
dnrBuffer domainNameResolution;
|
|
||||||
srBuff tcpStatus;
|
|
||||||
Word ipid;
|
|
||||||
rrBuff readResponseBuf;
|
|
||||||
tHelloResponse helloResponse;
|
|
||||||
uint32_t bytesRead;
|
|
||||||
md5WorkBlock hashWorkBlock;
|
|
||||||
uint32_t secrets[3];
|
|
||||||
tHighScoreRequestWithHash highScoreRequest;
|
|
||||||
Boolean hasHighScoreToSend;
|
|
||||||
tStatusResponse setHighScoreResponse;
|
|
||||||
uint16_t errorCode;
|
|
||||||
uint16_t timeout;
|
|
||||||
} tGameNetworkGlobals;
|
|
||||||
|
|
||||||
|
|
||||||
// Globals
|
|
||||||
|
|
||||||
// I am running out of space in the main segment so I am moving these globals into
|
|
||||||
// a dynamically allocated struct. It is only allocated if network capabilities are
|
|
||||||
// detected.
|
|
||||||
static tGameNetworkGlobals * networkGlobals = NULL;
|
|
||||||
|
|
||||||
// The following globals are accessed by name from assembly so are not in the
|
|
||||||
// tGameNetworkGlobals structure.
|
|
||||||
// TODO - Make real interfaces for these things.
|
|
||||||
Boolean hasGlobalHighScores = FALSE;
|
|
||||||
tScoresResponse highScoreResponse;
|
|
||||||
Word globalScoreAge = 0; // TODO - Replace this with a call to a MiscTool function?
|
|
||||||
tSetHighScoreRequestWithHash setHighScoreRequest;
|
|
||||||
|
|
||||||
|
|
||||||
// Implementation
|
|
||||||
|
|
||||||
|
|
||||||
segment "highscores";
|
|
||||||
|
|
||||||
void initNetwork(tHighScoreInitParams * params)
|
|
||||||
{
|
|
||||||
networkGlobals = NULL;
|
|
||||||
|
|
||||||
if ((params->scoreServer == NULL) ||
|
|
||||||
(params->scorePort == 0) ||
|
|
||||||
(params->waitForVbl == NULL))
|
|
||||||
return;
|
|
||||||
|
|
||||||
LoadOneTool(54, 0x200); // Load Marinetti
|
|
||||||
if (toolerror())
|
|
||||||
return;
|
|
||||||
|
|
||||||
LoadOneTool(128, 0x103); // Load the Hash toolset
|
|
||||||
if (toolerror()) {
|
|
||||||
UnloadOneTool(54);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
TCPIPStartUp();
|
|
||||||
if (toolerror()) {
|
|
||||||
UnloadOneTool(128);
|
|
||||||
UnloadOneTool(54);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
hashStartUp();
|
|
||||||
if (toolerror()) {
|
|
||||||
TCPIPShutDown();
|
|
||||||
UnloadOneTool(128);
|
|
||||||
UnloadOneTool(54);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
networkGlobals = malloc(sizeof(tGameNetworkGlobals));
|
|
||||||
if (networkGlobals == NULL) {
|
|
||||||
hashShutDown();
|
|
||||||
TCPIPShutDown();
|
|
||||||
UnloadOneTool(128);
|
|
||||||
UnloadOneTool(54);
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(&(networkGlobals->initParams), params, sizeof(networkGlobals->initParams));
|
|
||||||
|
|
||||||
networkGlobals->networkStartedConnected = TCPIPGetConnectStatus();
|
|
||||||
if (networkGlobals->networkStartedConnected) {
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_CONNECTED;
|
|
||||||
} else {
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_UNCONNECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
networkGlobals->secrets[0] = params->secret1;
|
|
||||||
networkGlobals->secrets[1] = params->secret2;
|
|
||||||
|
|
||||||
networkGlobals->hasHighScoreToSend = FALSE;
|
|
||||||
|
|
||||||
setHighScoreRequest.setHighScoreRequest.is60Hz = !ReadBParam(hrtz50or60);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void shutdownNetwork(void)
|
|
||||||
{
|
|
||||||
if ((!networkGlobals->networkStartedConnected) &&
|
|
||||||
(networkGlobals->gameNetworkState > GAME_NETWORK_UNCONNECTED)) {
|
|
||||||
TCPIPDisconnect(TRUE, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(networkGlobals);
|
|
||||||
|
|
||||||
hashShutDown();
|
|
||||||
TCPIPShutDown();
|
|
||||||
UnloadOneTool(128); // Unload the Hash toolset
|
|
||||||
UnloadOneTool(54); // Unload Marinetti
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void abortConnection(void)
|
|
||||||
{
|
|
||||||
TCPIPAbortTCP(networkGlobals->ipid);
|
|
||||||
TCPIPLogout(networkGlobals->ipid);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void disconnectNetwork(void)
|
|
||||||
{
|
|
||||||
if (networkGlobals == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (networkGlobals->gameNetworkState > GAME_NETWORK_TCP_UNCONNECTED) {
|
|
||||||
if (networkGlobals->gameNetworkState < GAME_NETWORK_CLOSING_TCP) {
|
|
||||||
TCPIPCloseTCP(networkGlobals->ipid);
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_CLOSING_TCP;
|
|
||||||
networkGlobals->timeout = SHUTDOWN_NETWORK_TIMEOUT;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (networkGlobals->gameNetworkState > GAME_NETWORK_TCP_UNCONNECTED) {
|
|
||||||
networkGlobals->initParams.waitForVbl();
|
|
||||||
pollNetwork();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static char hexDigitToAscii(Word digit)
|
|
||||||
{
|
|
||||||
digit &= 0xf;
|
|
||||||
if (digit < 10)
|
|
||||||
return '0' + digit;
|
|
||||||
|
|
||||||
if (digit > 15)
|
|
||||||
return 'X';
|
|
||||||
|
|
||||||
return 'A' + digit - 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void displayString(Word row, char * string)
|
|
||||||
{
|
|
||||||
strcpy(&(highScoreResponse.highScores[row].scoreText[2]), string);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void displayNetworkError(char * line1, char * line2)
|
|
||||||
{
|
|
||||||
Word row;
|
|
||||||
Word column;
|
|
||||||
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_FAILURE;
|
|
||||||
|
|
||||||
for (row = 0; row < sizeof(highScoreResponse.highScores) / sizeof(highScoreResponse.highScores[0]); row++) {
|
|
||||||
for (column = 0;
|
|
||||||
column < sizeof(highScoreResponse.highScores[0].scoreText) / sizeof(highScoreResponse.highScores[0].scoreText[0]);
|
|
||||||
column++) {
|
|
||||||
highScoreResponse.highScores[row].scoreText[column] = ' ';
|
|
||||||
}
|
|
||||||
for (column = 0;
|
|
||||||
column < sizeof(highScoreResponse.highScores[0].who) / sizeof(highScoreResponse.highScores[0].who[0]);
|
|
||||||
column++) {
|
|
||||||
highScoreResponse.highScores[row].who[column] = ' ';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
displayString(1, "NETWORK");
|
|
||||||
displayString(2, "PROBLEM");
|
|
||||||
|
|
||||||
displayString(4, line1);
|
|
||||||
displayString(5, line2);
|
|
||||||
|
|
||||||
highScoreResponse.highScores[7].scoreText[0] = 'C';
|
|
||||||
highScoreResponse.highScores[7].scoreText[1] = 'O';
|
|
||||||
highScoreResponse.highScores[7].scoreText[2] = 'D';
|
|
||||||
highScoreResponse.highScores[7].scoreText[3] = 'E';
|
|
||||||
highScoreResponse.highScores[7].scoreText[4] = ':';
|
|
||||||
highScoreResponse.highScores[7].scoreText[5] = ' ';
|
|
||||||
highScoreResponse.highScores[7].scoreText[6] = hexDigitToAscii(networkGlobals->errorCode >> 12);
|
|
||||||
highScoreResponse.highScores[7].scoreText[7] = hexDigitToAscii(networkGlobals->errorCode >> 8);
|
|
||||||
highScoreResponse.highScores[7].scoreText[8] = hexDigitToAscii(networkGlobals->errorCode >> 4);
|
|
||||||
highScoreResponse.highScores[7].scoreText[9] = hexDigitToAscii(networkGlobals->errorCode);
|
|
||||||
|
|
||||||
globalScoreAge = 0;
|
|
||||||
hasGlobalHighScores = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void pollNetwork(void)
|
|
||||||
{
|
|
||||||
if (networkGlobals == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
TCPIPPoll();
|
|
||||||
|
|
||||||
switch (networkGlobals->gameNetworkState) {
|
|
||||||
case GAME_NETWORK_SOCKET_ERROR:
|
|
||||||
displayNetworkError("SOCKET", "ERROR");
|
|
||||||
networkGlobals->timeout = NETWORK_RETRY_TIMEOUT;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GAME_NETWORK_LOOKUP_FAILED:
|
|
||||||
displayNetworkError("LOOKUP", "FAILED");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GAME_NETWORK_CONNECT_FAILED:
|
|
||||||
displayNetworkError("CONNECT", "FAILED");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GAME_NETWORK_PROTOCOL_FAILED:
|
|
||||||
abortConnection();
|
|
||||||
displayNetworkError("PROTOCOL", "FAILED");
|
|
||||||
networkGlobals->timeout = NETWORK_RETRY_TIMEOUT;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GAME_NETWORK_FAILURE:
|
|
||||||
// All of the different failure modes except protocol failure above end up here ultimately. And the state
|
|
||||||
// machine stays here once it arrives here.
|
|
||||||
if (networkGlobals->timeout > 0) {
|
|
||||||
networkGlobals->timeout--;
|
|
||||||
if (networkGlobals->timeout == 0)
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_TCP_UNCONNECTED;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GAME_NETWORK_UNCONNECTED:
|
|
||||||
if (networkGlobals->initParams.displayConnectionString != NULL)
|
|
||||||
networkGlobals->initParams.displayConnectionString(TRUE);
|
|
||||||
TCPIPConnect(NULL);
|
|
||||||
if ((!toolerror()) &&
|
|
||||||
(TCPIPGetConnectStatus())) {
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_CONNECTED;
|
|
||||||
} else {
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_CONNECT_FAILED;
|
|
||||||
}
|
|
||||||
if (networkGlobals->initParams.displayConnectionString != NULL)
|
|
||||||
networkGlobals->initParams.displayConnectionString(FALSE);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GAME_NETWORK_CONNECTED:
|
|
||||||
TCPIPDNRNameToIP(networkGlobals->initParams.scoreServer, &(networkGlobals->domainNameResolution));
|
|
||||||
if (toolerror()) {
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_LOOKUP_FAILED;
|
|
||||||
networkGlobals->errorCode = toolerror();
|
|
||||||
} else
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_RESOLVING_NAME;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GAME_NETWORK_RESOLVING_NAME:
|
|
||||||
if (networkGlobals->domainNameResolution.DNRstatus == DNR_Pending)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (networkGlobals->domainNameResolution.DNRstatus != DNR_OK) {
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_LOOKUP_FAILED;
|
|
||||||
networkGlobals->errorCode = networkGlobals->domainNameResolution.DNRstatus;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_TCP_UNCONNECTED;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GAME_NETWORK_TCP_UNCONNECTED:
|
|
||||||
if ((hasGlobalHighScores) &&
|
|
||||||
(globalScoreAge > 0) &&
|
|
||||||
(!networkGlobals->hasHighScoreToSend))
|
|
||||||
break;
|
|
||||||
|
|
||||||
networkGlobals->ipid = TCPIPLogin(networkGlobals->initParams.userId, networkGlobals->domainNameResolution.DNRIPaddress, networkGlobals->initParams.scorePort, 0, 64);
|
|
||||||
if (toolerror()) {
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR;
|
|
||||||
networkGlobals->errorCode = toolerror();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
networkGlobals->errorCode = TCPIPOpenTCP(networkGlobals->ipid);
|
|
||||||
if (networkGlobals->errorCode != tcperrOK) {
|
|
||||||
TCPIPLogout(networkGlobals->ipid);
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_WAITING_FOR_TCP;
|
|
||||||
networkGlobals->timeout = TCP_CONNECT_TIMEOUT;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GAME_NETWORK_WAITING_FOR_TCP:
|
|
||||||
networkGlobals->errorCode = TCPIPStatusTCP(networkGlobals->ipid, &(networkGlobals->tcpStatus));
|
|
||||||
if (networkGlobals->errorCode != tcperrOK) {
|
|
||||||
abortConnection();
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ((networkGlobals->tcpStatus.srState == TCPSSYNSENT) ||
|
|
||||||
(networkGlobals->tcpStatus.srState == TCPSSYNRCVD)) {
|
|
||||||
if (networkGlobals->timeout > 0) {
|
|
||||||
networkGlobals->timeout--;
|
|
||||||
} else {
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
|
|
||||||
networkGlobals->errorCode = TCP_CONNECT_TIMEOUT_ERROR;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (networkGlobals->tcpStatus.srState != TCPSESTABLISHED) {
|
|
||||||
abortConnection();
|
|
||||||
networkGlobals->errorCode = networkGlobals->tcpStatus.srState | 0x8000;
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_WAITING_FOR_HELLO;
|
|
||||||
networkGlobals->timeout = READ_NETWORK_TIMEOUT;
|
|
||||||
networkGlobals->bytesRead = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GAME_NETWORK_WAITING_FOR_HELLO:
|
|
||||||
networkGlobals->errorCode = TCPIPReadTCP(networkGlobals->ipid, 0,
|
|
||||||
((uint32_t)(&(networkGlobals->helloResponse))) + networkGlobals->bytesRead,
|
|
||||||
sizeof(networkGlobals->helloResponse) - networkGlobals->bytesRead,
|
|
||||||
&(networkGlobals->readResponseBuf));
|
|
||||||
if (networkGlobals->errorCode != tcperrOK) {
|
|
||||||
abortConnection();
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
networkGlobals->bytesRead += networkGlobals->readResponseBuf.rrBuffCount;
|
|
||||||
if (networkGlobals->bytesRead < sizeof(networkGlobals->helloResponse)) {
|
|
||||||
if (networkGlobals->timeout > 0) {
|
|
||||||
networkGlobals->timeout--;
|
|
||||||
} else {
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
|
|
||||||
networkGlobals->errorCode = HELLO_TIMEOUT_ERROR;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (networkGlobals->bytesRead > sizeof(networkGlobals->helloResponse)) {
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
|
|
||||||
networkGlobals->errorCode = HELLO_TOO_BIG_ERROR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (networkGlobals->helloResponse.responseType != RESPONSE_TYPE_HELLO) {
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
|
|
||||||
networkGlobals->errorCode = HELLO_UNEXPECTED_RESPONSE_ERROR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
networkGlobals->secrets[2] = networkGlobals->helloResponse.nonce;
|
|
||||||
if (networkGlobals->hasHighScoreToSend) {
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_SET_HIGH_SCORE;
|
|
||||||
} else if ((!hasGlobalHighScores) ||
|
|
||||||
(globalScoreAge == 0)) {
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_REQUEST_SCORES;
|
|
||||||
} else {
|
|
||||||
TCPIPCloseTCP(networkGlobals->ipid);
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_CLOSING_TCP;
|
|
||||||
networkGlobals->timeout = SHUTDOWN_NETWORK_TIMEOUT;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GAME_NETWORK_REQUEST_SCORES:
|
|
||||||
networkGlobals->highScoreRequest.highScoreRequest.requestType = REQUEST_TYPE_GET_HIGH_SCORES;
|
|
||||||
|
|
||||||
md5Init(&(networkGlobals->hashWorkBlock));
|
|
||||||
md5Append(&(networkGlobals->hashWorkBlock), (Pointer)&(networkGlobals->secrets), sizeof(networkGlobals->secrets));
|
|
||||||
md5Append(&(networkGlobals->hashWorkBlock), (Pointer)&(networkGlobals->highScoreRequest.highScoreRequest), sizeof(networkGlobals->highScoreRequest.highScoreRequest));
|
|
||||||
md5Finish(&(networkGlobals->hashWorkBlock), &(networkGlobals->highScoreRequest.md5Digest[0]));
|
|
||||||
|
|
||||||
networkGlobals->errorCode = TCPIPWriteTCP(networkGlobals->ipid, (Pointer)&(networkGlobals->highScoreRequest), sizeof(networkGlobals->highScoreRequest), FALSE, FALSE);
|
|
||||||
if (networkGlobals->errorCode != tcperrOK) {
|
|
||||||
abortConnection();
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_WAITING_FOR_SCORES;
|
|
||||||
networkGlobals->timeout = READ_NETWORK_TIMEOUT;
|
|
||||||
networkGlobals->bytesRead = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GAME_NETWORK_WAITING_FOR_SCORES:
|
|
||||||
networkGlobals->errorCode = TCPIPReadTCP(networkGlobals->ipid, 0,
|
|
||||||
((uint32_t)(&highScoreResponse)) + networkGlobals->bytesRead,
|
|
||||||
sizeof(highScoreResponse) - networkGlobals->bytesRead,
|
|
||||||
&(networkGlobals->readResponseBuf));
|
|
||||||
if (networkGlobals->errorCode != tcperrOK) {
|
|
||||||
abortConnection();
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
networkGlobals->bytesRead += networkGlobals->readResponseBuf.rrBuffCount;
|
|
||||||
if (networkGlobals->bytesRead < sizeof(highScoreResponse)) {
|
|
||||||
if (networkGlobals->timeout > 0) {
|
|
||||||
networkGlobals->timeout--;
|
|
||||||
} else {
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
|
|
||||||
networkGlobals->errorCode = HIGH_SCORE_TIMEOUT_ERROR;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (networkGlobals->bytesRead > sizeof(highScoreResponse)) {
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
|
|
||||||
networkGlobals->errorCode = HIGH_SCORE_TOO_BIG_ERROR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (highScoreResponse.responseType != RESPONSE_TYPE_SCORES) {
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
|
|
||||||
networkGlobals->errorCode = HIGH_SCORE_UNEXPECTED_RESPONSE_ERROR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
globalScoreAge = GLOBAL_SCORE_REFRESH_TIME;
|
|
||||||
hasGlobalHighScores = TRUE;
|
|
||||||
|
|
||||||
TCPIPCloseTCP(networkGlobals->ipid);
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_CLOSING_TCP;
|
|
||||||
networkGlobals->timeout = SHUTDOWN_NETWORK_TIMEOUT;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GAME_NETWORK_SET_HIGH_SCORE:
|
|
||||||
setHighScoreRequest.setHighScoreRequest.requestType = REQUEST_TYPE_SET_SCORE;
|
|
||||||
setHighScoreRequest.setHighScoreRequest.who[3] = '\0';
|
|
||||||
|
|
||||||
md5Init(&(networkGlobals->hashWorkBlock));
|
|
||||||
md5Append(&(networkGlobals->hashWorkBlock), (Pointer)&(networkGlobals->secrets), sizeof(networkGlobals->secrets));
|
|
||||||
md5Append(&(networkGlobals->hashWorkBlock), (Pointer)&(setHighScoreRequest.setHighScoreRequest), sizeof(setHighScoreRequest.setHighScoreRequest));
|
|
||||||
md5Finish(&(networkGlobals->hashWorkBlock), &(setHighScoreRequest.md5Digest[0]));
|
|
||||||
|
|
||||||
networkGlobals->errorCode = TCPIPWriteTCP(networkGlobals->ipid, (Pointer)&setHighScoreRequest, sizeof(setHighScoreRequest), FALSE, FALSE);
|
|
||||||
if (networkGlobals->errorCode != tcperrOK) {
|
|
||||||
abortConnection();
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_WAITING_FOR_SCORE_ACK;
|
|
||||||
networkGlobals->timeout = READ_NETWORK_TIMEOUT;
|
|
||||||
networkGlobals->bytesRead = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GAME_NETWORK_WAITING_FOR_SCORE_ACK:
|
|
||||||
networkGlobals->errorCode = TCPIPReadTCP(networkGlobals->ipid, 0,
|
|
||||||
((uint32_t)(&(networkGlobals->setHighScoreResponse))) + networkGlobals->bytesRead,
|
|
||||||
sizeof(networkGlobals->setHighScoreResponse) - networkGlobals->bytesRead,
|
|
||||||
&(networkGlobals->readResponseBuf));
|
|
||||||
if (networkGlobals->errorCode != tcperrOK) {
|
|
||||||
abortConnection();
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
networkGlobals->bytesRead += networkGlobals->readResponseBuf.rrBuffCount;
|
|
||||||
if (networkGlobals->bytesRead < sizeof(networkGlobals->setHighScoreResponse)) {
|
|
||||||
if (networkGlobals->timeout > 0) {
|
|
||||||
networkGlobals->timeout--;
|
|
||||||
} else {
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
|
|
||||||
networkGlobals->errorCode = SET_SCORE_TIMEOUT_ERROR;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (networkGlobals->bytesRead > sizeof(networkGlobals->setHighScoreResponse)) {
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
|
|
||||||
networkGlobals->errorCode = SET_SCORE_TOO_BIG_ERROR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (networkGlobals->setHighScoreResponse.responseType != RESPONSE_TYPE_STATUS) {
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
|
|
||||||
networkGlobals->errorCode = SET_SCORE_UNEXPECTED_RESPONSE_ERROR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!networkGlobals->setHighScoreResponse.success) {
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
|
|
||||||
networkGlobals->errorCode = SET_SCORE_FAILED_ERROR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
networkGlobals->hasHighScoreToSend = FALSE;
|
|
||||||
globalScoreAge = 0;
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_REQUEST_SCORES;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case GAME_NETWORK_CLOSING_TCP:
|
|
||||||
networkGlobals->errorCode = TCPIPStatusTCP(networkGlobals->ipid, &(networkGlobals->tcpStatus));
|
|
||||||
if ((networkGlobals->tcpStatus.srState != TCPSCLOSED) &&
|
|
||||||
(networkGlobals->tcpStatus.srState != TCPSTIMEWAIT)) {
|
|
||||||
if (networkGlobals->timeout > 0) {
|
|
||||||
networkGlobals->timeout--;
|
|
||||||
} else {
|
|
||||||
abortConnection();
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_TCP_UNCONNECTED;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
TCPIPLogout(networkGlobals->ipid);
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_TCP_UNCONNECTED;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BOOLEAN canSendHighScore(void)
|
|
||||||
{
|
|
||||||
if (networkGlobals == NULL)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
if (networkGlobals->gameNetworkState < GAME_NETWORK_TCP_UNCONNECTED) {
|
|
||||||
if ((networkGlobals->gameNetworkState == GAME_NETWORK_FAILURE) &&
|
|
||||||
(networkGlobals->timeout > 0))
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOLEAN sendHighScore(void)
|
|
||||||
{
|
|
||||||
uint16_t cycleCount = 0;
|
|
||||||
|
|
||||||
networkGlobals->hasHighScoreToSend = TRUE;
|
|
||||||
|
|
||||||
if (networkGlobals->gameNetworkState < GAME_NETWORK_TCP_UNCONNECTED)
|
|
||||||
networkGlobals->gameNetworkState = GAME_NETWORK_TCP_UNCONNECTED;
|
|
||||||
|
|
||||||
do {
|
|
||||||
networkGlobals->initParams.waitForVbl();
|
|
||||||
pollNetwork();
|
|
||||||
cycleCount++;
|
|
||||||
|
|
||||||
if ((cycleCount & 0x7) == 0) {
|
|
||||||
switch (cycleCount & 0x18) {
|
|
||||||
case 0x00:
|
|
||||||
if (networkGlobals->initParams.uploadSpin != NULL)
|
|
||||||
networkGlobals->initParams.uploadSpin(0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x08:
|
|
||||||
if (networkGlobals->initParams.uploadSpin != NULL)
|
|
||||||
networkGlobals->initParams.uploadSpin(1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x10:
|
|
||||||
if (networkGlobals->initParams.uploadSpin != NULL)
|
|
||||||
networkGlobals->initParams.uploadSpin(2);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x18:
|
|
||||||
if (networkGlobals->initParams.uploadSpin != NULL)
|
|
||||||
networkGlobals->initParams.uploadSpin(3);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (networkGlobals->gameNetworkState > GAME_NETWORK_TCP_UNCONNECTED);
|
|
||||||
|
|
||||||
if (networkGlobals->gameNetworkState != GAME_NETWORK_TCP_UNCONNECTED)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
if (networkGlobals->initParams.scorePosition != NULL)
|
|
||||||
networkGlobals->initParams.scorePosition(networkGlobals->setHighScoreResponse.position,
|
|
||||||
networkGlobals->setHighScoreResponse.numberOfScores);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
|
@ -195,7 +195,6 @@ collisionAddr dc i2'0'
|
||||||
numSegments dc i2'0'
|
numSegments dc i2'0'
|
||||||
displayGlobalHighScores dc i2'0'
|
displayGlobalHighScores dc i2'0'
|
||||||
shouldQuit dc i2'1'
|
shouldQuit dc i2'1'
|
||||||
scoreIndex dc i2'0'
|
|
||||||
|
|
||||||
|
|
||||||
tileJumpTable dc a4'solid0'
|
tileJumpTable dc a4'solid0'
|
||||||
|
|
|
@ -14,13 +14,16 @@
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if __ORCAC__
|
||||||
segment "loadSounds";
|
segment "loadSounds";
|
||||||
|
#endif
|
||||||
|
|
||||||
static void loadSound(Word addr, Word soundNum)
|
static void loadSound(Word addr, Word soundNum)
|
||||||
{
|
{
|
||||||
Handle handle = LoadResource(rRawSound, soundNum);
|
Handle handle = LoadResource(rRawSound, soundNum);
|
||||||
HLock(handle);
|
HLock(handle);
|
||||||
WriteRamBlock(*handle, addr, GetHandleSize(handle));
|
WriteRamBlock(*handle, addr, (Word)GetHandleSize(handle));
|
||||||
HUnlock(handle);
|
HUnlock(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
#define _GUARD_PROJECTBuGS_FILEloadSounds_
|
#define _GUARD_PROJECTBuGS_FILEloadSounds_
|
||||||
|
|
||||||
|
|
||||||
#include <types.h>
|
#include <TYPES.h>
|
||||||
|
|
||||||
|
|
||||||
extern void loadSpiderSound(Word addr);
|
extern void loadSpiderSound(Word addr);
|
||||||
|
|
145
BuGS/main.c
145
BuGS/main.c
|
@ -7,23 +7,33 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include <orca.h>
|
||||||
#include <Memory.h>
|
#include <Memory.h>
|
||||||
#include <Locator.h>
|
#include <Locator.h>
|
||||||
#include <MiscTool.h>
|
#include <MiscTool.h>
|
||||||
|
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
#include "globalScores.h"
|
#include "netScores.h"
|
||||||
|
#include "settings.h"
|
||||||
#include "tileData.h"
|
#include "tileData.h"
|
||||||
|
|
||||||
|
|
||||||
/* Defines and macros */
|
/* Defines and macros */
|
||||||
|
|
||||||
|
#define GLOBAL_SCORE_REFRESH_TIME (15 * 60 * 60)
|
||||||
|
#define SHUTDOWN_NETWORK_TIMEOUT (2 * 60)
|
||||||
|
#define TCP_CONNECT_TIMEOUT (8 * 60)
|
||||||
|
#define READ_NETWORK_TIMEOUT (5 * 60)
|
||||||
|
#define NETWORK_RETRY_TIMEOUT (3 * 60 * 60)
|
||||||
|
|
||||||
#define TOOLFAIL(string) \
|
#define TOOLFAIL(string) \
|
||||||
if (toolerror()) SysFailMgr(toolerror(), "\p" string "\n\r Error Code -> $");
|
if (toolerror()) SysFailMgr(toolerror(), (Pointer)"\p" string "\n\r Error Code -> $");
|
||||||
|
|
||||||
|
|
||||||
/* Globals */
|
/* Globals */
|
||||||
|
@ -34,6 +44,11 @@ unsigned int randomSeed;
|
||||||
// This symbol is used also from assembly directly so be careful with it...
|
// This symbol is used also from assembly directly so be careful with it...
|
||||||
char globalScoreInfo[GAME_NUM_TILES_WIDE + 1];
|
char globalScoreInfo[GAME_NUM_TILES_WIDE + 1];
|
||||||
|
|
||||||
|
tNSGSHighScores globalHighScores;
|
||||||
|
Boolean hasGlobalHighScores = FALSE;
|
||||||
|
Word globalScoreAge = 0;
|
||||||
|
unsigned int scoreIndex = 0;
|
||||||
|
|
||||||
|
|
||||||
/* Implementation */
|
/* Implementation */
|
||||||
|
|
||||||
|
@ -46,7 +61,7 @@ word randomMushroomOffset(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void uploadSpin(int val)
|
static void uploadSpin(int val)
|
||||||
{
|
{
|
||||||
switch (val)
|
switch (val)
|
||||||
{
|
{
|
||||||
|
@ -69,12 +84,12 @@ void uploadSpin(int val)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void scorePosition(unsigned int position, unsigned int numberOfScores)
|
static void scorePosition(unsigned int position, unsigned int numberOfScores)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
sprintf(globalScoreInfo, " %u OF %u SCORES", position, numberOfScores);
|
sprintf(globalScoreInfo, " %u OF %u SCORES", position, numberOfScores);
|
||||||
for (i = strlen(globalScoreInfo); i < sizeof(globalScoreInfo); i++) {
|
for (i = (int)strlen(globalScoreInfo); i < sizeof(globalScoreInfo); i++) {
|
||||||
globalScoreInfo[i] = ' ';
|
globalScoreInfo[i] = ' ';
|
||||||
}
|
}
|
||||||
globalScoreInfo[GAME_NUM_TILES_WIDE] = '\0';
|
globalScoreInfo[GAME_NUM_TILES_WIDE] = '\0';
|
||||||
|
@ -83,19 +98,121 @@ void scorePosition(unsigned int position, unsigned int numberOfScores)
|
||||||
for (i = 6 * 60; i > 0; i--) {
|
for (i = 6 * 60; i > 0; i--) {
|
||||||
waitForVbl();
|
waitForVbl();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
globalScoreAge = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void showConnectionString(BOOLEAN display)
|
static void showConnectionString(BOOLEAN display)
|
||||||
{
|
{
|
||||||
if (display)
|
if (display)
|
||||||
displayConnectionString();
|
displayConnectionString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char hexDigitToAscii(Word digit)
|
||||||
|
{
|
||||||
|
digit &= 0xf;
|
||||||
|
if (digit < 10)
|
||||||
|
return '0' + digit;
|
||||||
|
|
||||||
|
if (digit > 15)
|
||||||
|
return 'X';
|
||||||
|
|
||||||
|
return 'A' + digit - 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void displayString(Word row, char * string)
|
||||||
|
{
|
||||||
|
strcpy(&(globalHighScores.score[row].scoreText[2]), string);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void displayNetworkError(char * line1, char * line2, unsigned int errorCode)
|
||||||
|
{
|
||||||
|
Word row;
|
||||||
|
Word column;
|
||||||
|
|
||||||
|
for (row = 0; row < sizeof(globalHighScores.score) / sizeof(globalHighScores.score[0]); row++) {
|
||||||
|
for (column = 0;
|
||||||
|
column < sizeof(globalHighScores.score[0].scoreText) / sizeof(globalHighScores.score[0].scoreText[0]);
|
||||||
|
column++) {
|
||||||
|
globalHighScores.score[row].scoreText[column] = ' ';
|
||||||
|
}
|
||||||
|
for (column = 0;
|
||||||
|
column < sizeof(globalHighScores.score[0].who) / sizeof(globalHighScores.score[0].who[0]);
|
||||||
|
column++) {
|
||||||
|
globalHighScores.score[row].who[column] = ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
displayString(1, "NETWORK");
|
||||||
|
displayString(2, "PROBLEM");
|
||||||
|
|
||||||
|
displayString(4, line1);
|
||||||
|
displayString(5, line2);
|
||||||
|
|
||||||
|
globalHighScores.score[7].scoreText[0] = 'C';
|
||||||
|
globalHighScores.score[7].scoreText[1] = 'O';
|
||||||
|
globalHighScores.score[7].scoreText[2] = 'D';
|
||||||
|
globalHighScores.score[7].scoreText[3] = 'E';
|
||||||
|
globalHighScores.score[7].scoreText[4] = ':';
|
||||||
|
globalHighScores.score[7].scoreText[5] = ' ';
|
||||||
|
globalHighScores.score[7].scoreText[6] = hexDigitToAscii(errorCode >> 12);
|
||||||
|
globalHighScores.score[7].scoreText[7] = hexDigitToAscii(errorCode >> 8);
|
||||||
|
globalHighScores.score[7].scoreText[8] = hexDigitToAscii(errorCode >> 4);
|
||||||
|
globalHighScores.score[7].scoreText[9] = hexDigitToAscii(errorCode);
|
||||||
|
|
||||||
|
hasGlobalHighScores = TRUE;
|
||||||
|
globalScoreAge = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void displayError(tNSGSErrorType errorType, unsigned int errorCode)
|
||||||
|
{
|
||||||
|
switch (errorType) {
|
||||||
|
case NSGS_CONNECT_ERROR:
|
||||||
|
displayNetworkError("CONNECT", "FAILED", errorCode);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NSGS_LOOKUP_ERROR:
|
||||||
|
displayNetworkError("LOOKUP", "FAILED", errorCode);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NSGS_SOCKET_ERROR:
|
||||||
|
displayNetworkError("SOCKET", "ERROR", errorCode);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NSGS_PROTOCOL_ERROR:
|
||||||
|
displayNetworkError("PROTOCOL", "FAILED", errorCode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void setHighScores(const tNSGSHighScores * highScores)
|
||||||
|
{
|
||||||
|
memcpy(&globalHighScores, highScores, sizeof(globalHighScores));
|
||||||
|
hasGlobalHighScores = TRUE;
|
||||||
|
globalScoreAge = GLOBAL_SCORE_REFRESH_TIME;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static BOOLEAN shouldRefreshHighScores(void)
|
||||||
|
{
|
||||||
|
return globalScoreAge == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOLEAN sendHighScore(void)
|
||||||
|
{
|
||||||
|
const tNSGSHighScore * highScore = getHighScore(scoreIndex / sizeof(tNSGSHighScore));
|
||||||
|
return NSGS_SendHighScore(highScore->who, highScore->score);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
static tHighScoreInitParams highScoreInitParams;
|
static tNSGSHighScoreInitParams highScoreInitParams;
|
||||||
int event;
|
int event;
|
||||||
Ref toolStartupRef;
|
Ref toolStartupRef;
|
||||||
|
|
||||||
|
@ -124,24 +241,30 @@ int main(void)
|
||||||
SetMouse(transparent);
|
SetMouse(transparent);
|
||||||
|
|
||||||
highScoreInitParams.userId = myUserId;
|
highScoreInitParams.userId = myUserId;
|
||||||
highScoreInitParams.scoreServer = "\p" NETWORK_SERVER;
|
highScoreInitParams.scoreServer = (const char *)"\p" NETWORK_SERVER;
|
||||||
highScoreInitParams.scorePort = NETWORK_SERVERPORT;
|
highScoreInitParams.scorePort = NETWORK_SERVERPORT;
|
||||||
highScoreInitParams.secret1 = NETWORK_SERVERSECRET1;
|
highScoreInitParams.secret1 = NETWORK_SERVERSECRET1;
|
||||||
highScoreInitParams.secret2 = NETWORK_SERVERSECRET2;
|
highScoreInitParams.secret2 = NETWORK_SERVERSECRET2;
|
||||||
|
highScoreInitParams.shutdownTimeout = SHUTDOWN_NETWORK_TIMEOUT;
|
||||||
|
highScoreInitParams.connectTimeout = TCP_CONNECT_TIMEOUT;
|
||||||
|
highScoreInitParams.readTimeout = READ_NETWORK_TIMEOUT;
|
||||||
|
highScoreInitParams.retryTimeout = NETWORK_RETRY_TIMEOUT;
|
||||||
|
|
||||||
highScoreInitParams.displayConnectionString = showConnectionString;
|
highScoreInitParams.displayConnectionString = showConnectionString;
|
||||||
highScoreInitParams.waitForVbl = waitForVbl;
|
highScoreInitParams.waitForVbl = waitForVbl;
|
||||||
highScoreInitParams.uploadSpin = uploadSpin;
|
highScoreInitParams.uploadSpin = uploadSpin;
|
||||||
highScoreInitParams.scorePosition = scorePosition;
|
highScoreInitParams.scorePosition = scorePosition;
|
||||||
|
highScoreInitParams.displayError = displayError;
|
||||||
|
highScoreInitParams.setHighScores = setHighScores;
|
||||||
|
|
||||||
initNetwork(&highScoreInitParams);
|
NSGS_InitNetwork(&highScoreInitParams);
|
||||||
|
|
||||||
if (!loadSettings())
|
if (!loadSettings())
|
||||||
saveSettings();
|
saveSettings();
|
||||||
|
|
||||||
game();
|
game();
|
||||||
|
|
||||||
shutdownNetwork();
|
NSGS_ShutdownNetwork();
|
||||||
|
|
||||||
ShutDownTools(refIsHandle, toolStartupRef);
|
ShutDownTools(refIsHandle, toolStartupRef);
|
||||||
TOOLFAIL("Unable to shutdown tools");
|
TOOLFAIL("Unable to shutdown tools");
|
||||||
|
|
|
@ -0,0 +1,745 @@
|
||||||
|
/*
|
||||||
|
* netScores.c
|
||||||
|
* NetScoresGS
|
||||||
|
*
|
||||||
|
* Created by Jeremy Rand on 2021-05-23.
|
||||||
|
* Copyright © 2021 Jeremy Rand. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <Hash.h>
|
||||||
|
#include <locator.h>
|
||||||
|
#include <misctool.h>
|
||||||
|
#include <orca.h>
|
||||||
|
#include <tcpip.h>
|
||||||
|
|
||||||
|
#include "netScores.h"
|
||||||
|
|
||||||
|
|
||||||
|
// Defines
|
||||||
|
|
||||||
|
#define REQUEST_TYPE_GET_HIGH_SCORES 0
|
||||||
|
#define REQUEST_TYPE_SET_SCORE 1
|
||||||
|
|
||||||
|
#define RESPONSE_TYPE_HELLO 0
|
||||||
|
#define RESPONSE_TYPE_SCORES 1
|
||||||
|
#define RESPONSE_TYPE_STATUS 2
|
||||||
|
|
||||||
|
#define DEFAULT_SHUTDOWN_NETWORK_TIMEOUT (2 * 60)
|
||||||
|
#define DEFAULT_TCP_CONNECT_TIMEOUT (8 * 60)
|
||||||
|
#define DEFAULT_READ_NETWORK_TIMEOUT (5 * 60)
|
||||||
|
#define DEFAULT_NETWORK_RETRY_TIMEOUT (3 * 60 * 60)
|
||||||
|
|
||||||
|
|
||||||
|
// Types
|
||||||
|
|
||||||
|
typedef struct tSessionSecrets {
|
||||||
|
uint32_t secret;
|
||||||
|
uint32_t nonce;
|
||||||
|
} tSessionSecrets;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct tHighScoreRequest {
|
||||||
|
uint16_t requestType;
|
||||||
|
} tHighScoreRequest;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct tHighScoreRequestWithHash {
|
||||||
|
tHighScoreRequest highScoreRequest;
|
||||||
|
uint8_t md5Digest[16];
|
||||||
|
} tHighScoreRequestWithHash;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct tSetHighScoreRequest {
|
||||||
|
uint16_t requestType;
|
||||||
|
char who[4];
|
||||||
|
uint32_t score;
|
||||||
|
Word is60Hz;
|
||||||
|
} tSetHighScoreRequest;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct tSetHighScoreRequestWithHash {
|
||||||
|
tSetHighScoreRequest setHighScoreRequest;
|
||||||
|
uint8_t md5Digest[16];
|
||||||
|
} tSetHighScoreRequestWithHash;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct tHelloResponse {
|
||||||
|
uint16_t responseType;
|
||||||
|
uint32_t nonce;
|
||||||
|
} tHelloResponse;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct tScoresResponse {
|
||||||
|
uint16_t responseType;
|
||||||
|
tNSGSHighScores highScores;
|
||||||
|
} tScoresResponse;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct tStatusResponse {
|
||||||
|
uint16_t responseType;
|
||||||
|
Boolean success;
|
||||||
|
uint16_t position;
|
||||||
|
uint16_t numberOfScores;
|
||||||
|
} tStatusResponse;
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum tGameNetworkState {
|
||||||
|
GAME_NETWORK_CONNECT_FAILED = 0,
|
||||||
|
GAME_NETWORK_UNCONNECTED,
|
||||||
|
|
||||||
|
/* All states below this should have Marinetti disconnected */
|
||||||
|
GAME_NETWORK_CONNECTED,
|
||||||
|
GAME_NETWORK_RESOLVING_NAME,
|
||||||
|
|
||||||
|
/* These are all of the error states. Marinetti is still connected but the
|
||||||
|
TCP connection is closed and ipid released. */
|
||||||
|
GAME_NETWORK_LOOKUP_FAILED,
|
||||||
|
GAME_NETWORK_SOCKET_ERROR,
|
||||||
|
GAME_NETWORK_PROTOCOL_FAILED,
|
||||||
|
GAME_NETWORK_FAILURE,
|
||||||
|
|
||||||
|
/* This is the state we are in during a game on a machine with a working network
|
||||||
|
(other possible states are fail states). */
|
||||||
|
GAME_NETWORK_TCP_UNCONNECTED,
|
||||||
|
|
||||||
|
/* All of these states below here have an ipid open and the TCP connection is
|
||||||
|
open and in some state. */
|
||||||
|
GAME_NETWORK_WAITING_FOR_TCP,
|
||||||
|
|
||||||
|
/* All of these states below this point have the TCP connection established
|
||||||
|
and the score protocol is exchanging information. */
|
||||||
|
GAME_NETWORK_WAITING_FOR_HELLO,
|
||||||
|
GAME_NETWORK_REQUEST_SCORES,
|
||||||
|
GAME_NETWORK_WAITING_FOR_SCORES,
|
||||||
|
GAME_NETWORK_SET_HIGH_SCORE,
|
||||||
|
GAME_NETWORK_WAITING_FOR_SCORE_ACK,
|
||||||
|
|
||||||
|
GAME_NETWORK_CLOSING_TCP,
|
||||||
|
|
||||||
|
NUM_GAME_NETWORK_STATES
|
||||||
|
} tGameNetworkState;
|
||||||
|
|
||||||
|
typedef void (*tGameNetworkStateHandler)(void);
|
||||||
|
|
||||||
|
typedef struct tGameNetworkGlobals {
|
||||||
|
Boolean networkStartedConnected;
|
||||||
|
tNSGSHighScoreInitParams initParams;
|
||||||
|
tGameNetworkState gameNetworkState;
|
||||||
|
dnrBuffer domainNameResolution;
|
||||||
|
srBuff tcpStatus;
|
||||||
|
Word ipid;
|
||||||
|
rrBuff readResponseBuf;
|
||||||
|
tHelloResponse helloResponse;
|
||||||
|
uint32_t bytesRead;
|
||||||
|
md5WorkBlock hashWorkBlock;
|
||||||
|
uint32_t secrets[3];
|
||||||
|
tHighScoreRequestWithHash highScoreRequest;
|
||||||
|
tScoresResponse highScoreResponse;
|
||||||
|
Boolean hasHighScoreToSend;
|
||||||
|
tSetHighScoreRequestWithHash setHighScoreRequest;
|
||||||
|
tStatusResponse setHighScoreResponse;
|
||||||
|
uint16_t errorCode;
|
||||||
|
uint16_t timeout;
|
||||||
|
Boolean hasGlobalHighScores;
|
||||||
|
} tGameNetworkGlobals;
|
||||||
|
|
||||||
|
// Forward declarations
|
||||||
|
|
||||||
|
static void handleConnectFailed(void);
|
||||||
|
static void handleUnconnected(void);
|
||||||
|
static void handleConnected(void);
|
||||||
|
static void handleResolvingName(void);
|
||||||
|
static void handleLookupFailed(void);
|
||||||
|
static void handleSocketError(void);
|
||||||
|
static void handleProtocolFailed(void);
|
||||||
|
static void handleFailure(void);
|
||||||
|
static void handleTcpUnconnected(void);
|
||||||
|
static void handleWaitingForTcp(void);
|
||||||
|
static void handleWaitingForHello(void);
|
||||||
|
static void handleRequestScores(void);
|
||||||
|
static void handleWaitingForScores(void);
|
||||||
|
static void handleSetHighScore(void);
|
||||||
|
static void handleWaitingForScoreAck(void);
|
||||||
|
static void handleClosingTcp(void);
|
||||||
|
|
||||||
|
// Globals
|
||||||
|
|
||||||
|
#if __ORCAC__
|
||||||
|
segment "highscores";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static tGameNetworkStateHandler handlers[NUM_GAME_NETWORK_STATES] = {
|
||||||
|
handleConnectFailed,
|
||||||
|
handleUnconnected,
|
||||||
|
|
||||||
|
handleConnected,
|
||||||
|
handleResolvingName,
|
||||||
|
|
||||||
|
handleLookupFailed,
|
||||||
|
handleSocketError,
|
||||||
|
handleProtocolFailed,
|
||||||
|
handleFailure,
|
||||||
|
|
||||||
|
handleTcpUnconnected,
|
||||||
|
|
||||||
|
handleWaitingForTcp,
|
||||||
|
|
||||||
|
handleWaitingForHello,
|
||||||
|
handleRequestScores,
|
||||||
|
handleWaitingForScores,
|
||||||
|
handleSetHighScore,
|
||||||
|
handleWaitingForScoreAck,
|
||||||
|
|
||||||
|
handleClosingTcp
|
||||||
|
};
|
||||||
|
|
||||||
|
// I am running out of space in the main segment so I am moving these globals into
|
||||||
|
// a dynamically allocated struct. It is only allocated if network capabilities are
|
||||||
|
// detected.
|
||||||
|
static tGameNetworkGlobals * networkGlobals = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
// Implementation
|
||||||
|
|
||||||
|
void NSGS_InitNetwork(tNSGSHighScoreInitParams * params)
|
||||||
|
{
|
||||||
|
networkGlobals = NULL;
|
||||||
|
|
||||||
|
if ((params->scoreServer == NULL) ||
|
||||||
|
(params->scorePort == 0) ||
|
||||||
|
(params->waitForVbl == NULL))
|
||||||
|
return;
|
||||||
|
|
||||||
|
LoadOneTool(54, 0x200); // Load Marinetti
|
||||||
|
if (toolerror())
|
||||||
|
return;
|
||||||
|
|
||||||
|
LoadOneTool(128, 0x103); // Load the Hash toolset
|
||||||
|
if (toolerror()) {
|
||||||
|
UnloadOneTool(54);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TCPIPStartUp();
|
||||||
|
if (toolerror()) {
|
||||||
|
UnloadOneTool(128);
|
||||||
|
UnloadOneTool(54);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hashStartUp();
|
||||||
|
if (toolerror()) {
|
||||||
|
TCPIPShutDown();
|
||||||
|
UnloadOneTool(128);
|
||||||
|
UnloadOneTool(54);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
networkGlobals = malloc(sizeof(tGameNetworkGlobals));
|
||||||
|
if (networkGlobals == NULL) {
|
||||||
|
hashShutDown();
|
||||||
|
TCPIPShutDown();
|
||||||
|
UnloadOneTool(128);
|
||||||
|
UnloadOneTool(54);
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&(networkGlobals->initParams), params, sizeof(networkGlobals->initParams));
|
||||||
|
|
||||||
|
if (networkGlobals->initParams.shutdownTimeout == 0)
|
||||||
|
networkGlobals->initParams.shutdownTimeout = DEFAULT_SHUTDOWN_NETWORK_TIMEOUT;
|
||||||
|
if (networkGlobals->initParams.connectTimeout == 0)
|
||||||
|
networkGlobals->initParams.connectTimeout = DEFAULT_TCP_CONNECT_TIMEOUT;
|
||||||
|
if (networkGlobals->initParams.readTimeout == 0)
|
||||||
|
networkGlobals->initParams.readTimeout = DEFAULT_READ_NETWORK_TIMEOUT;
|
||||||
|
if (networkGlobals->initParams.retryTimeout == 0)
|
||||||
|
networkGlobals->initParams.retryTimeout = DEFAULT_NETWORK_RETRY_TIMEOUT;
|
||||||
|
|
||||||
|
networkGlobals->networkStartedConnected = TCPIPGetConnectStatus();
|
||||||
|
if (networkGlobals->networkStartedConnected) {
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_CONNECTED;
|
||||||
|
} else {
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_UNCONNECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
networkGlobals->secrets[0] = params->secret1;
|
||||||
|
networkGlobals->secrets[1] = params->secret2;
|
||||||
|
|
||||||
|
networkGlobals->hasHighScoreToSend = FALSE;
|
||||||
|
networkGlobals->hasGlobalHighScores = FALSE;
|
||||||
|
|
||||||
|
networkGlobals->setHighScoreRequest.setHighScoreRequest.is60Hz = !ReadBParam(hrtz50or60);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void NSGS_ShutdownNetwork(void)
|
||||||
|
{
|
||||||
|
if ((!networkGlobals->networkStartedConnected) &&
|
||||||
|
(networkGlobals->gameNetworkState > GAME_NETWORK_UNCONNECTED)) {
|
||||||
|
TCPIPDisconnect(TRUE, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(networkGlobals);
|
||||||
|
|
||||||
|
hashShutDown();
|
||||||
|
TCPIPShutDown();
|
||||||
|
UnloadOneTool(128); // Unload the Hash toolset
|
||||||
|
UnloadOneTool(54); // Unload Marinetti
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void abortConnection(void)
|
||||||
|
{
|
||||||
|
TCPIPAbortTCP(networkGlobals->ipid);
|
||||||
|
TCPIPLogout(networkGlobals->ipid);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void NSGS_DisconnectNetwork(void)
|
||||||
|
{
|
||||||
|
if (networkGlobals == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (networkGlobals->gameNetworkState > GAME_NETWORK_TCP_UNCONNECTED) {
|
||||||
|
if (networkGlobals->gameNetworkState < GAME_NETWORK_CLOSING_TCP) {
|
||||||
|
TCPIPCloseTCP(networkGlobals->ipid);
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_CLOSING_TCP;
|
||||||
|
networkGlobals->timeout = networkGlobals->initParams.shutdownTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((networkGlobals->gameNetworkState != GAME_NETWORK_TCP_UNCONNECTED) &&
|
||||||
|
(networkGlobals->gameNetworkState != GAME_NETWORK_FAILURE)) {
|
||||||
|
networkGlobals->initParams.waitForVbl();
|
||||||
|
NSGS_PollNetwork();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void handleConnectFailed(void)
|
||||||
|
{
|
||||||
|
if (networkGlobals->initParams.displayError != NULL)
|
||||||
|
networkGlobals->initParams.displayError(NSGS_CONNECT_ERROR, networkGlobals->errorCode);
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handleUnconnected(void)
|
||||||
|
{
|
||||||
|
if (networkGlobals->initParams.displayConnectionString != NULL)
|
||||||
|
networkGlobals->initParams.displayConnectionString(TRUE);
|
||||||
|
TCPIPConnect(NULL);
|
||||||
|
if ((!toolerror()) &&
|
||||||
|
(TCPIPGetConnectStatus())) {
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_CONNECTED;
|
||||||
|
} else {
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_CONNECT_FAILED;
|
||||||
|
networkGlobals->errorCode = toolerror();
|
||||||
|
}
|
||||||
|
if (networkGlobals->initParams.displayConnectionString != NULL)
|
||||||
|
networkGlobals->initParams.displayConnectionString(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handleConnected(void)
|
||||||
|
{
|
||||||
|
TCPIPDNRNameToIP((char *)networkGlobals->initParams.scoreServer, &(networkGlobals->domainNameResolution));
|
||||||
|
if (toolerror()) {
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_LOOKUP_FAILED;
|
||||||
|
networkGlobals->errorCode = toolerror();
|
||||||
|
} else
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_RESOLVING_NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handleResolvingName(void)
|
||||||
|
{
|
||||||
|
if (networkGlobals->domainNameResolution.DNRstatus == DNR_Pending)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (networkGlobals->domainNameResolution.DNRstatus != DNR_OK) {
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_LOOKUP_FAILED;
|
||||||
|
networkGlobals->errorCode = networkGlobals->domainNameResolution.DNRstatus;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_TCP_UNCONNECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handleLookupFailed(void)
|
||||||
|
{
|
||||||
|
if (networkGlobals->initParams.displayError != NULL)
|
||||||
|
networkGlobals->initParams.displayError(NSGS_LOOKUP_ERROR, networkGlobals->errorCode);
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handleSocketError(void)
|
||||||
|
{
|
||||||
|
if (networkGlobals->initParams.displayError != NULL)
|
||||||
|
networkGlobals->initParams.displayError(NSGS_SOCKET_ERROR, networkGlobals->errorCode);
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_FAILURE;
|
||||||
|
networkGlobals->timeout = networkGlobals->initParams.retryTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handleProtocolFailed(void)
|
||||||
|
{
|
||||||
|
abortConnection();
|
||||||
|
if (networkGlobals->initParams.displayError != NULL)
|
||||||
|
networkGlobals->initParams.displayError(NSGS_PROTOCOL_ERROR, networkGlobals->errorCode);
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_FAILURE;
|
||||||
|
networkGlobals->timeout = networkGlobals->initParams.retryTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handleFailure(void)
|
||||||
|
{
|
||||||
|
// All of the different failure modes except protocol failure above end up here ultimately. And the state
|
||||||
|
// machine stays here once it arrives here.
|
||||||
|
if (networkGlobals->timeout > 0) {
|
||||||
|
networkGlobals->timeout--;
|
||||||
|
if (networkGlobals->timeout == 0)
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_TCP_UNCONNECTED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handleTcpUnconnected(void)
|
||||||
|
{
|
||||||
|
if ((networkGlobals->hasGlobalHighScores) &&
|
||||||
|
(!networkGlobals->hasHighScoreToSend)) {
|
||||||
|
if (networkGlobals->initParams.shouldRefreshHighScores == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!networkGlobals->initParams.shouldRefreshHighScores())
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
networkGlobals->ipid = TCPIPLogin(networkGlobals->initParams.userId, networkGlobals->domainNameResolution.DNRIPaddress, networkGlobals->initParams.scorePort, 0, 64);
|
||||||
|
if (toolerror()) {
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR;
|
||||||
|
networkGlobals->errorCode = toolerror();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
networkGlobals->errorCode = TCPIPOpenTCP(networkGlobals->ipid);
|
||||||
|
if (networkGlobals->errorCode != tcperrOK) {
|
||||||
|
TCPIPLogout(networkGlobals->ipid);
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_WAITING_FOR_TCP;
|
||||||
|
networkGlobals->timeout = networkGlobals->initParams.connectTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handleWaitingForTcp(void)
|
||||||
|
{
|
||||||
|
networkGlobals->errorCode = TCPIPStatusTCP(networkGlobals->ipid, &(networkGlobals->tcpStatus));
|
||||||
|
if (networkGlobals->errorCode != tcperrOK) {
|
||||||
|
abortConnection();
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((networkGlobals->tcpStatus.srState == TCPSSYNSENT) ||
|
||||||
|
(networkGlobals->tcpStatus.srState == TCPSSYNRCVD)) {
|
||||||
|
if (networkGlobals->timeout > 0) {
|
||||||
|
networkGlobals->timeout--;
|
||||||
|
} else {
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
|
||||||
|
networkGlobals->errorCode = NSGS_TCP_CONNECT_TIMEOUT_ERROR;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (networkGlobals->tcpStatus.srState != TCPSESTABLISHED) {
|
||||||
|
abortConnection();
|
||||||
|
networkGlobals->errorCode = networkGlobals->tcpStatus.srState | 0x8000;
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_WAITING_FOR_HELLO;
|
||||||
|
networkGlobals->timeout = networkGlobals->initParams.readTimeout;
|
||||||
|
networkGlobals->bytesRead = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handleWaitingForHello(void)
|
||||||
|
{
|
||||||
|
networkGlobals->errorCode = TCPIPReadTCP(networkGlobals->ipid, 0,
|
||||||
|
((uint32_t)(&(networkGlobals->helloResponse))) + networkGlobals->bytesRead,
|
||||||
|
sizeof(networkGlobals->helloResponse) - networkGlobals->bytesRead,
|
||||||
|
&(networkGlobals->readResponseBuf));
|
||||||
|
if (networkGlobals->errorCode != tcperrOK) {
|
||||||
|
abortConnection();
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
networkGlobals->bytesRead += networkGlobals->readResponseBuf.rrBuffCount;
|
||||||
|
if (networkGlobals->bytesRead < sizeof(networkGlobals->helloResponse)) {
|
||||||
|
if (networkGlobals->timeout > 0) {
|
||||||
|
networkGlobals->timeout--;
|
||||||
|
} else {
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
|
||||||
|
networkGlobals->errorCode = NSGS_HELLO_TIMEOUT_ERROR;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (networkGlobals->bytesRead > sizeof(networkGlobals->helloResponse)) {
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
|
||||||
|
networkGlobals->errorCode = NSGS_HELLO_TOO_BIG_ERROR;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (networkGlobals->helloResponse.responseType != RESPONSE_TYPE_HELLO) {
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
|
||||||
|
networkGlobals->errorCode = NSGS_HELLO_UNEXPECTED_RESPONSE_ERROR;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
networkGlobals->secrets[2] = networkGlobals->helloResponse.nonce;
|
||||||
|
if (networkGlobals->hasHighScoreToSend) {
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_SET_HIGH_SCORE;
|
||||||
|
} else if ((!networkGlobals->hasGlobalHighScores) ||
|
||||||
|
((networkGlobals->initParams.shouldRefreshHighScores != NULL) &&
|
||||||
|
(networkGlobals->initParams.shouldRefreshHighScores()))) {
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_REQUEST_SCORES;
|
||||||
|
} else {
|
||||||
|
TCPIPCloseTCP(networkGlobals->ipid);
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_CLOSING_TCP;
|
||||||
|
networkGlobals->timeout = networkGlobals->initParams.shutdownTimeout;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handleRequestScores(void)
|
||||||
|
{
|
||||||
|
networkGlobals->highScoreRequest.highScoreRequest.requestType = REQUEST_TYPE_GET_HIGH_SCORES;
|
||||||
|
|
||||||
|
md5Init(&(networkGlobals->hashWorkBlock));
|
||||||
|
md5Append(&(networkGlobals->hashWorkBlock), (Pointer)&(networkGlobals->secrets), sizeof(networkGlobals->secrets));
|
||||||
|
md5Append(&(networkGlobals->hashWorkBlock), (Pointer)&(networkGlobals->highScoreRequest.highScoreRequest), sizeof(networkGlobals->highScoreRequest.highScoreRequest));
|
||||||
|
md5Finish(&(networkGlobals->hashWorkBlock), (Pointer)&(networkGlobals->highScoreRequest.md5Digest[0]));
|
||||||
|
|
||||||
|
networkGlobals->errorCode = TCPIPWriteTCP(networkGlobals->ipid, (Pointer)&(networkGlobals->highScoreRequest), sizeof(networkGlobals->highScoreRequest), FALSE, FALSE);
|
||||||
|
if (networkGlobals->errorCode != tcperrOK) {
|
||||||
|
abortConnection();
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_WAITING_FOR_SCORES;
|
||||||
|
networkGlobals->timeout = networkGlobals->initParams.readTimeout;
|
||||||
|
networkGlobals->bytesRead = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handleWaitingForScores(void)
|
||||||
|
{
|
||||||
|
networkGlobals->errorCode = TCPIPReadTCP(networkGlobals->ipid, 0,
|
||||||
|
((uint32_t)(&networkGlobals->highScoreResponse)) + networkGlobals->bytesRead,
|
||||||
|
sizeof(networkGlobals->highScoreResponse) - networkGlobals->bytesRead,
|
||||||
|
&(networkGlobals->readResponseBuf));
|
||||||
|
if (networkGlobals->errorCode != tcperrOK) {
|
||||||
|
abortConnection();
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
networkGlobals->bytesRead += networkGlobals->readResponseBuf.rrBuffCount;
|
||||||
|
if (networkGlobals->bytesRead < sizeof(networkGlobals->highScoreResponse)) {
|
||||||
|
if (networkGlobals->timeout > 0) {
|
||||||
|
networkGlobals->timeout--;
|
||||||
|
} else {
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
|
||||||
|
networkGlobals->errorCode = NSGS_HIGH_SCORE_TIMEOUT_ERROR;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (networkGlobals->bytesRead > sizeof(networkGlobals->highScoreResponse)) {
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
|
||||||
|
networkGlobals->errorCode = NSGS_HIGH_SCORE_TOO_BIG_ERROR;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (networkGlobals->highScoreResponse.responseType != RESPONSE_TYPE_SCORES) {
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
|
||||||
|
networkGlobals->errorCode = NSGS_HIGH_SCORE_UNEXPECTED_RESPONSE_ERROR;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
networkGlobals->hasGlobalHighScores = TRUE;
|
||||||
|
if (networkGlobals->initParams.setHighScores != NULL)
|
||||||
|
networkGlobals->initParams.setHighScores(&(networkGlobals->highScoreResponse.highScores));
|
||||||
|
|
||||||
|
TCPIPCloseTCP(networkGlobals->ipid);
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_CLOSING_TCP;
|
||||||
|
networkGlobals->timeout = networkGlobals->initParams.shutdownTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handleSetHighScore(void)
|
||||||
|
{
|
||||||
|
networkGlobals->setHighScoreRequest.setHighScoreRequest.requestType = REQUEST_TYPE_SET_SCORE;
|
||||||
|
networkGlobals->setHighScoreRequest.setHighScoreRequest.who[3] = '\0';
|
||||||
|
|
||||||
|
md5Init(&(networkGlobals->hashWorkBlock));
|
||||||
|
md5Append(&(networkGlobals->hashWorkBlock), (Pointer)&(networkGlobals->secrets), sizeof(networkGlobals->secrets));
|
||||||
|
md5Append(&(networkGlobals->hashWorkBlock), (Pointer)&(networkGlobals->setHighScoreRequest.setHighScoreRequest), sizeof(networkGlobals->setHighScoreRequest.setHighScoreRequest));
|
||||||
|
md5Finish(&(networkGlobals->hashWorkBlock), (Pointer)&(networkGlobals->setHighScoreRequest.md5Digest[0]));
|
||||||
|
|
||||||
|
networkGlobals->errorCode = TCPIPWriteTCP(networkGlobals->ipid, (Pointer)&(networkGlobals->setHighScoreRequest), sizeof(networkGlobals->setHighScoreRequest), FALSE, FALSE);
|
||||||
|
if (networkGlobals->errorCode != tcperrOK) {
|
||||||
|
abortConnection();
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_WAITING_FOR_SCORE_ACK;
|
||||||
|
networkGlobals->timeout = networkGlobals->initParams.readTimeout;
|
||||||
|
networkGlobals->bytesRead = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handleWaitingForScoreAck(void)
|
||||||
|
{
|
||||||
|
networkGlobals->errorCode = TCPIPReadTCP(networkGlobals->ipid, 0,
|
||||||
|
((uint32_t)(&(networkGlobals->setHighScoreResponse))) + networkGlobals->bytesRead,
|
||||||
|
sizeof(networkGlobals->setHighScoreResponse) - networkGlobals->bytesRead,
|
||||||
|
&(networkGlobals->readResponseBuf));
|
||||||
|
if (networkGlobals->errorCode != tcperrOK) {
|
||||||
|
abortConnection();
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_SOCKET_ERROR;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
networkGlobals->bytesRead += networkGlobals->readResponseBuf.rrBuffCount;
|
||||||
|
if (networkGlobals->bytesRead < sizeof(networkGlobals->setHighScoreResponse)) {
|
||||||
|
if (networkGlobals->timeout > 0) {
|
||||||
|
networkGlobals->timeout--;
|
||||||
|
} else {
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
|
||||||
|
networkGlobals->errorCode = NSGS_SET_SCORE_TIMEOUT_ERROR;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (networkGlobals->bytesRead > sizeof(networkGlobals->setHighScoreResponse)) {
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
|
||||||
|
networkGlobals->errorCode = NSGS_SET_SCORE_TOO_BIG_ERROR;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (networkGlobals->setHighScoreResponse.responseType != RESPONSE_TYPE_STATUS) {
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
|
||||||
|
networkGlobals->errorCode = NSGS_SET_SCORE_UNEXPECTED_RESPONSE_ERROR;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!networkGlobals->setHighScoreResponse.success) {
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_PROTOCOL_FAILED;
|
||||||
|
networkGlobals->errorCode = NSGS_SET_SCORE_FAILED_ERROR;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
networkGlobals->hasHighScoreToSend = FALSE;
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_REQUEST_SCORES;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handleClosingTcp(void)
|
||||||
|
{
|
||||||
|
networkGlobals->errorCode = TCPIPStatusTCP(networkGlobals->ipid, &(networkGlobals->tcpStatus));
|
||||||
|
if ((networkGlobals->tcpStatus.srState != TCPSCLOSED) &&
|
||||||
|
(networkGlobals->tcpStatus.srState != TCPSTIMEWAIT)) {
|
||||||
|
if (networkGlobals->timeout > 0) {
|
||||||
|
networkGlobals->timeout--;
|
||||||
|
} else {
|
||||||
|
abortConnection();
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_TCP_UNCONNECTED;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TCPIPLogout(networkGlobals->ipid);
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_TCP_UNCONNECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NSGS_PollNetwork(void)
|
||||||
|
{
|
||||||
|
if (networkGlobals == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
TCPIPPoll();
|
||||||
|
|
||||||
|
handlers[networkGlobals->gameNetworkState]();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BOOLEAN NSGS_CanSendHighScore(void)
|
||||||
|
{
|
||||||
|
if (networkGlobals == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (networkGlobals->gameNetworkState < GAME_NETWORK_TCP_UNCONNECTED) {
|
||||||
|
if ((networkGlobals->gameNetworkState == GAME_NETWORK_FAILURE) &&
|
||||||
|
(networkGlobals->timeout > 0))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN NSGS_SendHighScore(const char * who, unsigned long score)
|
||||||
|
{
|
||||||
|
uint16_t cycleCount = 0;
|
||||||
|
|
||||||
|
if (strlen(who) != 3)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
networkGlobals->hasHighScoreToSend = TRUE;
|
||||||
|
memcpy(networkGlobals->setHighScoreRequest.setHighScoreRequest.who, who, sizeof(networkGlobals->setHighScoreRequest.setHighScoreRequest.who));
|
||||||
|
networkGlobals->setHighScoreRequest.setHighScoreRequest.score = score;
|
||||||
|
|
||||||
|
if (networkGlobals->gameNetworkState < GAME_NETWORK_TCP_UNCONNECTED)
|
||||||
|
networkGlobals->gameNetworkState = GAME_NETWORK_TCP_UNCONNECTED;
|
||||||
|
|
||||||
|
do {
|
||||||
|
networkGlobals->initParams.waitForVbl();
|
||||||
|
NSGS_PollNetwork();
|
||||||
|
cycleCount++;
|
||||||
|
|
||||||
|
if ((cycleCount & 0x7) == 0) {
|
||||||
|
switch (cycleCount & 0x18) {
|
||||||
|
case 0x00:
|
||||||
|
if (networkGlobals->initParams.uploadSpin != NULL)
|
||||||
|
networkGlobals->initParams.uploadSpin(0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x08:
|
||||||
|
if (networkGlobals->initParams.uploadSpin != NULL)
|
||||||
|
networkGlobals->initParams.uploadSpin(1);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x10:
|
||||||
|
if (networkGlobals->initParams.uploadSpin != NULL)
|
||||||
|
networkGlobals->initParams.uploadSpin(2);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x18:
|
||||||
|
if (networkGlobals->initParams.uploadSpin != NULL)
|
||||||
|
networkGlobals->initParams.uploadSpin(3);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (networkGlobals->gameNetworkState > GAME_NETWORK_TCP_UNCONNECTED);
|
||||||
|
|
||||||
|
if (networkGlobals->gameNetworkState != GAME_NETWORK_TCP_UNCONNECTED)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (networkGlobals->initParams.scorePosition != NULL)
|
||||||
|
networkGlobals->initParams.scorePosition(networkGlobals->setHighScoreResponse.position,
|
||||||
|
networkGlobals->setHighScoreResponse.numberOfScores);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
|
@ -1,27 +1,54 @@
|
||||||
/*
|
/*
|
||||||
* globalScores.h
|
* netScores.h
|
||||||
* BuGS
|
* NetScoresGS
|
||||||
*
|
*
|
||||||
* Created by Jeremy Rand on 2021-05-23.
|
* Created by Jeremy Rand on 2021-05-23.
|
||||||
* Copyright © 2021 Jeremy Rand. All rights reserved.
|
* Copyright © 2021 Jeremy Rand. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _GUARD_PROJECTBuGS_FILEglobalScores_
|
#ifndef _GUARD_PROJECTNetScoresGS_FILEnetScores_
|
||||||
#define _GUARD_PROJECTBuGS_FILEglobalScores_
|
#define _GUARD_PROJECTNetScoresGS_FILEnetScores_
|
||||||
|
|
||||||
|
|
||||||
#include <types.h>
|
#include <TYPES.h>
|
||||||
|
|
||||||
|
typedef enum tNSGSErrorType
|
||||||
|
{
|
||||||
|
NSGS_CONNECT_ERROR,
|
||||||
|
NSGS_LOOKUP_ERROR,
|
||||||
|
NSGS_SOCKET_ERROR,
|
||||||
|
NSGS_PROTOCOL_ERROR
|
||||||
|
} tNSGSErrorType;
|
||||||
|
|
||||||
|
|
||||||
typedef struct tHighScore
|
typedef enum ttNSGSProtocolErrors {
|
||||||
|
NSGS_TCP_CONNECT_TIMEOUT_ERROR = 1,
|
||||||
|
NSGS_HELLO_TIMEOUT_ERROR,
|
||||||
|
NSGS_HELLO_TOO_BIG_ERROR,
|
||||||
|
NSGS_HELLO_UNEXPECTED_RESPONSE_ERROR,
|
||||||
|
NSGS_HIGH_SCORE_TIMEOUT_ERROR,
|
||||||
|
NSGS_HIGH_SCORE_TOO_BIG_ERROR,
|
||||||
|
NSGS_HIGH_SCORE_UNEXPECTED_RESPONSE_ERROR,
|
||||||
|
NSGS_SET_SCORE_TIMEOUT_ERROR,
|
||||||
|
NSGS_SET_SCORE_TOO_BIG_ERROR,
|
||||||
|
NSGS_SET_SCORE_UNEXPECTED_RESPONSE_ERROR,
|
||||||
|
NSGS_SET_SCORE_FAILED_ERROR,
|
||||||
|
} ttNSGSProtocolErrors;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct tNSGSHighScore
|
||||||
{
|
{
|
||||||
char scoreText[10];
|
char scoreText[10];
|
||||||
char who[4];
|
char who[4];
|
||||||
unsigned long score;
|
unsigned long score;
|
||||||
} tHighScore;
|
} tNSGSHighScore;
|
||||||
|
|
||||||
|
typedef struct tNSGSHighScores
|
||||||
|
{
|
||||||
|
tNSGSHighScore score[10];
|
||||||
|
} tNSGSHighScores;
|
||||||
|
|
||||||
typedef struct tHighScoreInitParams
|
typedef struct tNSGSHighScoreInitParams
|
||||||
{
|
{
|
||||||
/* This structure is initialized by the game and passed by pointer to the high score code. It consists of
|
/* This structure is initialized by the game and passed by pointer to the high score code. It consists of
|
||||||
a series of data members and a series of callbacks which are provided by the game.
|
a series of data members and a series of callbacks which are provided by the game.
|
||||||
|
@ -42,11 +69,31 @@ typedef struct tHighScoreInitParams
|
||||||
unsigned long secret1;
|
unsigned long secret1;
|
||||||
unsigned long secret2;
|
unsigned long secret2;
|
||||||
|
|
||||||
|
/* Each of these timeouts are measured in poll periods. So, if you call NSGS_PollNetwork() every 60th of a
|
||||||
|
second, then you would use 60 to set the timeout to 1 second. If these are zero, then the "good value"
|
||||||
|
in the comment will be used as a default.
|
||||||
|
|
||||||
|
The shutdown timeout controls how long we wait for a clean TCP disconnection before forcing an abort of
|
||||||
|
the connection. Two seconds is a good value for this timeout. */
|
||||||
|
unsigned int shutdownTimeout;
|
||||||
|
|
||||||
|
/* The connect timeout is the amount of time we wait for a TCP connection to come up before declaring a
|
||||||
|
timeout protocol error. Eight seconds is a good value for this timeout. */
|
||||||
|
unsigned int connectTimeout;
|
||||||
|
|
||||||
|
/* The read timeout is the amount of time we wait for a response from the server after we have made a
|
||||||
|
request of it, whether that is getting the high score list or setting a new high score. Five seconds
|
||||||
|
is a good value for this timeout. */
|
||||||
|
unsigned int readTimeout;
|
||||||
|
|
||||||
|
/* The retry timeout is the amount of time we wait in an error state before retrying. This only happens
|
||||||
|
for "soft" errors where a retry is worthwhile. Three minutes is a good value for this timeout. */
|
||||||
|
unsigned int retryTimeout;
|
||||||
|
|
||||||
/* This function should display a message to the user that the network is being brought up and they should
|
/* This function should display a message to the user that the network is being brought up and they should
|
||||||
be patient when the argument is TRUE and when the argument is FALSE, it should clear that message. This
|
be patient when the argument is TRUE and when the argument is FALSE, it should clear that message. This
|
||||||
function shouldn't block and just put something on the screen to say that the connection is being brought
|
function shouldn't block and just put something on the screen to say that the connection is being brought
|
||||||
up or clear that message. It is called sometimes (rarely) by pollNetwork(). It is called with argument
|
up or clear that message. It is called sometimes (rarely) by NSGS_PollNetwork(). It is called with argument
|
||||||
TRUE and will always be called with FALSE sometime after that.
|
TRUE and will always be called with FALSE sometime after that.
|
||||||
*/
|
*/
|
||||||
void (*displayConnectionString)(BOOLEAN display);
|
void (*displayConnectionString)(BOOLEAN display);
|
||||||
|
@ -59,7 +106,7 @@ typedef struct tHighScoreInitParams
|
||||||
/* This argument iterates over 0, 1, 2, 3 and then back to 0, 1, 2, etc and is intended to show some kind
|
/* This argument iterates over 0, 1, 2, 3 and then back to 0, 1, 2, etc and is intended to show some kind
|
||||||
of spinner to the user while uploading a high score to the server. This function shouldn't block for
|
of spinner to the user while uploading a high score to the server. This function shouldn't block for
|
||||||
any real amount of time and just cause something on the screen to change to make sure the player doesn't
|
any real amount of time and just cause something on the screen to change to make sure the player doesn't
|
||||||
think something has hung while the upload is in progress. It is called when sendHighScore() is called
|
think something has hung while the upload is in progress. It is called when NSGS_SendHighScore() is called
|
||||||
by the game.
|
by the game.
|
||||||
*/
|
*/
|
||||||
void (*uploadSpin)(int);
|
void (*uploadSpin)(int);
|
||||||
|
@ -68,52 +115,68 @@ typedef struct tHighScoreInitParams
|
||||||
of this player's score among the total number of scores recorded for this game. This information
|
of this player's score among the total number of scores recorded for this game. This information
|
||||||
should be displayed to the user. The function can block while this information is being displayed
|
should be displayed to the user. The function can block while this information is being displayed
|
||||||
and that message should be cleaned up before the function returns to the caller. This function is
|
and that message should be cleaned up before the function returns to the caller. This function is
|
||||||
called by sendHighScore().
|
called by NSGS_SendHighScore().
|
||||||
*/
|
*/
|
||||||
void (*scorePosition)(unsigned int position, unsigned int numberOfScores);
|
void (*scorePosition)(unsigned int position, unsigned int numberOfScores);
|
||||||
} tHighScoreInitParams;
|
|
||||||
|
/* This function is only called from NSGS_PollNetwork() when something unexpected has occurred.
|
||||||
|
The meaning of the error code depends on the error type. For a protocol error, the error code
|
||||||
|
is one of tNSGSProtocolErrors. For other error codes, they come from Marinetti error codes.
|
||||||
|
if the error code > $8000, then the error code is the socket state or-ed with $8000. */
|
||||||
|
void (*displayError)(tNSGSErrorType errorType, unsigned int errorCode);
|
||||||
|
|
||||||
|
/* This function is only called from NSGS_PollNetwork() when new scores have been downloaded.
|
||||||
|
The scores passed should be copied because the pointer is not guaranteed to be valid after
|
||||||
|
the callback returns. */
|
||||||
|
void (*setHighScores)(const tNSGSHighScores * scores);
|
||||||
|
|
||||||
|
/* This function is called to ask if it is time to refresh the global high score list. This should
|
||||||
|
be based on watching the elapsed time and it should return true if say 5 minutes has elapsed
|
||||||
|
since high scores have been updated. */
|
||||||
|
BOOLEAN (*shouldRefreshHighScores)(void);
|
||||||
|
} tNSGSHighScoreInitParams;
|
||||||
|
|
||||||
|
|
||||||
/* Call this function once at launch. The pointer to the parameters is copied so the structure does not need
|
/* Call this function once at launch. The pointer to the parameters is copied so the structure does not need
|
||||||
to remain valid after the call to this function.
|
to remain valid after the call to this function.
|
||||||
*/
|
*/
|
||||||
extern void initNetwork(tHighScoreInitParams * params);
|
extern void NSGS_InitNetwork(tNSGSHighScoreInitParams * params);
|
||||||
|
|
||||||
|
|
||||||
/* Call this when a game is about to start. It will interrupt any network operation in progress and get ready for
|
/* Call this when a game is about to start. It will interrupt any network operation in progress and get ready for
|
||||||
a quiet period where polling will stop until the game is over. That way, all CPU time can be focused on the game.
|
a quiet period where polling will stop until the game is over. That way, all CPU time can be focused on the game.
|
||||||
This function may call the waitForVbl() callback.
|
This function may call the waitForVbl() callback.
|
||||||
*/
|
*/
|
||||||
extern void disconnectNetwork(void);
|
extern void NSGS_DisconnectNetwork(void);
|
||||||
|
|
||||||
|
|
||||||
/* Call this every frame refresh period when a game is _not_ in progress. This does any network operations required
|
/* Call this every frame refresh period when a game is _not_ in progress. This does any network operations required
|
||||||
to download high scores. During this function call, the displayConnectionString() callback may be called.
|
to download high scores. During this function call, the displayConnectionString() callback may be called.
|
||||||
*/
|
*/
|
||||||
extern void pollNetwork(void);
|
extern void NSGS_PollNetwork(void);
|
||||||
|
|
||||||
|
|
||||||
/* Call this function once when the game is quitting. */
|
/* Call this function once when the game is quitting. */
|
||||||
extern void shutdownNetwork(void);
|
extern void NSGS_ShutdownNetwork(void);
|
||||||
|
|
||||||
|
|
||||||
/* Call this function when the player has a high score that should be recorded online. This function will return
|
/* Call this function when the player has a high score that should be recorded online. This function will return
|
||||||
TRUE if the network is up and a high score can be sent and if so, the game should call sendHighScore() to send
|
TRUE if the network is up and a high score can be sent and if so, the game should call NSGS_SendHighScore() to send
|
||||||
the high score. If FALSE is returned, then the user is playing while offline and no attempt should be made to
|
the high score. If FALSE is returned, then the user is playing while offline and no attempt should be made to
|
||||||
send the high score.
|
send the high score.
|
||||||
*/
|
*/
|
||||||
extern BOOLEAN canSendHighScore(void);
|
extern BOOLEAN NSGS_CanSendHighScore(void);
|
||||||
|
|
||||||
|
|
||||||
/* Assuming canSendHighScore() returned TRUE, the game can call this function to actually try to send the high score
|
/* Assuming NSGS_CanSendHighScore() returned TRUE, the game can call this function to actually try to send the high score
|
||||||
to the server. If this function returns TRUE, then the score was successfully sent to the server. If FALSE
|
to the server. If this function returns TRUE, then the score was successfully sent to the server. If FALSE
|
||||||
is returned, then an error has occurred. The game can offer the user the option to retry to the upload of the
|
is returned, then an error has occurred. The game can offer the user the option to retry to the upload of the
|
||||||
score and if the user would like to retry, just call sendHighScore() again. During this function call, the
|
score and if the user would like to retry, just call NSGS_SendHighScore() again. During this function call, the
|
||||||
waitForVbl(), uploadSpin() and scorePosition() callbacks may be called.
|
waitForVbl(), uploadSpin() and scorePosition() callbacks may be called.
|
||||||
|
|
||||||
TODO - Pass the score as an argument rather than through globals.
|
TODO - Pass the score as an argument rather than through globals.
|
||||||
*/
|
*/
|
||||||
extern BOOLEAN sendHighScore(void);
|
extern BOOLEAN NSGS_SendHighScore(const char * who, unsigned long score);
|
||||||
|
|
||||||
|
|
||||||
#endif /* define _GUARD_PROJECTBuGS_FILEglobalScores_ */
|
#endif /* define _GUARD_PROJECTNetScoresGS_FILEnetScores_ */
|
|
@ -438,10 +438,8 @@ checkHighScore_doneCopy anop
|
||||||
tax
|
tax
|
||||||
lda gameScore,x
|
lda gameScore,x
|
||||||
sta settings+SETTINGS_HIGH_SCORE_OFFSET+HIGH_SCORE_SCORE_OFFSET,y
|
sta settings+SETTINGS_HIGH_SCORE_OFFSET+HIGH_SCORE_SCORE_OFFSET,y
|
||||||
sta setHighScoreRequest+6
|
|
||||||
lda gameScore+2,x
|
lda gameScore+2,x
|
||||||
sta settings+SETTINGS_HIGH_SCORE_OFFSET+HIGH_SCORE_SCORE_OFFSET+2,y
|
sta settings+SETTINGS_HIGH_SCORE_OFFSET+HIGH_SCORE_SCORE_OFFSET+2,y
|
||||||
sta setHighScoreRequest+8
|
|
||||||
|
|
||||||
lda playerNum
|
lda playerNum
|
||||||
cmp #PLAYER_ONE
|
cmp #PLAYER_ONE
|
||||||
|
@ -782,12 +780,8 @@ checkHighScore_isInvalid anop
|
||||||
|
|
||||||
checkHighScore_doneInitials anop
|
checkHighScore_doneInitials anop
|
||||||
_overwriteGameTile TILE_EMPTY
|
_overwriteGameTile TILE_EMPTY
|
||||||
lda settings+SETTINGS_HIGH_SCORE_OFFSET+HIGH_SCORE_WHO_OFFSET-3,y
|
|
||||||
sta setHighScoreRequest+2
|
|
||||||
lda settings+SETTINGS_HIGH_SCORE_OFFSET+HIGH_SCORE_WHO_OFFSET-1,y
|
|
||||||
sta setHighScoreRequest+4
|
|
||||||
jsl saveSettings
|
jsl saveSettings
|
||||||
jsl canSendHighScore
|
jsl NSGS_CanSendHighScore
|
||||||
bne checkHighScore_retry
|
bne checkHighScore_retry
|
||||||
brl checkHighScore_doneNetwork
|
brl checkHighScore_doneNetwork
|
||||||
|
|
||||||
|
|
|
@ -6,11 +6,14 @@
|
||||||
* Copyright © 2021 Jeremy Rand. All rights reserved.
|
* Copyright © 2021 Jeremy Rand. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include <gsos.h>
|
#include <gsos.h>
|
||||||
|
#include <orca.h>
|
||||||
#include <Memory.h>
|
#include <Memory.h>
|
||||||
|
|
||||||
#include "globalScores.h"
|
#include "game.h"
|
||||||
|
#include "netScores.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "tileData.h"
|
#include "tileData.h"
|
||||||
|
|
||||||
|
@ -27,7 +30,7 @@ typedef struct tSettingsData
|
||||||
char magic[4];
|
char magic[4];
|
||||||
int version;
|
int version;
|
||||||
Boolean stereoCorrect;
|
Boolean stereoCorrect;
|
||||||
tHighScore highScores[NUM_HIGH_SCORES];
|
tNSGSHighScore highScores[NUM_HIGH_SCORES];
|
||||||
} tSettingsData;
|
} tSettingsData;
|
||||||
|
|
||||||
|
|
||||||
|
@ -62,8 +65,17 @@ static Handle filenameHandle = NULL;
|
||||||
|
|
||||||
// Implementation
|
// Implementation
|
||||||
|
|
||||||
|
#if __ORCAC__
|
||||||
segment "settings";
|
segment "settings";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const tNSGSHighScore * getHighScore(unsigned int index)
|
||||||
|
{
|
||||||
|
if (index >= NUM_HIGH_SCORES)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return &(settings.highScores[index]);
|
||||||
|
}
|
||||||
|
|
||||||
static void allocateFilenameHandle(void)
|
static void allocateFilenameHandle(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,14 +9,18 @@
|
||||||
#ifndef _GUARD_PROJECTBuGS_FILEsettings_
|
#ifndef _GUARD_PROJECTBuGS_FILEsettings_
|
||||||
#define _GUARD_PROJECTBuGS_FILEsettings_
|
#define _GUARD_PROJECTBuGS_FILEsettings_
|
||||||
|
|
||||||
#include <types.h>
|
#include <TYPES.h>
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct tNSGSHighScore tNSGSHighScore;
|
||||||
|
|
||||||
extern unsigned int myUserId;
|
extern unsigned int myUserId;
|
||||||
|
|
||||||
extern void saveSettings(void);
|
extern void saveSettings(void);
|
||||||
BOOLEAN loadSettings(void);
|
extern BOOLEAN loadSettings(void);
|
||||||
extern void swapStereoSettings(void);
|
extern void swapStereoSettings(void);
|
||||||
|
|
||||||
|
extern const tNSGSHighScore * getHighScore(unsigned int index);
|
||||||
|
|
||||||
|
|
||||||
#endif /* define _GUARD_PROJECTBuGS_FILEsettings_ */
|
#endif /* define _GUARD_PROJECTBuGS_FILEsettings_ */
|
||||||
|
|
Loading…
Reference in New Issue