From bce5abd33b7be8854f491a45b745059e1fe27369 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 11 Mar 2017 13:12:23 -0500 Subject: [PATCH 1/6] Made an attempt to spot Tigervision paging requests. --- StaticAnalyser/Atari/StaticAnalyser.cpp | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/StaticAnalyser/Atari/StaticAnalyser.cpp b/StaticAnalyser/Atari/StaticAnalyser.cpp index e48be34ed..ec477ec9e 100644 --- a/StaticAnalyser/Atari/StaticAnalyser.cpp +++ b/StaticAnalyser/Atari/StaticAnalyser.cpp @@ -93,11 +93,13 @@ static void DeterminePagingFor2kCartridge(StaticAnalyser::Target &target, const static void DeterminePagingFor8kCartridge(StaticAnalyser::Target &target, const Storage::Cartridge::Cartridge::Segment &segment, const std::vector &disassemblies) { std::set internal_accesses; + std::set external_stores; for(const StaticAnalyser::MOS6502::Disassembly &disassembly : disassemblies) { internal_accesses.insert(disassembly.internal_stores.begin(), disassembly.internal_stores.end()); internal_accesses.insert(disassembly.internal_modifies.begin(), disassembly.internal_modifies.end()); internal_accesses.insert(disassembly.internal_loads.begin(), disassembly.internal_loads.end()); + external_stores.insert(disassembly.external_stores.begin(), disassembly.external_stores.end()); } bool looks_like_atari = false; @@ -132,11 +134,13 @@ static void DeterminePagingForCartridge(StaticAnalyser::Target &target, const St std::vector disassemblies; std::set internal_stores; + std::set external_stores; for(std::vector::difference_type base = 0; base < segment.data.size(); base += 4096) { std::vector sub_data(segment.data.begin() + base, segment.data.begin() + base + 4096); disassemblies.push_back(StaticAnalyser::MOS6502::Disassemble(sub_data, address_mapper, {entry_address, break_address})); internal_stores.insert(disassemblies.back().internal_stores.begin(), disassemblies.back().internal_stores.end()); + external_stores.insert(disassemblies.back().external_stores.begin(), disassemblies.back().external_stores.end()); } if(segment.data.size() == 8192) @@ -159,18 +163,13 @@ static void DeterminePagingForCartridge(StaticAnalyser::Target &target, const St } target.atari.uses_superchip = has_superchip; if(is_ram_plus) target.atari.paging_model = StaticAnalyser::Atari2600PagingModel::CBSRamPlus; -// if(internal_stores.size() > 4) -// { -// bool writes_above_128 = false; -// for(uint16_t address : internal_stores) -// { -// writes_above_128 |= ((address & 0x1fff) > 0x10ff) && ((address & 0x1fff) < 0x1200); -// } -// if(writes_above_128) -// target.atari.paging_model = StaticAnalyser::Atari2600PagingModel::CBSRamPlus; -// else -// target.atari.uses_superchip = true; -// } + + // check for a Tigervision or Tigervision-esque scheme + if(target.atari.paging_model == StaticAnalyser::Atari2600PagingModel::None) + { + bool looks_like_tigervision = external_stores.find(0x3f) != external_stores.end(); + if(looks_like_tigervision) target.atari.paging_model = StaticAnalyser::Atari2600PagingModel::Tigervision; + } } void StaticAnalyser::Atari::AddTargets( From 38ce4dc56cdc2d37a56219a2c13c6ba58f9d871e Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 11 Mar 2017 17:44:02 -0500 Subject: [PATCH 2/6] Fixed potential deadlock, if a delegate decided to dealloc the queue as a result of its prompting. --- .../Mac/Clock Signal/Audio/CSAudioQueue.m | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/OSBindings/Mac/Clock Signal/Audio/CSAudioQueue.m b/OSBindings/Mac/Clock Signal/Audio/CSAudioQueue.m index 83280ad8b..495faf1e8 100644 --- a/OSBindings/Mac/Clock Signal/Audio/CSAudioQueue.m +++ b/OSBindings/Mac/Clock Signal/Audio/CSAudioQueue.m @@ -23,10 +23,11 @@ static NSLock *CSAudioQueueDeallocLock; #pragma mark - AudioQueue callbacks -- (void)audioQueue:(AudioQueueRef)theAudioQueue didCallbackWithBuffer:(AudioQueueBufferRef)buffer +/*! + @returns @c YES if the queue is running dry; @c NO otherwise. +*/ +- (BOOL)audioQueue:(AudioQueueRef)theAudioQueue didCallbackWithBuffer:(AudioQueueBufferRef)buffer { - [self.delegate audioQueueIsRunningDry:self]; - [_storedBuffersLock lock]; for(int c = 0; c < NumberOfStoredAudioQueueBuffer; c++) { @@ -35,11 +36,12 @@ static NSLock *CSAudioQueueDeallocLock; if(_storedBuffers[c]) AudioQueueFreeBuffer(_audioQueue, _storedBuffers[c]); _storedBuffers[c] = buffer; [_storedBuffersLock unlock]; - return; + return YES; } } [_storedBuffersLock unlock]; AudioQueueFreeBuffer(_audioQueue, buffer); + return YES; } static void audioOutputCallback( @@ -47,11 +49,16 @@ static void audioOutputCallback( AudioQueueRef inAQ, AudioQueueBufferRef inBuffer) { + // Pull the delegate call for audio queue running dry outside of the locked region, to allow non-deadlocking + // lifecycle -dealloc events to result from it. + CSAudioQueue *queue = (__bridge CSAudioQueue *)inUserData; + BOOL isRunningDry = NO; if([CSAudioQueueDeallocLock tryLock]) { - [(__bridge CSAudioQueue *)inUserData audioQueue:inAQ didCallbackWithBuffer:inBuffer]; + isRunningDry = [queue audioQueue:inAQ didCallbackWithBuffer:inBuffer]; [CSAudioQueueDeallocLock unlock]; } + if(isRunningDry) [queue.delegate audioQueueIsRunningDry:queue]; } #pragma mark - Standard object lifecycle From add14fb43a3167d7a610a3140a247d4533672fc7 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 11 Mar 2017 17:44:35 -0500 Subject: [PATCH 3/6] Made an attempt to implement Tigervision paging. --- Machines/Atari2600/Atari2600.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Machines/Atari2600/Atari2600.cpp b/Machines/Atari2600/Atari2600.cpp index 97a907762..eb314346c 100644 --- a/Machines/Atari2600/Atari2600.cpp +++ b/Machines/Atari2600/Atari2600.cpp @@ -211,6 +211,15 @@ unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uin case 0x18: update_audio(); speaker_->set_divider(decodedAddress - 0x17, *value); break; case 0x19: case 0x1a: update_audio(); speaker_->set_volume(decodedAddress - 0x19, *value); break; + + case 0x3f: + if(paging_model_ == StaticAnalyser::Atari2600PagingModel::Tigervision && (masked_address == 0x3f)) + { + int selected_page = (*value) % (rom_size_ / 2048); + rom_pages_[0] = &rom_[selected_page * 2048]; + rom_pages_[1] = rom_pages_[0] + 2048; + } + break; } } } From a72d70e70753f35fd015bb9973172a3723f37b3d Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 11 Mar 2017 17:44:56 -0500 Subject: [PATCH 4/6] Enabled code coverage calculation for unit tests. --- .../xcshareddata/xcschemes/Clock Signal.xcscheme | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal.xcscheme b/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal.xcscheme index 6cceb313b..fc79e9f59 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal.xcscheme +++ b/OSBindings/Mac/Clock Signal.xcodeproj/xcshareddata/xcschemes/Clock Signal.xcscheme @@ -26,7 +26,8 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" - shouldUseLaunchSchemeArgsEnv = "YES"> + shouldUseLaunchSchemeArgsEnv = "YES" + codeCoverageEnabled = "YES"> From f0d944847b6076b906318e55f96d21d2dc41a6d5 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 11 Mar 2017 18:16:29 -0500 Subject: [PATCH 5/6] Fixed setting of the second 1kb. --- Machines/Atari2600/Atari2600.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Machines/Atari2600/Atari2600.cpp b/Machines/Atari2600/Atari2600.cpp index eb314346c..bf189ee2b 100644 --- a/Machines/Atari2600/Atari2600.cpp +++ b/Machines/Atari2600/Atari2600.cpp @@ -217,7 +217,7 @@ unsigned int Machine::perform_bus_operation(CPU6502::BusOperation operation, uin { int selected_page = (*value) % (rom_size_ / 2048); rom_pages_[0] = &rom_[selected_page * 2048]; - rom_pages_[1] = rom_pages_[0] + 2048; + rom_pages_[1] = rom_pages_[0] + 1024; } break; } From b193248056e0a41e80c22e18d30f66956f61c6b5 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sat, 11 Mar 2017 18:17:09 -0500 Subject: [PATCH 6/6] Ensured that queue is not touched at all outside of the critical section. --- OSBindings/Mac/Clock Signal/Audio/CSAudioQueue.m | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/OSBindings/Mac/Clock Signal/Audio/CSAudioQueue.m b/OSBindings/Mac/Clock Signal/Audio/CSAudioQueue.m index 495faf1e8..4f740aaba 100644 --- a/OSBindings/Mac/Clock Signal/Audio/CSAudioQueue.m +++ b/OSBindings/Mac/Clock Signal/Audio/CSAudioQueue.m @@ -51,14 +51,15 @@ static void audioOutputCallback( { // Pull the delegate call for audio queue running dry outside of the locked region, to allow non-deadlocking // lifecycle -dealloc events to result from it. - CSAudioQueue *queue = (__bridge CSAudioQueue *)inUserData; - BOOL isRunningDry = NO; if([CSAudioQueueDeallocLock tryLock]) { + CSAudioQueue *queue = (__bridge CSAudioQueue *)inUserData; + BOOL isRunningDry = NO; isRunningDry = [queue audioQueue:inAQ didCallbackWithBuffer:inBuffer]; + id delegate = queue.delegate; [CSAudioQueueDeallocLock unlock]; + if(isRunningDry) [delegate audioQueueIsRunningDry:queue]; } - if(isRunningDry) [queue.delegate audioQueueIsRunningDry:queue]; } #pragma mark - Standard object lifecycle