mirror of
https://github.com/jeremysrand/BuGS.git
synced 2024-06-14 04:29:28 +00:00
Compare commits
2 Commits
f1a80c792a
...
37faafb698
Author | SHA1 | Date | |
---|---|---|---|
|
37faafb698 | ||
|
b8b9089aa2 |
|
@ -116,7 +116,7 @@
|
|||
9DE37B3E2694E0B0005FC562 /* globalScores.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = globalScores.h; 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>"; };
|
||||
9DE37B412694E0B0005FC562 /* score.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = score.s; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.asm.orcam; };
|
||||
9DE37B412694E0B0005FC562 /* score.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = score.s; sourceTree = "<group>"; };
|
||||
9DE37B422694E0B0005FC562 /* gamePlayer.s */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = gamePlayer.s; sourceTree = "<group>"; };
|
||||
9DE37B432694E0B0005FC562 /* Read.Me.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = Read.Me.md; sourceTree = "<group>"; };
|
||||
9DE37B442694E0B0005FC562 /* global.macros */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = global.macros; sourceTree = "<group>"; };
|
||||
|
@ -234,9 +234,9 @@
|
|||
9DE37B412694E0B0005FC562 /* score.s */,
|
||||
9DE37B482694E0B0005FC562 /* settings.c */,
|
||||
9DE37B462694E0B0005FC562 /* settings.h */,
|
||||
9DE37B342694E0B0005FC562 /* tileConvert.s */,
|
||||
9DE37B5C2694E0B0005FC562 /* sound */,
|
||||
9DE37B4A2694E0B0005FC562 /* sprites */,
|
||||
9DE37B342694E0B0005FC562 /* tileConvert.s */,
|
||||
9DE37AF62694E070005FC562 /* Makefile */,
|
||||
9DE37AF82694E070005FC562 /* make */,
|
||||
9DE37B112694E070005FC562 /* Supporting Files */,
|
||||
|
|
|
@ -22,12 +22,12 @@
|
|||
<key>DiskImage.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>2</integer>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
<key>doNotBuild.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>1</integer>
|
||||
<integer>2</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
|
|
|
@ -149,7 +149,7 @@ COPYBOOTDIRS=
|
|||
# By default, the build uses these arguments with mame:
|
||||
# apple2gs -skip_gameinfo -mouse -window -resolution 1408x1056 -ramsize 4M -sl7 cffa202
|
||||
# If you would like to use different arguments, specify that here.
|
||||
MAMEARGS=apple2gs -skip_gameinfo -mouse -window -resolution 1408x1056 -ramsize 4M -sl3 uthernet -sl7 cffa2
|
||||
MAMEARGS=apple2gs -skip_gameinfo -mouse -window -resolution 1408x1056 -ramsize 4M -sl3 uthernet -sl7 scsi
|
||||
|
||||
# For a desktop application, it can operate in 640x200 or 320x200
|
||||
# resolution. This setting is used to define which horizontal
|
||||
|
|
11
BuGS/game.h
11
BuGS/game.h
|
@ -9,11 +9,22 @@
|
|||
#ifndef _GUARD_PROJECTBuGS_FILEgame_
|
||||
#define _GUARD_PROJECTBuGS_FILEgame_
|
||||
|
||||
|
||||
#include "tileData.h"
|
||||
|
||||
// These are globals used from assembly.
|
||||
extern char globalScoreInfo[GAME_NUM_TILES_WIDE + 1];
|
||||
|
||||
// These are assembly functions called from C.
|
||||
|
||||
extern void game(void);
|
||||
extern void randInit(void);
|
||||
extern void waitForVbl(void);
|
||||
extern void uploadSpin1(void);
|
||||
extern void uploadSpin2(void);
|
||||
extern void uploadSpin3(void);
|
||||
extern void displayConnectionString(void);
|
||||
extern void displayScorePosition(void);
|
||||
extern void swapStereoChannels(void);
|
||||
|
||||
|
||||
|
|
|
@ -223,7 +223,6 @@ updateScorpion_explosionDone anop
|
|||
|
||||
|
||||
setScorpionSpeed entry
|
||||
; TODO - Call this code with each level to set the scorpion speed
|
||||
cmp #SPRITE_SPEED_FAST
|
||||
beq setScorpionSpeed_fast
|
||||
|
||||
|
|
|
@ -23,12 +23,14 @@ _drawDirtyGameRow_wait&rowNum anop
|
|||
; offset numbers.
|
||||
;
|
||||
; Also according to that technote, it looks like these numbers are different
|
||||
; in PAL mode. TODO - Do I need something here to handle PAL correctly? I
|
||||
; switched my GS to 50Hz mode (startup/reboot with option held down to get the
|
||||
; menu) and I didnt't detect any graphics glitches at all. I did notice that
|
||||
; the game is noticably easier because things run a bit slower. If I do an
|
||||
; online score system, I should record whether a score was gotten at 50Hz vs
|
||||
; 60Hz.
|
||||
; in PAL mode. Do I need something here to handle PAL correctly? I switched
|
||||
; my GS to 50Hz mode (startup/reboot with option held down to get the menu)
|
||||
; and I didnt't detect any graphics glitches at all. I did notice that the
|
||||
; game is noticably easier because things run a bit slower. If I do an online
|
||||
; score system, I should record whether a score was gotten at 50Hz vs 60Hz.
|
||||
; (and in fact, I have since implemented online high scores and record the
|
||||
; frequency at which the game was played)
|
||||
|
||||
lda >VERTICAL_COUNTER ; load the counter value
|
||||
and #$80ff ; mask out the VBL bits
|
||||
asl a ; shift the word around
|
||||
|
|
|
@ -16,9 +16,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "game.h"
|
||||
#include "globalScores.h"
|
||||
#include "tileData.h"
|
||||
|
||||
|
||||
// Defines
|
||||
|
@ -142,6 +140,7 @@ typedef enum tGameNetworkState {
|
|||
|
||||
typedef struct tGameNetworkGlobals {
|
||||
Boolean networkStartedConnected;
|
||||
tHighScoreInitParams initParams;
|
||||
tGameNetworkState gameNetworkState;
|
||||
dnrBuffer domainNameResolution;
|
||||
srBuff tcpStatus;
|
||||
|
@ -168,11 +167,11 @@ 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;
|
||||
Word globalScoreAge = 0; // TODO - Replace this with a call to a MiscTool function?
|
||||
tSetHighScoreRequestWithHash setHighScoreRequest;
|
||||
char globalScoreInfo[GAME_NUM_TILES_WIDE + 1];
|
||||
|
||||
|
||||
// Implementation
|
||||
|
@ -180,12 +179,13 @@ char globalScoreInfo[GAME_NUM_TILES_WIDE + 1];
|
|||
|
||||
segment "highscores";
|
||||
|
||||
void initNetwork(void)
|
||||
void initNetwork(tHighScoreInitParams * params)
|
||||
{
|
||||
networkGlobals = NULL;
|
||||
|
||||
if ((NETWORK_SERVER == NULL) ||
|
||||
(NETWORK_SERVERPORT == 0))
|
||||
if ((params->scoreServer == NULL) ||
|
||||
(params->scorePort == 0) ||
|
||||
(params->waitForVbl == NULL))
|
||||
return;
|
||||
|
||||
LoadOneTool(54, 0x200); // Load Marinetti
|
||||
|
@ -223,6 +223,8 @@ void initNetwork(void)
|
|||
|
||||
}
|
||||
|
||||
memcpy(&(networkGlobals->initParams), params, sizeof(networkGlobals->initParams));
|
||||
|
||||
networkGlobals->networkStartedConnected = TCPIPGetConnectStatus();
|
||||
if (networkGlobals->networkStartedConnected) {
|
||||
networkGlobals->gameNetworkState = GAME_NETWORK_CONNECTED;
|
||||
|
@ -230,8 +232,8 @@ void initNetwork(void)
|
|||
networkGlobals->gameNetworkState = GAME_NETWORK_UNCONNECTED;
|
||||
}
|
||||
|
||||
networkGlobals->secrets[0] = NETWORK_SERVERSECRET1;
|
||||
networkGlobals->secrets[1] = NETWORK_SERVERSECRET2;
|
||||
networkGlobals->secrets[0] = params->secret1;
|
||||
networkGlobals->secrets[1] = params->secret2;
|
||||
|
||||
networkGlobals->hasHighScoreToSend = FALSE;
|
||||
|
||||
|
@ -275,7 +277,7 @@ void disconnectNetwork(void)
|
|||
}
|
||||
|
||||
while (networkGlobals->gameNetworkState > GAME_NETWORK_TCP_UNCONNECTED) {
|
||||
waitForVbl();
|
||||
networkGlobals->initParams.waitForVbl();
|
||||
pollNetwork();
|
||||
}
|
||||
}
|
||||
|
@ -380,7 +382,8 @@ void pollNetwork(void)
|
|||
break;
|
||||
|
||||
case GAME_NETWORK_UNCONNECTED:
|
||||
displayConnectionString();
|
||||
if (networkGlobals->initParams.displayConnectionString != NULL)
|
||||
networkGlobals->initParams.displayConnectionString(TRUE);
|
||||
TCPIPConnect(NULL);
|
||||
if ((!toolerror()) &&
|
||||
(TCPIPGetConnectStatus())) {
|
||||
|
@ -388,10 +391,12 @@ void pollNetwork(void)
|
|||
} else {
|
||||
networkGlobals->gameNetworkState = GAME_NETWORK_CONNECT_FAILED;
|
||||
}
|
||||
if (networkGlobals->initParams.displayConnectionString != NULL)
|
||||
networkGlobals->initParams.displayConnectionString(FALSE);
|
||||
break;
|
||||
|
||||
case GAME_NETWORK_CONNECTED:
|
||||
TCPIPDNRNameToIP("\p" NETWORK_SERVER, &(networkGlobals->domainNameResolution));
|
||||
TCPIPDNRNameToIP(networkGlobals->initParams.scoreServer, &(networkGlobals->domainNameResolution));
|
||||
if (toolerror()) {
|
||||
networkGlobals->gameNetworkState = GAME_NETWORK_LOOKUP_FAILED;
|
||||
networkGlobals->errorCode = toolerror();
|
||||
|
@ -418,7 +423,7 @@ void pollNetwork(void)
|
|||
(!networkGlobals->hasHighScoreToSend))
|
||||
break;
|
||||
|
||||
networkGlobals->ipid = TCPIPLogin(myUserId, networkGlobals->domainNameResolution.DNRIPaddress, NETWORK_SERVERPORT, 0, 64);
|
||||
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();
|
||||
|
@ -686,26 +691,30 @@ BOOLEAN sendHighScore(void)
|
|||
networkGlobals->gameNetworkState = GAME_NETWORK_TCP_UNCONNECTED;
|
||||
|
||||
do {
|
||||
waitForVbl();
|
||||
networkGlobals->initParams.waitForVbl();
|
||||
pollNetwork();
|
||||
cycleCount++;
|
||||
|
||||
if ((cycleCount & 0x7) == 0) {
|
||||
switch (cycleCount & 0x18) {
|
||||
case 0x00:
|
||||
uploadSpin1();
|
||||
if (networkGlobals->initParams.uploadSpin != NULL)
|
||||
networkGlobals->initParams.uploadSpin(0);
|
||||
break;
|
||||
|
||||
case 0x08:
|
||||
uploadSpin2();
|
||||
if (networkGlobals->initParams.uploadSpin != NULL)
|
||||
networkGlobals->initParams.uploadSpin(1);
|
||||
break;
|
||||
|
||||
case 0x10:
|
||||
uploadSpin3();
|
||||
if (networkGlobals->initParams.uploadSpin != NULL)
|
||||
networkGlobals->initParams.uploadSpin(2);
|
||||
break;
|
||||
|
||||
case 0x18:
|
||||
uploadSpin2();
|
||||
if (networkGlobals->initParams.uploadSpin != NULL)
|
||||
networkGlobals->initParams.uploadSpin(3);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -714,16 +723,9 @@ BOOLEAN sendHighScore(void)
|
|||
if (networkGlobals->gameNetworkState != GAME_NETWORK_TCP_UNCONNECTED)
|
||||
return FALSE;
|
||||
|
||||
sprintf(globalScoreInfo, " %u OF %u SCORES", networkGlobals->setHighScoreResponse.position, networkGlobals->setHighScoreResponse.numberOfScores);
|
||||
for (cycleCount = strlen(globalScoreInfo); cycleCount < sizeof(globalScoreInfo); cycleCount++) {
|
||||
globalScoreInfo[cycleCount] = ' ';
|
||||
}
|
||||
globalScoreInfo[GAME_NUM_TILES_WIDE] = '\0';
|
||||
displayScorePosition();
|
||||
|
||||
for (cycleCount = 4 * 60; cycleCount > 0; cycleCount--) {
|
||||
waitForVbl();
|
||||
}
|
||||
if (networkGlobals->initParams.scorePosition != NULL)
|
||||
networkGlobals->initParams.scorePosition(networkGlobals->setHighScoreResponse.position,
|
||||
networkGlobals->setHighScoreResponse.numberOfScores);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
#include <types.h>
|
||||
|
||||
#include "tileData.h"
|
||||
|
||||
typedef struct tHighScore
|
||||
{
|
||||
|
@ -21,23 +20,100 @@ typedef struct tHighScore
|
|||
unsigned long score;
|
||||
} tHighScore;
|
||||
|
||||
extern char globalScoreInfo[GAME_NUM_TILES_WIDE + 1];
|
||||
|
||||
extern unsigned int myUserId;
|
||||
typedef struct tHighScoreInitParams
|
||||
{
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
extern void initNetwork(void);
|
||||
/* This is the memory manager ID of the game. */
|
||||
unsigned int userId;
|
||||
|
||||
/* This is a Pascal string (not a C string) of the hostname of the score server to connect to. */
|
||||
const char * scoreServer;
|
||||
|
||||
/* This is the TCP port number of the score server to connect to. */
|
||||
unsigned int scorePort;
|
||||
|
||||
/* These two 32-bit values are the shared secrets used by the connect between the game and the score server
|
||||
which is used to try to reduce the amount of game score hacking.
|
||||
*/
|
||||
unsigned long secret1;
|
||||
unsigned long secret2;
|
||||
|
||||
|
||||
/* 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
|
||||
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
|
||||
TRUE and will always be called with FALSE sometime after that.
|
||||
*/
|
||||
void (*displayConnectionString)(BOOLEAN display);
|
||||
|
||||
/* This function should wait for the next VBL and is used to poll the network and limit upload time for a
|
||||
high score.
|
||||
*/
|
||||
void (*waitForVbl)(void);
|
||||
|
||||
/* 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
|
||||
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
|
||||
by the game.
|
||||
*/
|
||||
void (*uploadSpin)(int);
|
||||
|
||||
/* When a score is successfully uploaded to the server, this function will be called with the position
|
||||
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
|
||||
and that message should be cleaned up before the function returns to the caller. This function is
|
||||
called by sendHighScore().
|
||||
*/
|
||||
void (*scorePosition)(unsigned int position, unsigned int numberOfScores);
|
||||
} tHighScoreInitParams;
|
||||
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
extern void initNetwork(tHighScoreInitParams * params);
|
||||
|
||||
|
||||
/* 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.
|
||||
This function may call the waitForVbl() callback.
|
||||
*/
|
||||
extern void disconnectNetwork(void);
|
||||
extern void pollNetwork(void);
|
||||
extern void shutdownNetwork(void);
|
||||
extern BOOLEAN canSendHighScore(void);
|
||||
extern BOOLEAN sendHighScore(void);
|
||||
|
||||
// These are actually assembly functions called from the C code.
|
||||
extern void uploadSpin1(void);
|
||||
extern void uploadSpin2(void);
|
||||
extern void uploadSpin3(void);
|
||||
extern void displayConnectionString(void);
|
||||
extern void displayScorePosition(void);
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
extern void pollNetwork(void);
|
||||
|
||||
|
||||
/* Call this function once when the game is quitting. */
|
||||
extern void shutdownNetwork(void);
|
||||
|
||||
|
||||
/* 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
|
||||
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.
|
||||
*/
|
||||
extern BOOLEAN canSendHighScore(void);
|
||||
|
||||
|
||||
/* Assuming 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
|
||||
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
|
||||
waitForVbl(), uploadSpin() and scorePosition() callbacks may be called.
|
||||
|
||||
TODO - Pass the score as an argument rather than through globals.
|
||||
*/
|
||||
extern BOOLEAN sendHighScore(void);
|
||||
|
||||
|
||||
#endif /* define _GUARD_PROJECTBuGS_FILEglobalScores_ */
|
||||
|
|
63
BuGS/main.c
63
BuGS/main.c
|
@ -31,6 +31,9 @@
|
|||
unsigned int myUserId;
|
||||
unsigned int randomSeed;
|
||||
|
||||
// This symbol is used also from assembly directly so be careful with it...
|
||||
char globalScoreInfo[GAME_NUM_TILES_WIDE + 1];
|
||||
|
||||
|
||||
/* Implementation */
|
||||
|
||||
|
@ -43,9 +46,56 @@ word randomMushroomOffset(void)
|
|||
}
|
||||
|
||||
|
||||
void uploadSpin(int val)
|
||||
{
|
||||
switch (val)
|
||||
{
|
||||
case 0:
|
||||
uploadSpin1();
|
||||
break;
|
||||
|
||||
case 1:
|
||||
uploadSpin2();
|
||||
break;
|
||||
|
||||
case 2:
|
||||
uploadSpin3();
|
||||
break;
|
||||
|
||||
case 3:
|
||||
uploadSpin2();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void scorePosition(unsigned int position, unsigned int numberOfScores)
|
||||
{
|
||||
int i;
|
||||
|
||||
sprintf(globalScoreInfo, " %u OF %u SCORES", position, numberOfScores);
|
||||
for (i = strlen(globalScoreInfo); i < sizeof(globalScoreInfo); i++) {
|
||||
globalScoreInfo[i] = ' ';
|
||||
}
|
||||
globalScoreInfo[GAME_NUM_TILES_WIDE] = '\0';
|
||||
displayScorePosition();
|
||||
|
||||
for (i = 6 * 60; i > 0; i--) {
|
||||
waitForVbl();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void showConnectionString(BOOLEAN display)
|
||||
{
|
||||
if (display)
|
||||
displayConnectionString();
|
||||
}
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
static tHighScoreInitParams highScoreInitParams;
|
||||
int event;
|
||||
Ref toolStartupRef;
|
||||
|
||||
|
@ -73,7 +123,18 @@ int main(void)
|
|||
InitMouse(0);
|
||||
SetMouse(transparent);
|
||||
|
||||
initNetwork();
|
||||
highScoreInitParams.userId = myUserId;
|
||||
highScoreInitParams.scoreServer = "\p" NETWORK_SERVER;
|
||||
highScoreInitParams.scorePort = NETWORK_SERVERPORT;
|
||||
highScoreInitParams.secret1 = NETWORK_SERVERSECRET1;
|
||||
highScoreInitParams.secret2 = NETWORK_SERVERSECRET2;
|
||||
|
||||
highScoreInitParams.displayConnectionString = showConnectionString;
|
||||
highScoreInitParams.waitForVbl = waitForVbl;
|
||||
highScoreInitParams.uploadSpin = uploadSpin;
|
||||
highScoreInitParams.scorePosition = scorePosition;
|
||||
|
||||
initNetwork(&highScoreInitParams);
|
||||
|
||||
if (!loadSettings())
|
||||
saveSettings();
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#include <types.h>
|
||||
|
||||
|
||||
extern unsigned int myUserId;
|
||||
|
||||
extern void saveSettings(void);
|
||||
BOOLEAN loadSettings(void);
|
||||
extern void swapStereoSettings(void);
|
||||
|
|
Loading…
Reference in New Issue
Block a user