mirror of
https://github.com/jeremysrand/a2bejwld.git
synced 2024-09-27 03:54:47 +00:00
Add code from Total Replay to detect the sound chip automatically on startup. This then leads to a complete rethinking about how to save/load the options for the game. It used to ask what slot the mockingboard was in (if any) and whether it had a speech chip. Now, the game should just know this information. So, I turned the first boolean in the save file into an options file version byte and bumped it to "2". The boolean was always true and was kind of a very simple "magic number" to say that the contents was valid. Now it is a version number of the contents. The slot number and boolean for the speech chip is are now each turned into booleans - one to say whether to enable a mockingboard if found and the other to enable the speech chip if found.
This means there are three booleans in the options related to sound now. The first one enables/disables sound entirely and is default on. The second is only relevant if the sound is enabled and says "use a mockingboard if present". Again this is true by default. Finally, the this says "use a speech chip on the mockingboard if present" and is only relevant if the mockingboard is also enabled. So, the basic approach now is to default the "best" sound options and auto-detect the sound HW at launch. The user can then use the options to downgrade their sound all the way to basic Apple // sound or turn off the sound entirely.
This commit is contained in:
parent
72fc265e5a
commit
20ad7dda1c
Binary file not shown.
@ -71,7 +71,6 @@ SRCDIRS+=
|
|||||||
|
|
||||||
# If you want to add arguments to the compile commandline, add them
|
# If you want to add arguments to the compile commandline, add them
|
||||||
# to this variable:
|
# to this variable:
|
||||||
# CFLAGS += -DTOTAL_REPLAY_BUILD
|
|
||||||
CFLAGS += -Os
|
CFLAGS += -Os
|
||||||
|
|
||||||
# If you want to add arguments to the assembly commandline, add them
|
# If you want to add arguments to the assembly commandline, add them
|
||||||
|
@ -16,20 +16,8 @@
|
|||||||
|
|
||||||
// Implementation
|
// Implementation
|
||||||
|
|
||||||
#ifdef TOTAL_REPLAY_BUILD
|
|
||||||
void totalReplayQuit(void)
|
|
||||||
{
|
|
||||||
__asm__ ("BIT $C082");
|
|
||||||
__asm__ ("JMP $100");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
#ifdef TOTAL_REPLAY_BUILD
|
|
||||||
atexit(totalReplayQuit);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
initUI();
|
initUI();
|
||||||
|
|
||||||
printInstructions();
|
printInstructions();
|
||||||
|
@ -46,6 +46,9 @@ static uint8_t *gMockDataDirA[NUM_SOUND_CHIPS] = { (uint8_t *)0xc003, (uint8_t *
|
|||||||
|
|
||||||
static uint8_t gMockingBoardInitialized = false;
|
static uint8_t gMockingBoardInitialized = false;
|
||||||
static uint8_t gMockingBoardSpeechInitialized = false;
|
static uint8_t gMockingBoardSpeechInitialized = false;
|
||||||
|
static uint8_t gMockingBoardSearchDone = false;
|
||||||
|
static tSlot gMockingBoardSlot = 0;
|
||||||
|
static bool gMockingBoardHasSpeech = false;
|
||||||
|
|
||||||
|
|
||||||
// Implementation
|
// Implementation
|
||||||
@ -64,29 +67,47 @@ static uint8_t *mapIOPointer(tSlot slot, uint8_t *ptr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void mockingBoardInit(tSlot slot, bool hasSpeechChip)
|
bool mockingBoardInit(void)
|
||||||
{
|
{
|
||||||
tMockingBoardSoundChip soundChip;
|
tMockingBoardSoundChip soundChip;
|
||||||
|
|
||||||
|
if (!gMockingBoardSearchDone)
|
||||||
|
{
|
||||||
|
gMockingBoardSlot = getMockingBoardSlot();
|
||||||
|
|
||||||
|
if ((gMockingBoardSlot & 0x80) != 0)
|
||||||
|
gMockingBoardHasSpeech = true;
|
||||||
|
|
||||||
|
gMockingBoardSlot &= 0x7;
|
||||||
|
|
||||||
|
gMockingBoardSearchDone = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gMockingBoardSlot == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (gMockingBoardInitialized)
|
||||||
|
return true;
|
||||||
|
|
||||||
if (sizeof(tMockingSoundRegisters) != 16) {
|
if (sizeof(tMockingSoundRegisters) != 16) {
|
||||||
printf("The sound registers must be 16 bytes long!\n");
|
printf("The sound registers must be 16 bytes long!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (soundChip = SOUND_CHIP_1; soundChip < NUM_SOUND_CHIPS; soundChip++) {
|
for (soundChip = SOUND_CHIP_1; soundChip < NUM_SOUND_CHIPS; soundChip++) {
|
||||||
gMockPortB[soundChip] = mapIOPointer(slot, gMockPortB[soundChip]);
|
gMockPortB[soundChip] = mapIOPointer(gMockingBoardSlot, gMockPortB[soundChip]);
|
||||||
gMockPortA[soundChip] = mapIOPointer(slot, gMockPortA[soundChip]);
|
gMockPortA[soundChip] = mapIOPointer(gMockingBoardSlot, gMockPortA[soundChip]);
|
||||||
gMockDataDirB[soundChip] = mapIOPointer(slot, gMockDataDirB[soundChip]);
|
gMockDataDirB[soundChip] = mapIOPointer(gMockingBoardSlot, gMockDataDirB[soundChip]);
|
||||||
gMockDataDirA[soundChip] = mapIOPointer(slot, gMockDataDirA[soundChip]);
|
gMockDataDirA[soundChip] = mapIOPointer(gMockingBoardSlot, gMockDataDirA[soundChip]);
|
||||||
|
|
||||||
*(gMockDataDirA[soundChip]) = 0xff; // Set port A for output
|
*(gMockDataDirA[soundChip]) = 0xff; // Set port A for output
|
||||||
*(gMockDataDirB[soundChip]) = 0x7; // Set port B for output
|
*(gMockDataDirB[soundChip]) = 0x7; // Set port B for output
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasSpeechChip) {
|
if (gMockingBoardHasSpeech) {
|
||||||
if (gMockingBoardSpeechInitialized) {
|
if (gMockingBoardSpeechInitialized) {
|
||||||
mockingBoardSpeechShutdown();
|
mockingBoardSpeechShutdown();
|
||||||
}
|
}
|
||||||
mockingBoardSpeechInit(slot);
|
mockingBoardSpeechInit(gMockingBoardSlot);
|
||||||
gMockingBoardSpeechInitialized = true;
|
gMockingBoardSpeechInitialized = true;
|
||||||
} else if (gMockingBoardSpeechInitialized) {
|
} else if (gMockingBoardSpeechInitialized) {
|
||||||
mockingBoardSpeechShutdown();
|
mockingBoardSpeechShutdown();
|
||||||
@ -94,6 +115,7 @@ void mockingBoardInit(tSlot slot, bool hasSpeechChip)
|
|||||||
}
|
}
|
||||||
|
|
||||||
gMockingBoardInitialized = true;
|
gMockingBoardInitialized = true;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -108,6 +130,18 @@ void mockingBoardShutdown(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
tSlot mockingBoardSlot(void)
|
||||||
|
{
|
||||||
|
return gMockingBoardSlot;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool mockingBoardHasSpeechChip(void)
|
||||||
|
{
|
||||||
|
return gMockingBoardHasSpeech;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void writeCommand(tMockingBoardSoundChip soundChip, uint8_t command)
|
static void writeCommand(tMockingBoardSoundChip soundChip, uint8_t command)
|
||||||
{
|
{
|
||||||
volatile uint8_t *ptr = gMockPortB[soundChip];
|
volatile uint8_t *ptr = gMockPortB[soundChip];
|
||||||
|
@ -117,13 +117,15 @@ typedef struct tMockingSoundRegisters {
|
|||||||
|
|
||||||
// API
|
// API
|
||||||
|
|
||||||
extern uint8_t getMockingBoardSlot(void);
|
extern bool mockingBoardInit(void);
|
||||||
extern void mockingBoardInit(tSlot slot, bool hasSpeechChip);
|
|
||||||
extern void mockingBoardShutdown(void);
|
extern void mockingBoardShutdown(void);
|
||||||
|
|
||||||
|
extern tSlot mockingBoardSlot(void);
|
||||||
|
|
||||||
extern void mockingBoardPlaySound(tMockingBoardSpeaker speaker, tMockingSoundRegisters *registers);
|
extern void mockingBoardPlaySound(tMockingBoardSpeaker speaker, tMockingSoundRegisters *registers);
|
||||||
extern void mockingBoardStopSound(tMockingBoardSpeaker speaker);
|
extern void mockingBoardStopSound(tMockingBoardSpeaker speaker);
|
||||||
|
|
||||||
|
extern bool mockingBoardHasSpeechChip(void);
|
||||||
extern bool mockingBoardSpeechIsBusy(void);
|
extern bool mockingBoardSpeechIsBusy(void);
|
||||||
extern bool mockingBoardSpeechIsPlaying(void);
|
extern bool mockingBoardSpeechIsPlaying(void);
|
||||||
extern bool mockingBoardSpeak(uint8_t *data, uint16_t dataLen);
|
extern bool mockingBoardSpeak(uint8_t *data, uint16_t dataLen);
|
||||||
|
@ -18,6 +18,7 @@ extern uint16_t mockingBoardSpeechLen;
|
|||||||
extern uint8_t mockingBoardSpeechBusy;
|
extern uint8_t mockingBoardSpeechBusy;
|
||||||
extern uint8_t mockingBoardSpeechPlaying;
|
extern uint8_t mockingBoardSpeechPlaying;
|
||||||
|
|
||||||
|
extern uint8_t getMockingBoardSlot(void);
|
||||||
extern void mockingBoardSpeechInit(uint8_t slot);
|
extern void mockingBoardSpeechInit(uint8_t slot);
|
||||||
extern void mockingBoardSpeechShutdown(void);
|
extern void mockingBoardSpeechShutdown(void);
|
||||||
extern void mockingBoardSpeakPriv(void);
|
extern void mockingBoardSpeakPriv(void);
|
||||||
|
@ -74,37 +74,128 @@ readChip:
|
|||||||
; in: none
|
; in: none
|
||||||
; accelerators should be off
|
; accelerators should be off
|
||||||
; out:
|
; out:
|
||||||
; if card was found, A = #$n where n is the slot number of the card, otherwise #$00
|
; if card was found, A = #$?n where n is the slot number of the card, otherwise #$00
|
||||||
|
; and bit 6 = 0 if Mockingboard Sound I found
|
||||||
|
; or bit 6 = 1 if Mockingboard Sound II or "A" found
|
||||||
|
; and bit 7 = 1 if Mockingboard Sound/Speech I or "C" found
|
||||||
; flags clobbered
|
; flags clobbered
|
||||||
; zp $80-$82 clobbered
|
; zp $80-$82 clobbered
|
||||||
; (jrand - and then restored because I am chicken and afraid of breaking cc65 runtime)
|
; (jrand - and then restored because I am chicken and afraid of breaking cc65 runtime)
|
||||||
; X/Y clobbered
|
; X/Y clobbered
|
||||||
;------------------------------------------------------------------------------
|
;------------------------------------------------------------------------------
|
||||||
.proc _getMockingBoardSlot
|
.proc _getMockingBoardSlot
|
||||||
|
php
|
||||||
lda $80
|
lda $80
|
||||||
sta zp80Backup
|
sta zp80Backup
|
||||||
lda $81
|
lda $81
|
||||||
sta zp81Backup
|
sta zp81Backup
|
||||||
lda $82
|
lda $82
|
||||||
sta zp82Backup
|
sta zp82Backup
|
||||||
|
lda $3fe
|
||||||
|
sta irq1Backup
|
||||||
|
lda $3ff
|
||||||
|
sta irq2Backup
|
||||||
|
|
||||||
lda #$00
|
lda #$00
|
||||||
sta $80
|
sta $80
|
||||||
ldx #$C7
|
sta $82 ; type
|
||||||
|
ldx #$C1
|
||||||
@slotLoop:
|
@slotLoop:
|
||||||
stx $81
|
stx $81
|
||||||
ldy #$04 ; 6522 #1 $Cx04
|
ldy #$04 ; 6522 #1 $Cx04
|
||||||
jsr timercheck
|
jsr @timercheck
|
||||||
bne @nextSlot
|
beq @foundI
|
||||||
ldy #$84 ; 6522 #2 $Cx84
|
inx
|
||||||
jsr timercheck
|
cpx #$C8
|
||||||
bne @nextSlot
|
|
||||||
beq @cleanup
|
|
||||||
@nextSlot:
|
|
||||||
dex
|
|
||||||
cpx #$C0
|
|
||||||
bne @slotLoop
|
bne @slotLoop
|
||||||
ldx #$00 ; not found
|
ldx #00 ; not found
|
||||||
|
jmp @cleanup
|
||||||
|
|
||||||
|
@foundI: ; sound I or better
|
||||||
|
ldy #$84 ; 6522 #2 $Cx84
|
||||||
|
jsr @timercheck
|
||||||
|
beq @foundII
|
||||||
|
|
||||||
|
ldy #$0C
|
||||||
|
sty @mb_smc3 + 1
|
||||||
|
iny
|
||||||
|
sty @mb_smc8 + 1
|
||||||
|
iny
|
||||||
|
sty @mb_smc7 + 1
|
||||||
|
sty @mb_smc11 + 1
|
||||||
|
|
||||||
|
.BYTE $2C ; Hide next 2 bytes using a BIT opcode
|
||||||
|
@foundII: ; stereo
|
||||||
|
ror $82
|
||||||
|
|
||||||
|
lda $81
|
||||||
|
sta @mb_smc1 + 2
|
||||||
|
sta @mb_smc2 + 2
|
||||||
|
sta @mb_smc3 + 2
|
||||||
|
sta @mb_smc4 + 2
|
||||||
|
sta @mb_smc5 + 2
|
||||||
|
sta @mb_smc6 + 2
|
||||||
|
sta @mb_smc7 + 2
|
||||||
|
sta @mb_smc8 + 2
|
||||||
|
sta @mb_smc9 + 2
|
||||||
|
sta @mb_smc10 + 2
|
||||||
|
sta @mb_smc11 + 2
|
||||||
|
sta @mb_smc12 + 2
|
||||||
|
sta @mb_smc13 + 2
|
||||||
|
|
||||||
|
; detect speech chip
|
||||||
|
|
||||||
|
sei
|
||||||
|
lda #<@mb_irq
|
||||||
|
sta $3fe
|
||||||
|
lda #>@mb_irq
|
||||||
|
sta $3ff
|
||||||
|
|
||||||
|
lda #0
|
||||||
|
@mb_smc1:
|
||||||
|
sta $c403
|
||||||
|
@mb_smc2:
|
||||||
|
sta $c402
|
||||||
|
lda #$0c
|
||||||
|
@mb_smc3:
|
||||||
|
sta $c48c
|
||||||
|
lda #$80
|
||||||
|
@mb_smc4:
|
||||||
|
sta $c443
|
||||||
|
lda #$c0
|
||||||
|
@mb_smc5:
|
||||||
|
sta $c440
|
||||||
|
lda #$70
|
||||||
|
@mb_smc6:
|
||||||
|
sta $c443
|
||||||
|
lda #$82
|
||||||
|
@mb_smc7:
|
||||||
|
sta $c48e
|
||||||
|
|
||||||
|
ldx #0
|
||||||
|
ldy #0
|
||||||
|
sec
|
||||||
|
cli
|
||||||
|
|
||||||
|
@wait_irq:
|
||||||
|
lda $80
|
||||||
|
bne @got_irq
|
||||||
|
iny
|
||||||
|
bne @wait_irq
|
||||||
|
inx
|
||||||
|
bne @wait_irq
|
||||||
|
clc
|
||||||
|
|
||||||
|
@got_irq:
|
||||||
|
|
||||||
|
sei
|
||||||
|
ror $82
|
||||||
|
|
||||||
|
lda $81
|
||||||
|
and #7
|
||||||
|
ora $82
|
||||||
|
tax
|
||||||
|
|
||||||
@cleanup:
|
@cleanup:
|
||||||
lda zp80Backup
|
lda zp80Backup
|
||||||
sta $80
|
sta $80
|
||||||
@ -112,25 +203,53 @@ readChip:
|
|||||||
sta $81
|
sta $81
|
||||||
lda zp82Backup
|
lda zp82Backup
|
||||||
sta $82
|
sta $82
|
||||||
|
lda irq1Backup
|
||||||
|
sta $3fe
|
||||||
|
lda irq2Backup
|
||||||
|
sta $3ff
|
||||||
txa
|
txa
|
||||||
and #$07
|
|
||||||
ldx #$00
|
ldx #$00
|
||||||
|
plp
|
||||||
rts
|
rts
|
||||||
|
|
||||||
timercheck:
|
@timercheck:
|
||||||
lda ($80),y ; read 6522 timer low byte
|
|
||||||
sta $82
|
|
||||||
lda ($80),y ; second time
|
|
||||||
sec
|
sec
|
||||||
sbc $82
|
lda ($80),y ; read 6522 timer low byte
|
||||||
cmp #$F8 ; looking for (-)8 cycles between reads
|
sbc ($80),y ; second time
|
||||||
|
cmp #5 ; looking for (-)8 cycles between reads
|
||||||
beq :+
|
beq :+
|
||||||
cmp #$F7 ; FastChip //e clock is different
|
cmp #6 ; FastChip //e clock is different
|
||||||
: rts
|
: rts
|
||||||
|
|
||||||
|
@mb_irq:
|
||||||
|
lda #2
|
||||||
|
@mb_smc8:
|
||||||
|
sta $c48d
|
||||||
|
lda #0
|
||||||
|
@mb_smc9:
|
||||||
|
sta $c440
|
||||||
|
lda #$70
|
||||||
|
@mb_smc10:
|
||||||
|
sta $c443
|
||||||
|
sta $80
|
||||||
|
lda #2
|
||||||
|
@mb_smc11:
|
||||||
|
sta $c48e
|
||||||
|
lda #$ff
|
||||||
|
@mb_smc12:
|
||||||
|
sta $c403
|
||||||
|
lda #7
|
||||||
|
@mb_smc13:
|
||||||
|
sta $c402
|
||||||
|
lda $45
|
||||||
|
rti
|
||||||
|
|
||||||
; Locals
|
; Locals
|
||||||
zp80Backup: .BYTE $00
|
zp80Backup: .BYTE $00
|
||||||
zp81Backup: .BYTE $00
|
zp81Backup: .BYTE $00
|
||||||
zp82Backup: .BYTE $00
|
zp82Backup: .BYTE $00
|
||||||
|
irq1Backup: .BYTE $00
|
||||||
|
irq2Backup: .BYTE $00
|
||||||
.endproc
|
.endproc
|
||||||
|
|
||||||
|
|
||||||
|
@ -185,6 +185,7 @@ static uint8_t gSpeakIncredible[] = {
|
|||||||
|
|
||||||
|
|
||||||
static bool gSoundEnabled = false;
|
static bool gSoundEnabled = false;
|
||||||
|
static bool gMockingBoardInitialized = false;
|
||||||
static bool gMockingBoardEnabled = false;
|
static bool gMockingBoardEnabled = false;
|
||||||
static bool gMockingBoardSpeechEnabled = false;
|
static bool gMockingBoardSpeechEnabled = false;
|
||||||
|
|
||||||
@ -194,35 +195,30 @@ static tMockingBoardSpeaker gMockingBoardSoundSpeaker = SPEAKER_BOTH;
|
|||||||
// Implementation
|
// Implementation
|
||||||
|
|
||||||
|
|
||||||
void soundInit(tSlot mockingBoardSlot, bool enableSpeechChip)
|
void soundInit(bool enableSounds, bool enableMockingBoard, bool enableSpeechChip)
|
||||||
{
|
{
|
||||||
gSoundEnabled = true;
|
gMockingBoardInitialized = mockingBoardInit();
|
||||||
if (mockingBoardSlot > 0) {
|
gSoundEnabled = enableSounds;
|
||||||
mockingBoardInit(mockingBoardSlot, enableSpeechChip);
|
|
||||||
gMockingBoardEnabled = true;
|
gMockingBoardEnabled = ((gSoundEnabled) && (gMockingBoardInitialized) && (enableMockingBoard));
|
||||||
gMockingBoardSpeechEnabled = enableSpeechChip;
|
gMockingBoardSpeechEnabled = ((enableSpeechChip) && (gMockingBoardEnabled) && (mockingBoardHasSpeechChip()));
|
||||||
|
|
||||||
// When the speech chip is on, sound effects go out the right speaker
|
// 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
|
// only and the left speaker is used for speech. If the speech chip is
|
||||||
// off, then sound effects go to both speakers.
|
// off, then sound effects go to both speakers.
|
||||||
if (enableSpeechChip) {
|
if (gMockingBoardSpeechEnabled) {
|
||||||
gMockingBoardSoundSpeaker = SPEAKER_RIGHT;
|
gMockingBoardSoundSpeaker = SPEAKER_RIGHT;
|
||||||
} else {
|
} else {
|
||||||
gMockingBoardSoundSpeaker = SPEAKER_BOTH;
|
gMockingBoardSoundSpeaker = SPEAKER_BOTH;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if (gMockingBoardEnabled) {
|
|
||||||
mockingBoardShutdown();
|
|
||||||
}
|
|
||||||
gMockingBoardEnabled = false;
|
|
||||||
gMockingBoardSpeechEnabled = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void soundShutdown(void)
|
void soundShutdown(void)
|
||||||
{
|
{
|
||||||
if (gMockingBoardEnabled) {
|
if (gMockingBoardInitialized) {
|
||||||
mockingBoardShutdown();
|
mockingBoardShutdown();
|
||||||
|
gMockingBoardInitialized = false;
|
||||||
gMockingBoardEnabled = false;
|
gMockingBoardEnabled = false;
|
||||||
gMockingBoardSpeechEnabled = false;
|
gMockingBoardSpeechEnabled = false;
|
||||||
}
|
}
|
||||||
@ -367,6 +363,7 @@ void speakNoMoreMoves(void)
|
|||||||
mockingBoardSpeak(gSpeakNoMoreMoves, sizeof(gSpeakNoMoreMoves));
|
mockingBoardSpeak(gSpeakNoMoreMoves, sizeof(gSpeakNoMoreMoves));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool speakGood(void)
|
bool speakGood(void)
|
||||||
{
|
{
|
||||||
if (!gMockingBoardSpeechEnabled)
|
if (!gMockingBoardSpeechEnabled)
|
||||||
@ -392,6 +389,7 @@ bool speakExcellent(void)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool speakIncredible(void)
|
bool speakIncredible(void)
|
||||||
{
|
{
|
||||||
if (!gMockingBoardSpeechEnabled)
|
if (!gMockingBoardSpeechEnabled)
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
#include "mockingboard.h"
|
#include "mockingboard.h"
|
||||||
|
|
||||||
|
|
||||||
extern void soundInit(tSlot mockingBoardSlot, bool enableSpeechChip);
|
extern void soundInit(bool enableSounds, bool enableMockingBoard, bool enableSpeechChip);
|
||||||
extern void soundShutdown(void);
|
extern void soundShutdown(void);
|
||||||
|
|
||||||
extern void beginClearGemSound(void);
|
extern void beginClearGemSound(void);
|
||||||
|
214
a2bejwld/ui.c
214
a2bejwld/ui.c
@ -26,24 +26,20 @@
|
|||||||
// Defines
|
// Defines
|
||||||
|
|
||||||
#define SAVE_OPTIONS_FILE "A2BEJWLD.OPTS"
|
#define SAVE_OPTIONS_FILE "A2BEJWLD.OPTS"
|
||||||
#define BASE_VERSION "v2.3"
|
#define VERSION "v2.4.a3"
|
||||||
|
|
||||||
#ifdef TOTAL_REPLAY_BUILD
|
|
||||||
#define VERSION BASE_VERSION ".tr"
|
|
||||||
#else
|
|
||||||
#define VERSION BASE_VERSION
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
#define OPTIONS_VERSION_UNSAVED 0
|
||||||
|
#define OPTIONS_VERSION 2
|
||||||
|
|
||||||
// Typedefs
|
// Typedefs
|
||||||
|
|
||||||
typedef struct tGameOptions {
|
typedef struct tGameOptions {
|
||||||
bool optionsSaved;
|
uint8_t optionsVersion;
|
||||||
bool enableJoystick;
|
bool enableJoystick;
|
||||||
bool enableMouse;
|
bool enableMouse;
|
||||||
bool enableSound;
|
bool enableSound;
|
||||||
tSlot mockingBoardSlot;
|
bool enableMockingboard;
|
||||||
bool enableSpeechChip;
|
bool enableMockingboardSpeech;
|
||||||
} tGameOptions;
|
} tGameOptions;
|
||||||
|
|
||||||
|
|
||||||
@ -107,12 +103,12 @@ static tMouseCallbacks gMouseCallbacks = {
|
|||||||
static bool gShouldSave = false;
|
static bool gShouldSave = false;
|
||||||
|
|
||||||
static tGameOptions gGameOptions = {
|
static tGameOptions gGameOptions = {
|
||||||
false, // optionsSaved
|
OPTIONS_VERSION_UNSAVED, // optionsVersion
|
||||||
false, // enableJoystick
|
false, // enableJoystick
|
||||||
true, // enableMouse
|
true, // enableMouse
|
||||||
true, // enableSound
|
true, // enableSound
|
||||||
0, // mockingBoardSlot
|
true, // enableMockingboard
|
||||||
false // enableSpeechChip
|
true // enableMockingboardSpeech
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -161,7 +157,7 @@ static void saveOptions(void)
|
|||||||
FILE *optionsFile = fopen(SAVE_OPTIONS_FILE, "wb");
|
FILE *optionsFile = fopen(SAVE_OPTIONS_FILE, "wb");
|
||||||
|
|
||||||
if (optionsFile != NULL) {
|
if (optionsFile != NULL) {
|
||||||
gGameOptions.optionsSaved = true;
|
gGameOptions.optionsVersion = OPTIONS_VERSION;
|
||||||
fwrite(&gGameOptions, sizeof(gGameOptions), 1, optionsFile);
|
fwrite(&gGameOptions, sizeof(gGameOptions), 1, optionsFile);
|
||||||
fclose(optionsFile);
|
fclose(optionsFile);
|
||||||
}
|
}
|
||||||
@ -183,6 +179,17 @@ static bool loadOptions(void)
|
|||||||
|
|
||||||
fclose(optionsFile);
|
fclose(optionsFile);
|
||||||
|
|
||||||
|
// If we are upgrading from v1 of the options file, then:
|
||||||
|
// - There used to be a tSlot of the mockingboard where we now have the enableMockingboard boolean.
|
||||||
|
// Overwrite it with true, forcing mockingboard sound to be on if one is detected.
|
||||||
|
// - There used to be a boolean to enable/disable the speech chip on the mockingboard. It was only
|
||||||
|
// true if the user enabled it. Now that we can detect the speech chip, the value is default true
|
||||||
|
// and the user can disable speech if they want.
|
||||||
|
if (gGameOptions < OPTIONS_VERSION) {
|
||||||
|
gGameOptions.enableMockingboard = true;
|
||||||
|
gGameOptions.enableMockingboardSpeech = true;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,19 +203,17 @@ static void applyNewOptions(tGameOptions *newOptions)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printString("\n\n\n Saving options...");
|
||||||
|
|
||||||
if ((gGameOptions.enableSound != newOptions->enableSound) ||
|
if ((gGameOptions.enableSound != newOptions->enableSound) ||
|
||||||
(gGameOptions.mockingBoardSlot != newOptions->mockingBoardSlot) ||
|
(gGameOptions.enableMockingboard != newOptions->enableMockingboard) ||
|
||||||
(gGameOptions.enableSpeechChip != gGameOptions.enableSpeechChip)) {
|
(gGameOptions.enableMockingboardSpeech != newOptions->enableMockingboardSpeech)) {
|
||||||
// If the sound parameters have changed, then re-init or shutdown sounds
|
// If the sound parameters have changed, then re-init sounds
|
||||||
if (newOptions->enableSound) {
|
soundInit(newOptions->enableSound, newOptions->enableMockingboard, newOptions->enableMockingboardSpeech);
|
||||||
soundInit(newOptions->mockingBoardSlot, newOptions->enableSpeechChip);
|
|
||||||
} else {
|
|
||||||
soundShutdown();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(&gGameOptions, newOptions, sizeof(gGameOptions));
|
memcpy(&gGameOptions, newOptions, sizeof(gGameOptions));
|
||||||
gGameOptions.optionsSaved = false;
|
gGameOptions.optionsVersion = OPTIONS_VERSION_UNSAVED;
|
||||||
if (oldEnableMouse != gGameOptions.enableMouse) {
|
if (oldEnableMouse != gGameOptions.enableMouse) {
|
||||||
if (gGameOptions.enableMouse) {
|
if (gGameOptions.enableMouse) {
|
||||||
gGameOptions.enableMouse = initMouse(&gMouseCallbacks);
|
gGameOptions.enableMouse = initMouse(&gMouseCallbacks);
|
||||||
@ -231,67 +236,62 @@ static void replaceCursor(char ch)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void getSoundOptions(tGameOptions *newOptions)
|
static bool yorn(void)
|
||||||
{
|
{
|
||||||
char ch;
|
char ch;
|
||||||
|
bool result = true;
|
||||||
|
|
||||||
|
showCursor();
|
||||||
|
while (true) {
|
||||||
|
ch = cgetc();
|
||||||
|
|
||||||
|
if ((ch == 'N') ||
|
||||||
|
(ch == 'n')) {
|
||||||
|
result = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ch == 'Y') ||
|
||||||
|
(ch == 'y'))
|
||||||
|
break;
|
||||||
|
|
||||||
|
badThingHappened();
|
||||||
|
}
|
||||||
|
|
||||||
|
replaceCursor(ch);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void getSoundOptions(tGameOptions *newOptions)
|
||||||
|
{
|
||||||
|
tSlot slot;
|
||||||
|
|
||||||
printString("\n\nEnable sounds? (Y/N) ");
|
printString("\n\nEnable sounds? (Y/N) ");
|
||||||
showCursor();
|
newOptions->enableSound = yorn();
|
||||||
while (true) {
|
if (!newOptions->enableSound)
|
||||||
ch = cgetc();
|
|
||||||
if ((ch == 'N') ||
|
|
||||||
(ch == 'n')) {
|
|
||||||
newOptions->enableSound = false;
|
|
||||||
newOptions->mockingBoardSlot = 0;
|
|
||||||
newOptions->enableSpeechChip = false;
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
if ((ch == 'Y') ||
|
|
||||||
(ch == 'y')) {
|
|
||||||
replaceCursor(ch);
|
|
||||||
newOptions->enableSound = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
badThingHappened();
|
// If no mockingboard present, don't bother to ask whether to enable/disable it.
|
||||||
}
|
slot = mockingBoardSlot();
|
||||||
|
if (slot == 0)
|
||||||
printString("\nMockingBoard slot number (0 for none) ");
|
|
||||||
showCursor();
|
|
||||||
while (true) {
|
|
||||||
ch = cgetc();
|
|
||||||
if (ch == '0') {
|
|
||||||
newOptions->mockingBoardSlot = 0;
|
|
||||||
newOptions->enableSpeechChip = false;
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
if ((ch >= '1') &&
|
|
||||||
(ch <= '7')) {
|
|
||||||
replaceCursor(ch);
|
|
||||||
newOptions->mockingBoardSlot = (ch - '0');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
badThingHappened();
|
printString("\nEnable MockingBoard sound found in slot ");
|
||||||
}
|
printInteger(slot);
|
||||||
|
printString("? (Y/N) ");
|
||||||
|
newOptions->enableMockingboard = yorn();
|
||||||
|
if (!newOptions->enableMockingboard)
|
||||||
|
return;
|
||||||
|
|
||||||
printString("\nMockingBoard has a speech chip? (Y/N) ");
|
// If the mockingboard does not have a speech chip, do not prompt whether to
|
||||||
showCursor();
|
// enable/disable it.
|
||||||
while (true) {
|
if (!mockingBoardHasSpeechChip())
|
||||||
ch = cgetc();
|
return;
|
||||||
if ((ch == 'N') ||
|
|
||||||
(ch == 'n')) {
|
|
||||||
newOptions->enableSpeechChip = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ((ch == 'Y') ||
|
|
||||||
(ch == 'y')) {
|
|
||||||
newOptions->enableSpeechChip = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
badThingHappened();
|
printString("\nEnable speech on the Mockingboard? (Y/N) ");
|
||||||
}
|
newOptions->enableMockingboardSpeech = yorn();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -314,29 +314,35 @@ static void selectOptions(void)
|
|||||||
" Options\n"
|
" Options\n"
|
||||||
"\n"
|
"\n"
|
||||||
" J - Joystick control - ");
|
" J - Joystick control - ");
|
||||||
printString(newOptions.enableJoystick ? "Enable\n" : "Disabled\n");
|
printString(newOptions.enableJoystick ? "Enabled\n" : "Disabled\n");
|
||||||
printString(
|
printString(
|
||||||
" M - Mouse control - ");
|
" M - Mouse control - ");
|
||||||
printString(newOptions.enableMouse ? "Enable\n" : "Disabled\n");
|
printString(newOptions.enableMouse ? "Enabled\n" : "Disabled\n");
|
||||||
printString(
|
printString(
|
||||||
" S - Sound - ");
|
" S - Sound - ");
|
||||||
printString(newOptions.enableSound ? "Enable\n" : "Disabled\n");
|
printString(newOptions.enableSound ? "Enabled\n" : "Disabled\n");
|
||||||
|
|
||||||
if (newOptions.enableSound) {
|
if (newOptions.enableSound) {
|
||||||
if (newOptions.mockingBoardSlot > 0) {
|
tSlot slot = mockingBoardSlot();
|
||||||
|
|
||||||
|
if (slot != 0) {
|
||||||
printString(
|
printString(
|
||||||
// 0000000001111111111222222222233333333334444444444555555555566666666667
|
// 0000000001111111111222222222233333333334444444444555555555566666666667
|
||||||
// 1234567890123456789012345678901234567890123456789012345678901234567890
|
// 1234567890123456789012345678901234567890123456789012345678901234567890
|
||||||
" MockingBoard - Slot ");
|
" MockingBoard - ");
|
||||||
printInteger(newOptions.mockingBoardSlot);
|
printString(newOptions.enableMockingboard ? "Enabled (Slot " : "Disabled (Slot ");
|
||||||
printString("\n"
|
printInteger(slot);
|
||||||
" Speech Chip - ");
|
printString(")\n");
|
||||||
printString(newOptions.enableSpeechChip ? "Enable\n" : "Disable\n");
|
|
||||||
} else {
|
if ((newOptions.enableMockingboard) &&
|
||||||
|
(mockingBoardHasSpeechChip()))
|
||||||
|
{
|
||||||
printString(
|
printString(
|
||||||
// 0000000001111111111222222222233333333334444444444555555555566666666667
|
// 0000000001111111111222222222233333333334444444444555555555566666666667
|
||||||
// 1234567890123456789012345678901234567890123456789012345678901234567890
|
// 1234567890123456789012345678901234567890123456789012345678901234567890
|
||||||
" MockingBoard - Disabled\n");
|
" Speech - ");
|
||||||
|
printString(newOptions.enableMockingboardSpeech ? "Enabled\n" : "Disabled\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printString(
|
printString(
|
||||||
@ -716,6 +722,8 @@ void initUI(void)
|
|||||||
|
|
||||||
optionsLoaded = loadOptions();
|
optionsLoaded = loadOptions();
|
||||||
|
|
||||||
|
soundInit(gGameOptions.enableSound, gGameOptions.enableMockingboard, gGameOptions.enableMockingboardSpeech);
|
||||||
|
|
||||||
initGameEngine(&gCallbacks);
|
initGameEngine(&gCallbacks);
|
||||||
mouseInitialized = initMouse(&gMouseCallbacks);
|
mouseInitialized = initMouse(&gMouseCallbacks);
|
||||||
|
|
||||||
@ -723,19 +731,12 @@ void initUI(void)
|
|||||||
if ((!mouseInitialized) &&
|
if ((!mouseInitialized) &&
|
||||||
(gGameOptions.enableMouse)) {
|
(gGameOptions.enableMouse)) {
|
||||||
gGameOptions.enableMouse = false;
|
gGameOptions.enableMouse = false;
|
||||||
gGameOptions.optionsSaved = false;
|
gGameOptions.optionsVersion = OPTIONS_VERSION_UNSAVED;
|
||||||
}
|
}
|
||||||
|
|
||||||
initJoystick(&gJoyCallbacks);
|
initJoystick(&gJoyCallbacks);
|
||||||
|
|
||||||
if (gGameOptions.enableSound) {
|
if (gGameOptions.optionsVersion == OPTIONS_VERSION_UNSAVED) {
|
||||||
if (!optionsLoaded) {
|
|
||||||
gGameOptions.mockingBoardSlot = getMockingBoardSlot();
|
|
||||||
}
|
|
||||||
soundInit(gGameOptions.mockingBoardSlot, gGameOptions.enableSpeechChip);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!gGameOptions.optionsSaved) {
|
|
||||||
saveOptions();
|
saveOptions();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -957,33 +958,14 @@ void playGame(void)
|
|||||||
printString("\n\nChecking for a saved game...");
|
printString("\n\nChecking for a saved game...");
|
||||||
|
|
||||||
if (loadGame()) {
|
if (loadGame()) {
|
||||||
bool gotAnswer = false;
|
bool loadSavedGame = false;
|
||||||
|
|
||||||
printString("\n\nYou have a saved game!\n Would you like to continue it (Y/N) ");
|
printString("\n\nYou have a saved game!\n Would you like to continue it (Y/N) ");
|
||||||
|
loadSavedGame = yorn();
|
||||||
showCursor();
|
if (loadSavedGame) {
|
||||||
while (!gotAnswer) {
|
|
||||||
ch = cgetc();
|
|
||||||
switch (ch) {
|
|
||||||
case 'y':
|
|
||||||
case 'Y':
|
|
||||||
replaceCursor(ch);
|
|
||||||
printString("\n\nLoading your saved puzzle");
|
printString("\n\nLoading your saved puzzle");
|
||||||
gotAnswer = true;
|
|
||||||
gShouldSave = true;
|
gShouldSave = true;
|
||||||
gameLoaded = true;
|
gameLoaded = true;
|
||||||
break;
|
|
||||||
|
|
||||||
case 'n':
|
|
||||||
case 'N':
|
|
||||||
replaceCursor(ch);
|
|
||||||
gotAnswer = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
badThingHappened();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user