Skip to content

Commit

Permalink
Carmen Sandiego IIgs write protection/disk bit cell timings fix + oth…
Browse files Browse the repository at this point in the history
…er debugger changes (#132)

* DOC debugger display adjusted for new view + flavor text for no memory view
* Support random bit reads on 3.5 apple drives for Rastan copy protection
* Adding IWM Debugger Window
* inlining some disk utility functions
* 3.5 disks use different methodology for bit cell timings (closer to 2us and fixes Carmen Sandiego copy protection) and it works so far...
* disable audio wraparound if the clemens audio buffer is not consumed in time - and up mockingboard event buffer
* Moved debug diagnostics view to CPU pane
* Keyboard focus on emulator startup
  • Loading branch information
samkusin authored Jul 21, 2023
1 parent a818f70 commit 6f0ebf5
Show file tree
Hide file tree
Showing 20 changed files with 852 additions and 321 deletions.
5 changes: 4 additions & 1 deletion clem_audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,9 @@ void clem_sound_glu_sync(struct ClemensDeviceAudio *glu, struct ClemensClock *cl
// TODO: stereo
unsigned ensoniq_voice_cnt = clem_ensoniq_voices(&glu->doc);
clem_ensoniq_mono(&glu->doc, ensoniq_voice_cnt, &doc_out[0], &doc_out[1]);
if (glu->mix_frame_index + delta_frames > glu->mix_buffer.frame_count) {
delta_frames = glu->mix_buffer.frame_count - glu->mix_frame_index;
}
for (unsigned i = 0; i < delta_frames; ++i) {
unsigned frame_index = (glu->mix_frame_index + i) % glu->mix_buffer.frame_count;
float *samples = (float *)(&mix_out[frame_index * glu->mix_buffer.stride]);
Expand Down Expand Up @@ -570,7 +573,7 @@ void clem_sound_glu_sync(struct ClemensDeviceAudio *glu, struct ClemensClock *cl
samples[1] = -1.0f;
}
glu->mix_frame_index =
(glu->mix_frame_index + delta_frames) % (glu->mix_buffer.frame_count);
(glu->mix_frame_index + delta_frames); // % (glu->mix_buffer.frame_count);
glu->dt_mix_frame = glu->dt_mix_frame % glu->dt_mix_sample;
#if CLEM_AUDIO_DIAGNOSTICS
glu->diag_delta_frames += delta_frames;
Expand Down
44 changes: 25 additions & 19 deletions clem_drive.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,16 +144,16 @@ static void _clem_disk_reset_drive(struct ClemensDrive *drive) {
"Half-step single-coil mode"
Mechanical Summary: 3.5"
*/
static unsigned _clem_disk_get_track_bit_length(struct ClemensDrive *drive, int qtr_track_index,
bool is_drive_525) {
static inline unsigned _clem_disk_get_track_bit_length(struct ClemensDrive *drive,
int qtr_track_index, bool is_drive_525) {
if (drive->disk.meta_track_map[qtr_track_index] != 0xff) {
return drive->disk.track_bits_count[(drive->disk.meta_track_map[qtr_track_index])];
}
/* empty track - use a 6400 byte, 51200 bit track size per WOZ2 spec */
return 51200;
}

static void _clem_disk_write_bit(struct ClemensDrive *drive, bool value) {
static inline void _clem_disk_write_bit(struct ClemensDrive *drive, bool value) {
uint8_t *data =
drive->disk.bits_data + (drive->disk.track_byte_offset[drive->real_track_index]);
if (value) {
Expand All @@ -180,7 +180,7 @@ static inline bool _clem_disk_read_fake_bit_525(struct ClemensDrive *drive) {
return random_bit;
}

unsigned _clem_disk_get_track_position(struct ClemensDrive *drive) {
static inline unsigned _clem_disk_get_track_position(struct ClemensDrive *drive) {
unsigned track_cur_pos = (drive->track_byte_index * 8) + (7 - drive->track_bit_shift);
return track_cur_pos;
}
Expand Down Expand Up @@ -294,7 +294,10 @@ void clem_disk_control(struct ClemensDrive *drive, unsigned *io_flags, unsigned
drive->track_bit_length = drive->disk.track_bits_count[0];
}
if (track_prev_len) {
track_cur_pos = track_cur_pos * drive->track_bit_length / track_prev_len;
// TODO: this should be 64-bit math or reexamined - using double here for
// expediency until Carmen Sandiego copy protection bug is fixed
track_cur_pos = (unsigned)(track_cur_pos *
((double)(drive->track_bit_length) / track_prev_len));
}
}
} else {
Expand Down Expand Up @@ -329,25 +332,28 @@ void clem_disk_step(struct ClemensDrive *drive, unsigned *io_flags) {
drive->read_buffer |= 0x1;
}
}
if (is_drive_525) {
/* 3.5" drives don't have the same hardware as the Disk II, so
I *think* fake bits don't apply
*/
if ((drive->read_buffer & 0xf) && valid_disk_data) {
if (drive->read_buffer & 0x2) {
*io_flags |= CLEM_IWM_FLAG_READ_DATA;
}
} else {
*io_flags |= CLEM_IWM_FLAG_READ_DATA_FAKE;
if (_clem_disk_read_fake_bit_525(drive)) {
*io_flags |= CLEM_IWM_FLAG_READ_DATA;
}
/* 3.5" drives don't have the same hardware as the Disk II, so
I *think* fake bits don't apply.
WRONG!! Though the hardware isn't the same, randomness can still
occur. No real documentation on how similiar this is to Disk II
random behavior.
*/
// if (is_drive_525) {
if ((drive->read_buffer & 0xf) && valid_disk_data) {
if (drive->read_buffer & 0x2) {
*io_flags |= CLEM_IWM_FLAG_READ_DATA;
}
} else {
if (drive->read_buffer & 0x1) {
*io_flags |= CLEM_IWM_FLAG_READ_DATA_FAKE;
if (_clem_disk_read_fake_bit_525(drive)) {
*io_flags |= CLEM_IWM_FLAG_READ_DATA;
}
}
//} else {
// if (drive->read_buffer & 0x1) {
// *io_flags |= CLEM_IWM_FLAG_READ_DATA;
// }
//}

drive->current_byte = (drive->current_byte & 0xfe) | (drive->read_buffer & 0x01);

Expand Down
34 changes: 25 additions & 9 deletions clem_mmio_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -403,9 +403,9 @@
* of IO registers. Our host should have the opportunity to send input to the
* emulator at a decent frequency (30-60hz) for us not to lose events
*/
#define CLEM_ADB_KEYB_BUFFER_LIMIT 8
#define CLEM_ADB_KEYB_BUFFER_LIMIT 8
#define CLEM_ADB_CLIPBOARD_BUFFER_LIMIT 8
#define CLEM_ADB_KEYB_TOGGLE_CAPS_LOCK 0x0000001
#define CLEM_ADB_KEYB_TOGGLE_CAPS_LOCK 0x0000001

/** Gameport support - note that paddle axis values range from 0 to 1023, and
* there's support for up to 8 buttons. Of course the Apple 2 only supports
Expand Down Expand Up @@ -605,13 +605,29 @@
#define CLEM_ADB_KEY_MOD_STATE_RESET CLEM_ADB_GLU_REG2_KEY_RESET
#define CLEM_ADB_KEY_MOD_STATE_ESCAPE 0x00010000

/** Emulated duration of every 'step' iwm_glu_sync runs. 1.023 / 2 ~ 0.511 */
#define CLEM_IWM_SYNC_CLOCKS_FAST (CLEM_CLOCKS_2MHZ_CYCLE * 4)
#define CLEM_IWM_SYNC_CLOCKS_NORMAL (CLEM_CLOCKS_2MHZ_CYCLE * 8)
#define CLEM_IWM_SYNC_DISK_FRAME_NS 500
#define CLEM_IWM_SYNC_DISK_FRAME_NS_FAST 250
#define CLEM_IWM_DRIVE_RANDOM_BYTES 16
#define CLEM_IWM_DEBUG_BUFFER_SIZE 256
/**
* Instead of using clock multiples for 3.5" drives, use values that get us closer
* to 2000ns bit cell times. Doing the same for 5.25" drives seems to result in
* write errors (the bane of our IWM implementation whenever we change timing
* values!) This approach seems highly suspect but it does pass some copy
* protection schemes for 3.5" titles that rely on precise timing between sectors
* on tracks (https://github.com/samkusin/clemens_iigs/issues/108) - see
* Where in the World is Carmen Sandiego
*
* Perhaps a longer term solution is to investigate how our IWM sync loop
* deals with IWM updates vs disk head updates - i.e. decouple them, which
* seems even more potentially buggy - as we used to do this but ran into
* other issues when fixing how PHI0 + stretch worked.
*
* When I have time to investigate that.........
*/
// #define CLEM_IWM_SYNC_CLOCKS_FAST (CLEM_CLOCKS_2MHZ_CYCLE * 4)
#define CLEM_IWM_SYNC_CLOCKS_FAST 5714 //(2000 * CLEM_CLOCKS_14MHZ_CYCLE / CLEM_14MHZ_CYCLE_NS)
#define CLEM_IWM_SYNC_CLOCKS_NORMAL (CLEM_CLOCKS_2MHZ_CYCLE * 8)
// #define CLEM_IWM_SYNC_CLOCKS_NORMAL 11461 //(4000 * CLEM_CLOCKS_14MHZ_CYCLE /
// CLEM_14MHZ_CYCLE_NS)
#define CLEM_IWM_DRIVE_RANDOM_BYTES 16
#define CLEM_IWM_DEBUG_BUFFER_SIZE 256

/* Enable 3.5 drive seris */
#define CLEM_IWM_FLAG_DRIVE_35 0x00000001
Expand Down
2 changes: 1 addition & 1 deletion clem_mmio_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ struct ClemensDrive {
unsigned track_byte_index; /**< byte index into track */
unsigned track_bit_shift; /**< bit offset into current byte */
unsigned track_bit_length; /**< current track bit length */
clem_clocks_duration_t pulse_clocks_dt; /**< clocks per drive tick */
clem_clocks_duration_t pulse_clocks_dt; /**< TODO: remove, NOT USED ANYMORE */
unsigned read_buffer; /**< Used for MC3470 emulation */

/**
Expand Down
2 changes: 1 addition & 1 deletion devices/mockingboard.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
#define CLEM_VIA_6522_IER_TIMER1 0x40
#define CLEM_VIA_6522_IER_TIMER2 0x20

#define CLEM_AY3_QUEUE_SIZE 32
#define CLEM_AY3_QUEUE_SIZE 64

#define CLEM_AY3_REG_A_TONE_PERIOD_FINE 0x00
#define CLEM_AY3_REG_A_TONE_PERIOD_COARSE 0x01
Expand Down
11 changes: 10 additions & 1 deletion host/clem_backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,16 @@ auto ClemensBackend::step(ClemensCommandQueue &commands) -> ClemensCommandQueue:
return result;
}

ClemensAudio ClemensBackend::renderAudioFrame() { return GS_->renderAudio(); }
ClemensAudio ClemensBackend::renderAudioFrame() {
ClemensAudio audio = GS_->renderAudio();
/*
if (runSampler_.fastModeEnabled) {
audio.frame_count = 0;
audio.frame_total = 0;
}
*/
return audio;
}

void ClemensBackend::post(ClemensBackendState &backendState) {
auto &machine = GS_->getMachine();
Expand Down
Loading

0 comments on commit 6f0ebf5

Please sign in to comment.