From 9bca2bc307f5d4398fd1f043d8ebd28571a0d538 Mon Sep 17 00:00:00 2001 From: Jeremy Rand Date: Fri, 23 Dec 2016 22:51:45 -0500 Subject: [PATCH] Modify options to allow enabling mockingboard and speech chip support. Hook up mockingboard and speech support. --- a2bejwld/sound.c | 244 ++++++++++++++++++++++++++++++++++++----------- a2bejwld/sound.h | 15 +++ a2bejwld/ui.c | 164 ++++++++++++++++++++++++++----- a2bejwld/ui.h | 3 - 4 files changed, 343 insertions(+), 83 deletions(-) diff --git a/a2bejwld/sound.c b/a2bejwld/sound.c index 2db6b80..52f5066 100644 --- a/a2bejwld/sound.c +++ b/a2bejwld/sound.c @@ -7,7 +7,6 @@ // #include "sound.h" -#include "ui.h" #include "mockingboard.h" #include @@ -112,81 +111,125 @@ static tMockingSoundRegisters gGemLandSound = { static uint8_t gSpeakGood[] = { - 0xE6, 0x7B, 0x68, 0x32, 0xE9, 0xE6, 0x7B, 0x68, - 0x32, 0xE6, 0xE6, 0x7B, 0x68, 0x32, 0x52, 0xE6, - 0x7B, 0x68, 0x32, 0x52, 0xE8, 0x7F, 0x48, 0x42, - 0x65, 0xE8, 0x7F, 0x48, 0x42, 0xC0 + 0xE8, 0x7B, 0x88, 0x3A, 0xE9, 0xE8, 0x7B, 0x88, + 0x3A, 0xE6, 0xE8, 0x7B, 0x88, 0x3A, 0x52, 0xE8, + 0x7B, 0x88, 0x3A, 0x52, 0xEA, 0x7F, 0x68, 0x4A, + 0x65, 0xEA, 0x7F, 0x68, 0x4A, 0xC0 }; static uint8_t gSpeakGo[] = { - 0xE6, 0x7B, 0x68, 0x32, 0xE9, 0xE6, 0x7B, 0x68, - 0x32, 0xE6, 0xE6, 0x7B, 0x68, 0x32, 0x11, 0xE6, - 0x7B, 0x68, 0x32, 0x63 + 0xE8, 0x7B, 0x88, 0x3A, 0xE9, 0xE8, 0x7B, 0x88, + 0x3A, 0xE6, 0xE8, 0x7B, 0x88, 0x3A, 0x11, 0xE8, + 0x7B, 0x88, 0x3A, 0x63 }; static uint8_t gSpeakLevelComplete[] = { - 0xE6, 0x7B, 0x68, 0x32, 0x60, 0xE6, 0x7B, 0x68, - 0x32, 0x0A, 0xE6, 0x7B, 0x68, 0x32, 0x33, 0xE6, - 0x7B, 0x68, 0x32, 0xEC, 0xE6, 0x7B, 0x68, 0x32, - 0x4A, 0xE6, 0x7B, 0x68, 0x32, 0x4A, 0xE6, 0x7B, - 0x68, 0x32, 0x60, 0xE6, 0x7B, 0x68, 0x32, 0x29, - 0xE6, 0x7B, 0x68, 0x32, 0xAD, 0xE6, 0x7B, 0x68, - 0x32, 0x5A, 0xE6, 0x7B, 0x68, 0x32, 0x5A, 0xE6, - 0x7B, 0x68, 0x32, 0x37, 0xE6, 0x7B, 0x68, 0x32, - 0x27, 0xE6, 0x7B, 0x68, 0x32, 0x60, 0xE6, 0x7B, - 0x68, 0x32, 0x01, 0xE6, 0x7B, 0x68, 0x32, 0x68, - 0xE6, 0x7B, 0x68, 0x32, 0xC0 + 0xE8, 0x7B, 0x88, 0x3A, 0x60, 0xE8, 0x7B, 0x88, + 0x3A, 0x0A, 0xE8, 0x7B, 0x88, 0x3A, 0x33, 0xE8, + 0x7B, 0x88, 0x3A, 0xEC, 0xE8, 0x7B, 0x88, 0x3A, + 0x4A, 0xE8, 0x7B, 0x88, 0x3A, 0x4A, 0xE8, 0x7B, + 0x88, 0x3A, 0x60, 0xE8, 0x7B, 0x88, 0x3A, 0x29, + 0xE8, 0x7B, 0x88, 0x3A, 0xAD, 0xE8, 0x7B, 0x88, + 0x3A, 0x5A, 0xE8, 0x7B, 0x88, 0x3A, 0x5A, 0xE8, + 0x7B, 0x88, 0x3A, 0x37, 0xE8, 0x7B, 0x88, 0x3A, + 0x27, 0xE8, 0x7B, 0x88, 0x3A, 0x60, 0xE8, 0x7B, + 0x88, 0x3A, 0x01, 0xE8, 0x7B, 0x88, 0x3A, 0x68, + 0xE8, 0x7B, 0x88, 0x3A, 0xC0 }; -static uint8_t gSpeakReady[] = { - 0xE6, 0x7B, 0x68, 0x32, 0xE6, 0xE6, 0x7B, 0x68, - 0x32, 0xC0, 0xE6, 0x7B, 0x68, 0x32, 0x0A, 0xE8, - 0x7F, 0x48, 0x42, 0x68, 0xE8, 0x7F, 0x48, 0x42, - 0xC0, 0xE6, 0x7B, 0x68, 0x32, 0x1D, 0xE6, 0x7B, - 0x68, 0x32, 0x4A, 0xE6, 0x7B, 0x68, 0x32, 0x4A, - 0xE6, 0x7B, 0x68, 0x32, 0x25, 0xE6, 0x7B, 0x68, - 0x32, 0x01 +static uint8_t gSpeakGetReady[] = { + 0xE8, 0x7B, 0x88, 0x3A, 0xE6, 0xE8, 0x7B, 0x88, + 0x3A, 0xC0, 0xE8, 0x7B, 0x88, 0x3A, 0x0A, 0xE8, + 0x7B, 0x88, 0x3A, 0x68, 0xE8, 0x7B, 0x88, 0x3A, + 0xC0, 0xE8, 0x7B, 0x88, 0x3A, 0x1D, 0xE8, 0x7B, + 0x88, 0x3A, 0x4A, 0xE8, 0x7B, 0x88, 0x3A, 0x4A, + 0xE8, 0x7B, 0x88, 0x3A, 0x25, 0xE8, 0x7B, 0x88, + 0x3A, 0x01 }; static uint8_t gSpeakNoMoreMoves[] = { - 0xE6, 0x7B, 0x68, 0x32, 0x78, 0xE6, 0x7B, 0x68, - 0x32, 0x11, 0xE6, 0x7B, 0x68, 0x32, 0x63, 0xE6, - 0x7B, 0x68, 0x32, 0x37, 0xE6, 0x7B, 0x68, 0x32, - 0x11, 0xE6, 0x7B, 0x68, 0x32, 0x5C, 0xE6, 0x7B, - 0x68, 0x32, 0x37, 0xE6, 0x7B, 0x68, 0x32, 0x16, - 0xE6, 0x7B, 0x68, 0x32, 0x33, 0xE6, 0x7B, 0x68, - 0x32, 0x2F + 0xE8, 0x7B, 0x88, 0x3A, 0x78, 0xE8, 0x7B, 0x88, + 0x3A, 0x11, 0xE8, 0x7B, 0x88, 0x3A, 0x63, 0xE8, + 0x7B, 0x88, 0x3A, 0x37, 0xE8, 0x7B, 0x88, 0x3A, + 0x11, 0xE8, 0x7B, 0x88, 0x3A, 0x5C, 0xE8, 0x7B, + 0x88, 0x3A, 0x37, 0xE8, 0x7B, 0x88, 0x3A, 0x16, + 0xE8, 0x7B, 0x88, 0x3A, 0x33, 0xE8, 0x7B, 0x88, + 0x3A, 0x2F }; static uint8_t gSpeakExcellent[] = { - 0xE6, 0x7B, 0x68, 0x32, 0x4A, 0xE6, 0x7B, 0x68, - 0x32, 0x29, 0xE6, 0x7B, 0x68, 0x32, 0x30, 0xE6, - 0x7B, 0x68, 0x32, 0x0A, 0xE6, 0x7B, 0x68, 0x32, - 0x4A, 0xE6, 0x7B, 0x68, 0x32, 0x60, 0xE6, 0x7B, - 0x68, 0x32, 0x60, 0xE6, 0x7B, 0x68, 0x32, 0x4A, - 0xE6, 0x7B, 0x68, 0x32, 0x4A, 0xE6, 0x7B, 0x68, - 0x32, 0x78, 0xE6, 0x7B, 0x68, 0x32, 0x68, 0xE6, - 0x7B, 0x68, 0x32, 0xC0 + 0xE8, 0x7B, 0x88, 0x3A, 0x4A, 0xE8, 0x7B, 0x88, + 0x3A, 0x29, 0xE8, 0x7B, 0x88, 0x3A, 0x30, 0xE8, + 0x7B, 0x88, 0x3A, 0x0A, 0xE8, 0x7B, 0x88, 0x3A, + 0x4A, 0xE8, 0x7B, 0x88, 0x3A, 0x60, 0xE8, 0x7B, + 0x88, 0x3A, 0x60, 0xE8, 0x7B, 0x88, 0x3A, 0x4A, + 0xE8, 0x7B, 0x88, 0x3A, 0x4A, 0xE8, 0x7B, 0x88, + 0x3A, 0x78, 0xEA, 0x7F, 0x68, 0x4A, 0x68, 0xEA, + 0x7F, 0x68, 0x4A, 0xC0 }; static uint8_t gSpeakIncredible[] = { - 0xE6, 0x7B, 0x68, 0x32, 0x47, 0xE6, 0x7B, 0x68, - 0x32, 0x78, 0xE6, 0x7B, 0x68, 0x32, 0x29, 0xE6, - 0x7B, 0x68, 0x32, 0x1D, 0xE6, 0x7B, 0x68, 0x32, - 0x0A, 0xE6, 0x7B, 0x68, 0x32, 0x65, 0xE6, 0x7B, - 0x68, 0x32, 0x1B, 0xE6, 0x7B, 0x68, 0x32, 0x64, - 0xE6, 0x7B, 0x68, 0x32, 0x60 + 0xE8, 0x7B, 0x88, 0x3A, 0x47, 0xE8, 0x7B, 0x88, + 0x3A, 0x78, 0xE8, 0x7B, 0x88, 0x3A, 0x29, 0xE8, + 0x7B, 0x88, 0x3A, 0x1D, 0xE8, 0x7B, 0x88, 0x3A, + 0x0A, 0xE8, 0x7B, 0x88, 0x3A, 0x65, 0xE8, 0x7B, + 0x88, 0x3A, 0x1B, 0xE8, 0x7B, 0x88, 0x3A, 0x64, + 0xE8, 0x7B, 0x88, 0x3A, 0x60 }; +static bool gSoundEnabled = false; +static bool gMockingBoardEnabled = false; +static bool gMockingBoardSpeechEnabled = false; + +static tMockingBoardSpeaker gMockingBoardSoundSpeaker = SPEAKER_BOTH; + + // Implementation + +void soundInit(tSlot mockingBoardSlot, bool enableSpeechChip) +{ + gSoundEnabled = true; + if (mockingBoardSlot > 0) { + mockingBoardInit(mockingBoardSlot, enableSpeechChip); + gMockingBoardEnabled = true; + gMockingBoardSpeechEnabled = enableSpeechChip; + // When the speech chip is on, sound effects go out the right speaker + // only and the left speaker is used for speech. If the speech chip is + // off, then sound effects go to both speakers. + if (enableSpeechChip) { + gMockingBoardSoundSpeaker = SPEAKER_RIGHT; + } else { + gMockingBoardSoundSpeaker = SPEAKER_BOTH; + } + } else { + if (gMockingBoardEnabled) { + mockingBoardShutdown(); + } + gMockingBoardEnabled = false; + gMockingBoardSpeechEnabled = false; + } +} + + +void soundShutdown(void) +{ + if (gMockingBoardEnabled) { + mockingBoardShutdown(); + gMockingBoardEnabled = false; + gMockingBoardSpeechEnabled = false; + } + gSoundEnabled = false; +} + + static void playSound(int8_t startFreq, int8_t duration) { int8_t freq; @@ -234,12 +277,12 @@ void playClearGemSound(uint8_t frame) static uint8_t *clearGemSoundFreq; static uint8_t *clearGemSoundDuration; - if (!soundEnabled()) + if (!gSoundEnabled) return; - if (mockingBoardEnabled()) { + if (gMockingBoardEnabled) { if (frame == 0) { - mockingBoardPlaySound(SPEAKER_BOTH, &(gClearGemMockSounds[gSoundClearGem])); + mockingBoardPlaySound(gMockingBoardSoundSpeaker, &(gClearGemMockSounds[gSoundClearGem])); } } else { if (frame == 0) { @@ -256,14 +299,107 @@ void playClearGemSound(uint8_t frame) void playLandingSound(uint8_t numLanded) { - if (!soundEnabled()) + if (!gSoundEnabled) return; - if (mockingBoardEnabled()) { + if (gMockingBoardEnabled) { if (numLanded == 0) { - mockingBoardPlaySound(SPEAKER_BOTH, &gGemLandSound); + mockingBoardPlaySound(gMockingBoardSoundSpeaker, &gGemLandSound); } } else { playSound(1, 1); } } + + +void speakGo(void) +{ + if (!gMockingBoardSpeechEnabled) + return; + + if (mockingBoardSpeechIsBusy()) { + while (mockingBoardSpeechIsPlaying()) + ; + } + + mockingBoardSpeak(gSpeakGo, sizeof(gSpeakGo)); +} + + +void speakLevelComplete(void) +{ + if (!gMockingBoardSpeechEnabled) + return; + + if (mockingBoardSpeechIsBusy()) { + while (mockingBoardSpeechIsPlaying()) + ; + } + + mockingBoardSpeak(gSpeakLevelComplete, sizeof(gSpeakLevelComplete)); +} + + +void speakGetReady(void) +{ + if (!gMockingBoardSpeechEnabled) + return; + + if (mockingBoardSpeechIsBusy()) { + while (mockingBoardSpeechIsPlaying()) + ; + } + + mockingBoardSpeak(gSpeakGetReady, sizeof(gSpeakGetReady)); +} + + +void speakNoMoreMoves(void) +{ + if (!gMockingBoardSpeechEnabled) + return; + + if (mockingBoardSpeechIsBusy()) { + while (mockingBoardSpeechIsPlaying()) + ; + } + + mockingBoardSpeak(gSpeakNoMoreMoves, sizeof(gSpeakNoMoreMoves)); +} + +bool speakGood(void) +{ + if (!gMockingBoardSpeechEnabled) + return true; + + if (mockingBoardSpeechIsBusy()) + return false; + + mockingBoardSpeak(gSpeakGood, sizeof(gSpeakGood)); + return true; +} + + +bool speakExcellent(void) +{ + if (!gMockingBoardSpeechEnabled) + return true; + + if (mockingBoardSpeechIsBusy()) + return false; + + mockingBoardSpeak(gSpeakExcellent, sizeof(gSpeakExcellent)); + return true; +} + +bool speakIncredible(void) +{ + if (!gMockingBoardSpeechEnabled) + return true; + + if (mockingBoardSpeechIsBusy()) + return false; + + mockingBoardSpeak(gSpeakIncredible, sizeof(gSpeakIncredible)); + return true; +} diff --git a/a2bejwld/sound.h b/a2bejwld/sound.h index 81cdd04..475bcc6 100644 --- a/a2bejwld/sound.h +++ b/a2bejwld/sound.h @@ -10,8 +10,14 @@ #define __a2bejwld__sound__ +#include #include +#include "mockingboard.h" + + +extern void soundInit(tSlot mockingBoardSlot, bool enableSpeechChip); +extern void soundShutdown(void); extern void beginClearGemSound(void); extern void playSoundForExplodingGem(void); @@ -21,5 +27,14 @@ extern void playClearGemSound(uint8_t frame); extern void playLandingSound(uint8_t numLanded); +extern void speakGo(void); +extern void speakLevelComplete(void); +extern void speakGetReady(void); +extern void speakNoMoreMoves(void); + +extern bool speakGood(void); +extern bool speakExcellent(void); +extern bool speakIncredible(void); + #endif /* defined(__a2bejwld__sound__) */ diff --git a/a2bejwld/ui.c b/a2bejwld/ui.c index 796b46a..18f8c8e 100644 --- a/a2bejwld/ui.c +++ b/a2bejwld/ui.c @@ -35,6 +35,8 @@ typedef struct tGameOptions { bool enableJoystick; bool enableMouse; bool enableSound; + tSlot mockingBoardSlot; + bool enableSpeechChip; } tGameOptions; @@ -94,29 +96,19 @@ static tMouseCallbacks gMouseCallbacks = { static bool gShouldSave = false; static tGameOptions gGameOptions = { - false, - false, - true, - true, + false, // optionsSaved + false, // enableJoystick + true, // enableMouse + true, // enableSound + 0, // mockingBoardSlot + false // enableSpeechChip }; // Implementation -bool soundEnabled(void) -{ - return gGameOptions.enableSound; -} - - -bool mockingBoardEnabled(void) -{ - return false; -} - - -void badThingHappened(void) +static void badThingHappened(void) { if (gGameOptions.enableSound) printf("\007"); @@ -130,7 +122,7 @@ static void showAndClearDblLoRes(void) } -void saveOptions(void) +static void saveOptions(void) { FILE *optionsFile = fopen(SAVE_OPTIONS_FILE, "wb"); @@ -142,7 +134,7 @@ void saveOptions(void) } -bool loadOptions(void) +static bool loadOptions(void) { FILE *optionsFile = fopen(SAVE_OPTIONS_FILE, "rb"); @@ -161,7 +153,7 @@ bool loadOptions(void) } -void applyNewOptions(tGameOptions *newOptions) +static void applyNewOptions(tGameOptions *newOptions) { bool oldEnableMouse = gGameOptions.enableMouse; @@ -170,6 +162,17 @@ void applyNewOptions(tGameOptions *newOptions) return; } + if ((gGameOptions.enableSound != newOptions->enableSound) || + (gGameOptions.mockingBoardSlot != newOptions->mockingBoardSlot) || + (gGameOptions.enableSpeechChip != gGameOptions.enableSpeechChip)) { + // If the sound parameters have changed, then re-init or shutdown sounds + if (newOptions->enableSound) { + soundInit(newOptions->mockingBoardSlot, newOptions->enableSpeechChip); + } else { + soundShutdown(); + } + } + memcpy(&gGameOptions, newOptions, sizeof(gGameOptions)); gGameOptions.optionsSaved = false; if (oldEnableMouse != gGameOptions.enableMouse) { @@ -181,7 +184,86 @@ void applyNewOptions(tGameOptions *newOptions) } -void selectOptions(void) +static void showCursor(void) +{ + revers(true); + cputc(' '); + revers(false); +} + + +static void replaceCursor(char ch) +{ + gotox(wherex() - 1); + cputc(ch); +} + + +static void getSoundOptions(tGameOptions *newOptions) +{ + char ch; + + cputs("\n\nEnable sounds? (Y/N) "); + showCursor(); + while (true) { + ch = cgetc(); + if ((ch == 'N') || + (ch == 'n')) { + newOptions->enableSound = false; + newOptions->mockingBoardSlot = 0; + newOptions->enableSpeechChip = false; + return; + } + if ((ch == 'Y') || + (ch == 'y')) { + replaceCursor(ch); + newOptions->enableSound = true; + break; + } + + badThingHappened(); + } + + cputs("\n\rMockingBoard slot number (0 for none) "); + showCursor(); + while (true) { + ch = cgetc(); + if (ch == '0') { + newOptions->mockingBoardSlot = 0; + newOptions->enableSpeechChip = false; + return; + } + if ((ch >= '1') && + (ch <= '7')) { + replaceCursor(ch); + newOptions->mockingBoardSlot = (ch - '0'); + break; + } + + badThingHappened(); + } + + cputs("\n\rMockingBoard has a speech chip? (Y/N) "); + showCursor(); + while (true) { + ch = cgetc(); + if ((ch == 'N') || + (ch == 'n')) { + newOptions->enableSpeechChip = false; + break; + } + if ((ch == 'Y') || + (ch == 'y')) { + newOptions->enableSpeechChip = true; + break; + } + + badThingHappened(); + } +} + + +static void selectOptions(void) { tGameOptions newOptions; @@ -201,14 +283,34 @@ void selectOptions(void) "\n" " J - Joystick control - %s\n" " M - Mouse control - %s\n" - " S - Sound - %s\n" - "\n" - " Type a letter to toggle a setting or any other key to save settings\n" - " and continue", + " S - Sound - %s\n", (newOptions.enableJoystick ? "Enable" : "Disabled"), (newOptions.enableMouse ? "Enable" : "Disabled"), (newOptions.enableSound ? "Enable" : "Disabled")); + if (newOptions.enableSound) { + if (newOptions.mockingBoardSlot > 0) { + printf( + // 0000000001111111111222222222233333333334444444444555555555566666666667 + // 1234567890123456789012345678901234567890123456789012345678901234567890 + " MockingBoard - Slot %u\n" + " Speech Chip - %s\n", + newOptions.mockingBoardSlot, + (newOptions.enableSpeechChip ? "Enable" : "Disable")); + } else { + printf( + // 0000000001111111111222222222233333333334444444444555555555566666666667 + // 1234567890123456789012345678901234567890123456789012345678901234567890 + " MockingBoard - Disabled\n"); + } + } + printf( + // 0000000001111111111222222222233333333334444444444555555555566666666667 + // 1234567890123456789012345678901234567890123456789012345678901234567890 + "\n" + " Type a letter to change a setting or any other key to save settings\n" + " and continue"); + switch (cgetc()) { case 'j': case 'J': @@ -228,7 +330,7 @@ void selectOptions(void) case 's': case 'S': - newOptions.enableSound = !newOptions.enableSound; + getSoundOptions(&newOptions); break; default: @@ -325,6 +427,7 @@ static void quitGame(void) videomode(VIDEOMODE_40x24); clrscr(); shutdownMouse(); + soundShutdown(); uninitMachine(); @@ -480,6 +583,8 @@ static void endGame(void) videomode(VIDEOMODE_80x24); mixedTextMode(); + speakNoMoreMoves(); + cputsxy(0, 0, " No more moves - GAME OVER!!"); gotoxy(0,1); cprintf( " You made it to level %u", getLevel()); @@ -523,6 +628,7 @@ static void refreshLevel(tLevel level) videomode(VIDEOMODE_80x24); mixedTextMode(); + speakLevelComplete(); gotoxy(0, 0); cprintf( " Completed level %u!!", level); @@ -541,6 +647,7 @@ static void refreshLevel(tLevel level) } showAndClearDblLoRes(); + speakGetReady(); } @@ -580,6 +687,10 @@ void initUI(void) initJoystick(&gJoyCallbacks); + if (gGameOptions.enableSound) { + soundInit(gGameOptions.mockingBoardSlot, gGameOptions.enableSpeechChip); + } + if (!gGameOptions.optionsSaved) { saveOptions(); } @@ -833,6 +944,7 @@ void playGame(void) startNewGame(); } drawBoard(); + speakGo(); while (true) { resetStarAnim(); diff --git a/a2bejwld/ui.h b/a2bejwld/ui.h index ed025e5..2dea01a 100644 --- a/a2bejwld/ui.h +++ b/a2bejwld/ui.h @@ -17,9 +17,6 @@ extern void initUI(void); -extern bool soundEnabled(void); -extern bool mockingBoardEnabled(void); - extern void printInstructions(void); extern void playGame(void);