mirror of
https://github.com/trudnai/Steve2.git
synced 2024-12-20 23:29:19 +00:00
Fixed sound issues and resource leaks related to that
This commit is contained in:
parent
4751c59fad
commit
cb498c415c
@ -126,9 +126,6 @@
|
||||
32F8A8A724A3A98D00EE6735 /* XPS Diagnostic IIe.woz in Copy Disk Images */ = {isa = PBXBuildFile; fileRef = 32440B8B247F86D5000F9DA1 /* XPS Diagnostic IIe.woz */; };
|
||||
32F8A8A824A3A98D00EE6735 /* LOCKSMITH_V7_REV_B.woz in Copy Disk Images */ = {isa = PBXBuildFile; fileRef = 32440BA0247F9F99000F9DA1 /* LOCKSMITH_V7_REV_B.woz */; };
|
||||
32F8A8A924A3A98D00EE6735 /* locksmith_v6.0.woz in Copy Disk Images */ = {isa = PBXBuildFile; fileRef = 32F2C144249218A400FDC61B /* locksmith_v6.0.woz */; };
|
||||
32F8A8AB24A3AAD300EE6735 /* diskmotor.sfx in Copy SFX Files */ = {isa = PBXBuildFile; fileRef = 323D043D248F70930086A901 /* diskmotor.sfx */; };
|
||||
32F8A8AC24A3AAD300EE6735 /* diskarm.sfx in Copy SFX Files */ = {isa = PBXBuildFile; fileRef = 323D0441248F711F0086A901 /* diskarm.sfx */; };
|
||||
32F8A8AD24A3AAD300EE6735 /* diskioerr.sfx in Copy SFX Files */ = {isa = PBXBuildFile; fileRef = 323D043F248F70A10086A901 /* diskioerr.sfx */; };
|
||||
32F8A8AF24A3AB5900EE6735 /* apple-rainbow.png in Copy Image Files */ = {isa = PBXBuildFile; fileRef = 32E21BE62491BF8B006C0C72 /* apple-rainbow.png */; };
|
||||
32F8A8B024A3AB5D00EE6735 /* scanlines.png in Copy Image Files */ = {isa = PBXBuildFile; fileRef = 323D04452490BA1E0086A901 /* scanlines.png */; };
|
||||
/* End PBXBuildFile section */
|
||||
@ -247,9 +244,6 @@
|
||||
32E3126724A7194900E61891 /* disk_ii_arm.sfx in Copy SFX Files */,
|
||||
3296223A24A710E5002DEB78 /* disk_ii_io_error.sfx in Copy SFX Files */,
|
||||
3296223624A709EE002DEB78 /* disk_ii_motor_w_floppy.sfx in Copy SFX Files */,
|
||||
32F8A8AB24A3AAD300EE6735 /* diskmotor.sfx in Copy SFX Files */,
|
||||
32F8A8AC24A3AAD300EE6735 /* diskarm.sfx in Copy SFX Files */,
|
||||
32F8A8AD24A3AAD300EE6735 /* diskioerr.sfx in Copy SFX Files */,
|
||||
);
|
||||
name = "Copy SFX Files";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
@ -181,8 +181,8 @@ extern double mhz;
|
||||
#define DEF_VIDEO_DIV 1U
|
||||
#define DEF_SPKR_DIV 1U
|
||||
|
||||
#define GAME_FPS 300U
|
||||
#define GAME_VIDEO_DIV 5U // 300 / 5 = 60 FPS
|
||||
#define GAME_FPS 600U
|
||||
#define GAME_VIDEO_DIV 10U // 600 / 10 = 60 FPS
|
||||
|
||||
extern unsigned int video_fps_divider;
|
||||
extern unsigned int fps;
|
||||
|
@ -58,6 +58,7 @@ int spkr_level = SPKR_LEVEL_ZERO;
|
||||
|
||||
#define BUFFER_COUNT 256
|
||||
#define SOURCES_COUNT 4
|
||||
#define SPKR_CHANNELS 2
|
||||
|
||||
ALuint spkr_src [SOURCES_COUNT] = { 0, 0, 0, 0 };
|
||||
|
||||
@ -77,9 +78,9 @@ const unsigned spkr_sample_rate = 44100;
|
||||
const unsigned sfx_sample_rate = 22050; // original sample rate
|
||||
//const unsigned sfx_sample_rate = 26000; // bit higher pitch
|
||||
int spkr_extra_buf = 0; // 800 / spkr_fps;
|
||||
const unsigned spkr_buf_alloc_size = spkr_seconds * spkr_sample_rate * 2 / DEFAULT_FPS;
|
||||
const unsigned spkr_buf_alloc_size = spkr_seconds * spkr_sample_rate * SPKR_CHANNELS / DEFAULT_FPS;
|
||||
unsigned spkr_buf_size = spkr_buf_alloc_size;
|
||||
int16_t spkr_samples [ spkr_buf_alloc_size * DEFAULT_FPS * BUFFER_COUNT * 2]; // stereo
|
||||
int16_t spkr_samples [ spkr_buf_alloc_size * DEFAULT_FPS * BUFFER_COUNT * SPKR_CHANNELS]; // stereo
|
||||
unsigned spkr_sample_idx = 0;
|
||||
|
||||
unsigned spkr_play_timeout = 8; // increase to 32 for 240 fps, normally 8 for 30 fps
|
||||
@ -95,6 +96,8 @@ int diskarm_sfx_len = 0;
|
||||
uint8_t * diskioerr_sfx = NULL;
|
||||
int diskioerr_sfx_len = 0;
|
||||
|
||||
ALint freeBuffers = BUFFER_COUNT;
|
||||
|
||||
|
||||
static int load_sfx( const char * bundlePath, const char * filename, uint8_t ** buf ) {
|
||||
char fullPath[256];
|
||||
@ -237,11 +240,48 @@ void spkr_init() {
|
||||
freeBuffers = BUFFER_COUNT;
|
||||
}
|
||||
|
||||
|
||||
int spkr_unqueue( ALuint src ) {
|
||||
ALint processed = 0;
|
||||
|
||||
alGetSourcei ( src, AL_BUFFERS_PROCESSED, &processed );
|
||||
al_check_error();
|
||||
printf("%s alGetSourcei(%d)\n", __FUNCTION__, src);
|
||||
|
||||
if ( processed ) {
|
||||
alSourceUnqueueBuffers( src, processed, &spkr_buffers[freeBuffers]);
|
||||
al_check_error();
|
||||
}
|
||||
|
||||
return processed;
|
||||
}
|
||||
|
||||
void spkr_unqueueAll() {
|
||||
for ( int i = 0; i < SOURCES_COUNT; i++ ) {
|
||||
spkr_unqueue( spkr_src[i] );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Dealloc OpenAL
|
||||
void spkr_exit() {
|
||||
if ( spkr_src[SPKR_SRC_GAME_SFX] ) {
|
||||
alSourceStop( spkr_src[SPKR_SRC_GAME_SFX] );
|
||||
spkr_stopAll();
|
||||
spkr_unqueueAll();
|
||||
|
||||
// delete buffers
|
||||
alDeleteBuffers(BUFFER_COUNT, spkr_buffers);
|
||||
al_check_error();
|
||||
alDeleteBuffers(1, &spkr_disk_motor_buf);
|
||||
al_check_error();
|
||||
alDeleteBuffers(1, &spkr_disk_arm_buf);
|
||||
al_check_error();
|
||||
|
||||
// delete sound source and play buffer
|
||||
alDeleteSources(SOURCES_COUNT, spkr_src);
|
||||
al_check_error();
|
||||
|
||||
|
||||
ALCdevice *dev = NULL;
|
||||
ALCcontext *ctx = NULL;
|
||||
ctx = alcGetCurrentContext();
|
||||
@ -280,7 +320,7 @@ void spkr_toggle() {
|
||||
|
||||
// push a click into the speaker buffer
|
||||
// (we will play the entire buffer at the end of the frame)
|
||||
spkr_sample_idx = ( (spkr_clk + clkfrm) / ( MHZ(default_MHz_6502) / spkr_sample_rate)) * 2;
|
||||
spkr_sample_idx = ( (spkr_clk + clkfrm) / ( MHZ(default_MHz_6502) / spkr_sample_rate)) * SPKR_CHANNELS;
|
||||
|
||||
if ( spkr_state ) {
|
||||
// down edge
|
||||
@ -290,7 +330,7 @@ void spkr_toggle() {
|
||||
|
||||
while ( fadeLevel > +1 ) {
|
||||
spkr_samples[ spkr_sample_idx++ ] = SPKR_LEVEL_MIN + fadeLevel;
|
||||
spkr_samples[ spkr_sample_idx++ ] = SPKR_LEVEL_MIN + fadeLevel;
|
||||
spkr_samples[ spkr_sample_idx++ ] = SPKR_LEVEL_MIN + fadeLevel; // stereo
|
||||
|
||||
// how smooth we want the speeker to decay, so we will hear no pops and crackles
|
||||
// 0.9 gives you a kind of saw wave at 1KHz (beep)
|
||||
@ -307,7 +347,7 @@ void spkr_toggle() {
|
||||
|
||||
while ( fadeLevel < -1 ) {
|
||||
spkr_samples[ spkr_sample_idx++ ] = SPKR_LEVEL_MAX + fadeLevel;
|
||||
spkr_samples[ spkr_sample_idx++ ] = SPKR_LEVEL_MAX + fadeLevel;
|
||||
spkr_samples[ spkr_sample_idx++ ] = SPKR_LEVEL_MAX + fadeLevel; // stereo
|
||||
|
||||
// how smooth we want the speeker to decay, so we will hear no pops and crackles
|
||||
// 0.9 gives you a kind of saw wave at 1KHz (beep)
|
||||
@ -328,25 +368,8 @@ void spkr_toggle() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
ALint freeBuffers = BUFFER_COUNT;
|
||||
//ALuint alBuffers[BUFFER_COUNT];
|
||||
|
||||
int spkr_unqueue( ALuint src ) {
|
||||
ALint processed = 0;
|
||||
|
||||
alGetSourcei ( src, AL_BUFFERS_PROCESSED, &processed );
|
||||
al_check_error();
|
||||
|
||||
if ( processed ) {
|
||||
alSourceUnqueueBuffers( src, processed, &spkr_buffers[freeBuffers]);
|
||||
al_check_error();
|
||||
}
|
||||
|
||||
return processed;
|
||||
}
|
||||
|
||||
int playDelay = 4;
|
||||
#define SPKR_PLAY_DELAY 2
|
||||
int playDelay = SPKR_PLAY_DELAY;
|
||||
|
||||
|
||||
void spkr_update() {
|
||||
@ -354,12 +377,7 @@ void spkr_update() {
|
||||
spkr_frame_cntr = 0;
|
||||
|
||||
if ( spkr_play_time ) {
|
||||
// free up unused buffers
|
||||
freeBuffers += spkr_unqueue( spkr_src[SPKR_SRC_GAME_SFX] );
|
||||
freeBuffers = clamp( 1, freeBuffers, BUFFER_COUNT );
|
||||
|
||||
if ( freeBuffers ) {
|
||||
|
||||
// in Game Mode do not fade out and stop playing
|
||||
if ( ( cpuMode_game != cpuMode ) && ( --spkr_play_time == 0 ) ) {
|
||||
float fadeLevel = spkr_level - SPKR_LEVEL_ZERO;
|
||||
@ -369,7 +387,7 @@ void spkr_update() {
|
||||
|
||||
while ( ( fadeLevel < -1 ) || ( fadeLevel > 1 ) ) {
|
||||
spkr_samples[ spkr_sample_idx++ ] = SPKR_LEVEL_ZERO + fadeLevel;
|
||||
spkr_samples[ spkr_sample_idx++ ] = SPKR_LEVEL_ZERO + fadeLevel;
|
||||
spkr_samples[ spkr_sample_idx++ ] = SPKR_LEVEL_ZERO + fadeLevel; // stereo
|
||||
|
||||
// how smooth we want the speeker to decay, so we will hear no pops and crackles
|
||||
fadeLevel *= 0.999;
|
||||
@ -402,7 +420,7 @@ void spkr_update() {
|
||||
case AL_PAUSED:
|
||||
if ( --playDelay <= 0 ) {
|
||||
alSourcePlay(spkr_src[SPKR_SRC_GAME_SFX]);
|
||||
playDelay = 4;
|
||||
playDelay = SPKR_PLAY_DELAY;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -429,6 +447,10 @@ void spkr_update() {
|
||||
}
|
||||
|
||||
spkr_clk = 0;
|
||||
|
||||
// free up unused buffers
|
||||
freeBuffers += spkr_unqueue( spkr_src[SPKR_SRC_GAME_SFX] );
|
||||
freeBuffers = clamp( 1, freeBuffers, BUFFER_COUNT );
|
||||
}
|
||||
else {
|
||||
spkr_clk += clkfrm;
|
||||
@ -438,15 +460,16 @@ void spkr_update() {
|
||||
|
||||
void spkr_playqueue_sfx( ALuint src, uint8_t * sfx, int len ) {
|
||||
|
||||
// freeBuffers += spkr_unqueue( src );
|
||||
// freeBuffers = clamp( 1, freeBuffers, BUFFER_COUNT );
|
||||
|
||||
// printf("%s freeBuffers:%d\n", __FUNCTION__, freeBuffers);
|
||||
|
||||
if ( freeBuffers ) {
|
||||
ALenum queued;
|
||||
alGetSourcei( src, AL_BUFFERS_QUEUED, &queued );
|
||||
// printf("Q:%u\n", queued);
|
||||
|
||||
if ( queued < 32 ) {
|
||||
// printf("%s queued:%d\n", __FUNCTION__, queued);
|
||||
|
||||
if ( queued < 16 ) {
|
||||
freeBuffers--;
|
||||
alBufferData( spkr_buffers[freeBuffers], AL_FORMAT_STEREO16, sfx, len, sfx_sample_rate );
|
||||
al_check_error();
|
||||
@ -472,6 +495,9 @@ void spkr_playqueue_sfx( ALuint src, uint8_t * sfx, int len ) {
|
||||
|
||||
|
||||
void spkr_play_sfx( ALuint src, uint8_t * sfx, int len ) {
|
||||
|
||||
// printf("%s freeBuffers:%d\n", __FUNCTION__, freeBuffers);
|
||||
|
||||
if ( freeBuffers ) {
|
||||
ALenum state;
|
||||
alGetSourcei( src, AL_SOURCE_STATE, &state );
|
||||
@ -509,13 +535,16 @@ void spkr_stop_sfx( ALuint src ) {
|
||||
case AL_PAUSED:
|
||||
case AL_PLAYING:
|
||||
alSourceStop( src );
|
||||
freeBuffers += spkr_unqueue( src );
|
||||
freeBuffers = clamp( 1, freeBuffers, BUFFER_COUNT );
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// free up unused buffers
|
||||
freeBuffers += spkr_unqueue( src );
|
||||
freeBuffers = clamp( 1, freeBuffers, BUFFER_COUNT );
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -577,12 +606,7 @@ void spkr_update_disk_sfx() {
|
||||
|
||||
update_disk_sfx( &spkr_play_disk_motor_time, spkr_src[SPKR_SRC_DISK_MOTOR_SFX] );
|
||||
update_disk_sfx( &spkr_play_disk_arm_time, spkr_src[SPKR_SRC_DISK_ARM_SFX] );
|
||||
update_disk_sfx( &spkr_play_disk_ioerr_time, spkr_src[SPKR_SRC_DISK_IOERR_SFX] );
|
||||
|
||||
// we do not need to stop playing,
|
||||
// however, counter needed to eliminate arm movement noise while in io error
|
||||
if ( spkr_play_disk_ioerr_time ) {
|
||||
spkr_play_disk_ioerr_time--;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -517,7 +517,22 @@ int woz_loadFile( const char * filename ) {
|
||||
|
||||
fread( woz_file_buffer, woz_file_size, 1, f);
|
||||
fclose(f);
|
||||
if ( woz_header->magic != WOZ1_MAGIC ) {
|
||||
|
||||
// if this really a WOZ file?
|
||||
switch ( woz_header->magic ) {
|
||||
case WOZ1_MAGIC:
|
||||
break;
|
||||
|
||||
case WOZ2_MAGIC:
|
||||
break;
|
||||
|
||||
default:
|
||||
woz_free_buffer();
|
||||
return WOZ_ERR_NOT_WOZ_FILE;
|
||||
}
|
||||
|
||||
// check if bits and line ends not been altered by data transmission protocols
|
||||
if ( woz_header->bit_correctness != 0x0A0D0AFF ) {
|
||||
woz_free_buffer();
|
||||
return WOZ_ERR_NOT_WOZ_FILE;
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
#define WOZ_TMAP_CHUNK_ID 0x50414D54
|
||||
#define WOZ_TRKS_CHUNK_ID 0x534B5254
|
||||
#define WOZ_META_CHUNK_ID 0x4154454D
|
||||
#define WOZ_WRIT_CHUNK_ID 0x54495257
|
||||
|
||||
#define WOZ_ERR_OK 0
|
||||
#define WOZ_ERR_FILE_NOT_FOUND -1
|
||||
@ -37,8 +38,13 @@
|
||||
|
||||
typedef struct woz_header_s {
|
||||
uint32_t magic;
|
||||
uint8_t no7;
|
||||
char lineend [3];
|
||||
union {
|
||||
struct {
|
||||
uint8_t no7;
|
||||
char lineend [3];
|
||||
};
|
||||
uint32_t bit_correctness;
|
||||
};
|
||||
uint32_t crc;
|
||||
} woz_header_t;
|
||||
|
||||
@ -49,12 +55,39 @@ typedef struct woz_chunk_header_s {
|
||||
|
||||
// chunk data only
|
||||
typedef struct woz_info_s {
|
||||
uint8_t version;
|
||||
uint8_t version; // Version number of the INFO chunk.
|
||||
// WOZ1 version is 1
|
||||
// WOZ2 version is 2
|
||||
uint8_t disk_type; // 1 = 5.25, 2 = 3.5
|
||||
uint8_t is_write_protected;
|
||||
uint8_t is_write_protected; // 1 = Floppy is write protected
|
||||
uint8_t sync; // 1 = Cross track sync
|
||||
uint8_t cleaned; // 1 = MC3470 fake bits removed
|
||||
char creator [32]; // Name of software created this file (UTF-8, 0x20 padded, NOT zero terminated)
|
||||
uint8_t disk_sides; // The number of disk sides contained within this image. A 5.25 disk will always be 1. A 3.5 disk can be 1 or 2.
|
||||
uint8_t boot_sec_format; // The type of boot sector found on this disk. This is only for 5.25 disks. 3.5 disks should just set this to 0.
|
||||
// 0 = Unknown
|
||||
// 1 = Contains boot sector for 16-sector
|
||||
// 2 = Contains boot sector for 13-sector
|
||||
// 3 = Contains boot sectors for both
|
||||
uint8_t opt_bit_timing; // The ideal rate that bits should be delivered to the disk controller card.
|
||||
// This value is in 125 nanosecond increments, so 8 is equal to 1 microsecond.
|
||||
// And a standard bit rate for a 5.25 disk would be 32 (4µs).
|
||||
uint16_t compatible_hw; // Bit field with a 1 indicating known compatibility. Multiple compatibility flags are possible.
|
||||
// A 0 value represents that the compatible hardware list is unknown.
|
||||
// 0x0001 = Apple ][
|
||||
// 0x0002 = Apple ][ Plus
|
||||
// 0x0004 = Apple //e (unenhanced)
|
||||
// 0x0008 = Apple //c
|
||||
// 0x0010 = Apple //e Enhanced
|
||||
// 0x0020 = Apple IIgs
|
||||
// 0x0040 = Apple //c Plus
|
||||
// 0x0080 = Apple ///
|
||||
// 0x0100 = Apple /// Plus
|
||||
uint16_t required_ram; // Minimum RAM size needed for this software. This value is in K (1024 bytes).
|
||||
// If the minimum size is unknown, this value should be set to 0. So, a requirement
|
||||
// of 64K would be indicated by the value 64 here.
|
||||
uint16_t largest_track; // The number of blocks (512 bytes) used by the largest track.
|
||||
// Can be used to allocate a buffer with a size safe for all tracks.
|
||||
} woz_info_t;
|
||||
|
||||
// chunk data only
|
||||
@ -108,6 +141,7 @@ typedef struct woz_flags_s {
|
||||
|
||||
|
||||
extern WOZread_t WOZread;
|
||||
extern WOZread_t WOZwrite;
|
||||
extern uint8_t WOZlatch;
|
||||
extern char woz_filename[MAXFILENAME];
|
||||
extern woz_flags_t woz_flags;
|
||||
|
@ -741,34 +741,34 @@ INLINE uint8_t ioRead( uint16_t addr ) {
|
||||
case (uint8_t)io_DISK_PHASE2_OFF + SLOT6:
|
||||
case (uint8_t)io_DISK_PHASE3_OFF + SLOT6:
|
||||
disk_phase_off( (addr - io_DISK_PHASE0_OFF - SLOT6) / 2 );
|
||||
return 0;
|
||||
return disk_read();
|
||||
|
||||
case (uint8_t)io_DISK_PHASE0_ON + SLOT6:
|
||||
case (uint8_t)io_DISK_PHASE1_ON + SLOT6:
|
||||
case (uint8_t)io_DISK_PHASE2_ON + SLOT6:
|
||||
case (uint8_t)io_DISK_PHASE3_ON + SLOT6:
|
||||
disk_phase_on( (addr - io_DISK_PHASE0_ON - SLOT6) / 2 );
|
||||
return 0;
|
||||
return disk_read();
|
||||
|
||||
case (uint8_t)io_DISK_POWER_OFF + SLOT6:
|
||||
dbgPrintf2("io_DISK_POWER_OFF (S%u)\n", 6);
|
||||
disk_motor_off();
|
||||
return 0;
|
||||
return disk_read();
|
||||
|
||||
case (uint8_t)io_DISK_POWER_ON + SLOT6:
|
||||
dbgPrintf2("io_DISK_POWER_ON (S%u)\n", 6);
|
||||
disk_motor_on();
|
||||
return 0;
|
||||
return disk_read();
|
||||
|
||||
case (uint8_t)io_DISK_SELECT_1 + SLOT6:
|
||||
dbgPrintf2("io_DISK_SELECT_1 (S%u)\n", 6);
|
||||
disk.drive = 0;
|
||||
return 0;
|
||||
return disk_read();
|
||||
|
||||
case (uint8_t)io_DISK_SELECT_2 + SLOT6:
|
||||
dbgPrintf2("io_DISK_SELECT_2 (S%u)\n", 6);
|
||||
disk.drive = 1;
|
||||
return 0;
|
||||
return disk_read();
|
||||
|
||||
case (uint8_t)io_DISK_READ + SLOT6:
|
||||
if ( writeState ) {
|
||||
@ -784,6 +784,7 @@ INLINE uint8_t ioRead( uint16_t addr ) {
|
||||
case (uint8_t)io_DISK_WRITE + SLOT6:
|
||||
dbgPrintf2("io_DISK_WRITE (S%u)\n", 6);
|
||||
// Apple2_64K_RAM[io_DISK_CLEAR + SLOT6] |= 1 << 7; // mark disk as write protected
|
||||
WOZwrite.latch = WOZread.latch = 0;
|
||||
Apple2_64K_RAM[io_DISK_CLEAR + SLOT6] &= ~(1 << 7); // mark disk as write enabled
|
||||
return Apple2_64K_RAM[io_DISK_WRITE + SLOT6];
|
||||
|
||||
@ -793,7 +794,7 @@ INLINE uint8_t ioRead( uint16_t addr ) {
|
||||
|
||||
case (uint8_t)io_DISK_SHIFT + SLOT6:
|
||||
dbgPrintf2("io_DISK_SHIFT (S%u)\n", 6);
|
||||
return 0;
|
||||
return disk_read();
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user