mirror of
https://github.com/TomHarte/CLK.git
synced 2024-08-16 00:29:01 +00:00
Merge pull request #106 from TomHarte/Tigervision
Adds detection and emulation of the Tigervision paging scheme
This commit is contained in:
commit
8c7f724ce4
@ -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 0x18: update_audio(); speaker_->set_divider(decodedAddress - 0x17, *value); break;
|
||||||
case 0x19:
|
case 0x19:
|
||||||
case 0x1a: update_audio(); speaker_->set_volume(decodedAddress - 0x19, *value); break;
|
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] + 1024;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,8 @@
|
|||||||
buildConfiguration = "Debug"
|
buildConfiguration = "Debug"
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
codeCoverageEnabled = "YES">
|
||||||
<Testables>
|
<Testables>
|
||||||
<TestableReference
|
<TestableReference
|
||||||
skipped = "NO">
|
skipped = "NO">
|
||||||
|
@ -23,10 +23,11 @@ static NSLock *CSAudioQueueDeallocLock;
|
|||||||
|
|
||||||
#pragma mark - AudioQueue callbacks
|
#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];
|
[_storedBuffersLock lock];
|
||||||
for(int c = 0; c < NumberOfStoredAudioQueueBuffer; c++)
|
for(int c = 0; c < NumberOfStoredAudioQueueBuffer; c++)
|
||||||
{
|
{
|
||||||
@ -35,11 +36,12 @@ static NSLock *CSAudioQueueDeallocLock;
|
|||||||
if(_storedBuffers[c]) AudioQueueFreeBuffer(_audioQueue, _storedBuffers[c]);
|
if(_storedBuffers[c]) AudioQueueFreeBuffer(_audioQueue, _storedBuffers[c]);
|
||||||
_storedBuffers[c] = buffer;
|
_storedBuffers[c] = buffer;
|
||||||
[_storedBuffersLock unlock];
|
[_storedBuffersLock unlock];
|
||||||
return;
|
return YES;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[_storedBuffersLock unlock];
|
[_storedBuffersLock unlock];
|
||||||
AudioQueueFreeBuffer(_audioQueue, buffer);
|
AudioQueueFreeBuffer(_audioQueue, buffer);
|
||||||
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void audioOutputCallback(
|
static void audioOutputCallback(
|
||||||
@ -47,10 +49,16 @@ static void audioOutputCallback(
|
|||||||
AudioQueueRef inAQ,
|
AudioQueueRef inAQ,
|
||||||
AudioQueueBufferRef inBuffer)
|
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.
|
||||||
if([CSAudioQueueDeallocLock tryLock])
|
if([CSAudioQueueDeallocLock tryLock])
|
||||||
{
|
{
|
||||||
[(__bridge CSAudioQueue *)inUserData audioQueue:inAQ didCallbackWithBuffer:inBuffer];
|
CSAudioQueue *queue = (__bridge CSAudioQueue *)inUserData;
|
||||||
|
BOOL isRunningDry = NO;
|
||||||
|
isRunningDry = [queue audioQueue:inAQ didCallbackWithBuffer:inBuffer];
|
||||||
|
id<CSAudioQueueDelegate> delegate = queue.delegate;
|
||||||
[CSAudioQueueDeallocLock unlock];
|
[CSAudioQueueDeallocLock unlock];
|
||||||
|
if(isRunningDry) [delegate audioQueueIsRunningDry:queue];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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<StaticAnalyser::MOS6502::Disassembly> &disassemblies)
|
static void DeterminePagingFor8kCartridge(StaticAnalyser::Target &target, const Storage::Cartridge::Cartridge::Segment &segment, const std::vector<StaticAnalyser::MOS6502::Disassembly> &disassemblies)
|
||||||
{
|
{
|
||||||
std::set<uint16_t> internal_accesses;
|
std::set<uint16_t> internal_accesses;
|
||||||
|
std::set<uint16_t> external_stores;
|
||||||
for(const StaticAnalyser::MOS6502::Disassembly &disassembly : disassemblies)
|
for(const StaticAnalyser::MOS6502::Disassembly &disassembly : disassemblies)
|
||||||
{
|
{
|
||||||
internal_accesses.insert(disassembly.internal_stores.begin(), disassembly.internal_stores.end());
|
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_modifies.begin(), disassembly.internal_modifies.end());
|
||||||
internal_accesses.insert(disassembly.internal_loads.begin(), disassembly.internal_loads.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;
|
bool looks_like_atari = false;
|
||||||
@ -132,11 +134,13 @@ static void DeterminePagingForCartridge(StaticAnalyser::Target &target, const St
|
|||||||
|
|
||||||
std::vector<StaticAnalyser::MOS6502::Disassembly> disassemblies;
|
std::vector<StaticAnalyser::MOS6502::Disassembly> disassemblies;
|
||||||
std::set<uint16_t> internal_stores;
|
std::set<uint16_t> internal_stores;
|
||||||
|
std::set<uint16_t> external_stores;
|
||||||
for(std::vector<uint8_t>::difference_type base = 0; base < segment.data.size(); base += 4096)
|
for(std::vector<uint8_t>::difference_type base = 0; base < segment.data.size(); base += 4096)
|
||||||
{
|
{
|
||||||
std::vector<uint8_t> sub_data(segment.data.begin() + base, segment.data.begin() + base + 4096);
|
std::vector<uint8_t> 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}));
|
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());
|
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)
|
if(segment.data.size() == 8192)
|
||||||
@ -159,18 +163,13 @@ static void DeterminePagingForCartridge(StaticAnalyser::Target &target, const St
|
|||||||
}
|
}
|
||||||
target.atari.uses_superchip = has_superchip;
|
target.atari.uses_superchip = has_superchip;
|
||||||
if(is_ram_plus) target.atari.paging_model = StaticAnalyser::Atari2600PagingModel::CBSRamPlus;
|
if(is_ram_plus) target.atari.paging_model = StaticAnalyser::Atari2600PagingModel::CBSRamPlus;
|
||||||
// if(internal_stores.size() > 4)
|
|
||||||
// {
|
// check for a Tigervision or Tigervision-esque scheme
|
||||||
// bool writes_above_128 = false;
|
if(target.atari.paging_model == StaticAnalyser::Atari2600PagingModel::None)
|
||||||
// for(uint16_t address : internal_stores)
|
{
|
||||||
// {
|
bool looks_like_tigervision = external_stores.find(0x3f) != external_stores.end();
|
||||||
// writes_above_128 |= ((address & 0x1fff) > 0x10ff) && ((address & 0x1fff) < 0x1200);
|
if(looks_like_tigervision) target.atari.paging_model = StaticAnalyser::Atari2600PagingModel::Tigervision;
|
||||||
// }
|
}
|
||||||
// if(writes_above_128)
|
|
||||||
// target.atari.paging_model = StaticAnalyser::Atari2600PagingModel::CBSRamPlus;
|
|
||||||
// else
|
|
||||||
// target.atari.uses_superchip = true;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void StaticAnalyser::Atari::AddTargets(
|
void StaticAnalyser::Atari::AddTargets(
|
||||||
|
Loading…
Reference in New Issue
Block a user