From aca7842ca488b6cc15f10c82b53760f3d292b351 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Thu, 14 Dec 2017 20:27:26 -0500 Subject: [PATCH 1/4] Better documents and tidies the TMS9918. --- Components/9918/9918.cpp | 44 ++++--- Components/9918/9918.hpp | 110 +++++------------- Components/9918/Implementation/9918Base.cpp | 11 ++ Components/9918/Implementation/9918Base.hpp | 101 ++++++++++++++++ .../Clock Signal.xcodeproj/project.pbxproj | 14 +++ OSBindings/SDL/SConstruct | 1 + 6 files changed, 175 insertions(+), 106 deletions(-) create mode 100644 Components/9918/Implementation/9918Base.cpp create mode 100644 Components/9918/Implementation/9918Base.hpp diff --git a/Components/9918/9918.cpp b/Components/9918/9918.cpp index faf4aea1d..6cf2ece05 100644 --- a/Components/9918/9918.cpp +++ b/Components/9918/9918.cpp @@ -55,10 +55,14 @@ const uint8_t StatusSpriteCollision = 0x20; } -TMS9918::TMS9918(Personality p) : +TMS9918Base::TMS9918Base() : // 342 internal cycles are 228/227.5ths of a line, so 341.25 cycles should be a whole // line. Therefore multiply everything by four, but set line length to 1365 rather than 342*4 = 1368. - crt_(new Outputs::CRT::CRT(1365, 4, Outputs::CRT::DisplayType::NTSC60, 4)) { + crt_(new Outputs::CRT::CRT(1365, 4, Outputs::CRT::DisplayType::NTSC60, 4)) {} + +TMS9918::TMS9918(Personality p) { + // Unimaginatively, this class just passes RGB through to the shader. Investigation is needed + // into whether there's a more natural form. crt_->set_rgb_sampling_function( "vec3 rgb_sample(usampler2D sampler, vec2 coordinate, vec2 icoordinate)" "{" @@ -72,7 +76,7 @@ std::shared_ptr TMS9918::get_crt() { return crt_; } -void TMS9918::test_sprite(int sprite_number) { +void TMS9918Base::test_sprite(int sprite_number) { if(!(status_ & StatusFifthSprite)) { status_ = static_cast((status_ & ~31) | sprite_number); } @@ -101,7 +105,7 @@ void TMS9918::test_sprite(int sprite_number) { sprite_sets_[active_sprite_set_].active_sprite_slot++; } -void TMS9918::get_sprite_contents(int field, int cycles_left, int screen_row) { +void TMS9918Base::get_sprite_contents(int field, int cycles_left, int screen_row) { int sprite_id = field / 6; field %= 6; @@ -187,10 +191,11 @@ void TMS9918::run_for(const HalfCycles cycles) { if(cycles_left >= time_until_access_slot) { if(queued_access_ == MemoryAccess::Write) { - ram_[queued_address_] = read_ahead_buffer_; + ram_[ram_pointer_ & 16383] = read_ahead_buffer_; } else { - read_ahead_buffer_ = ram_[queued_address_]; + read_ahead_buffer_ = ram_[ram_pointer_ & 16383]; } + ram_pointer_++; queued_access_ = MemoryAccess::None; } } @@ -445,7 +450,10 @@ void TMS9918::run_for(const HalfCycles cycles) { if(sprite_set.active_sprite_slot) { int sprite_pixels_left = pixels_left; const int shift_advance = sprites_magnified_ ? 1 : 2; -// const uint32_t sprite_colour_selection_masks[2] = {0x00000000, 0xffffffff}; + + const uint32_t sprite_colour_selection_masks[2] = {0x00000000, 0xffffffff}; + const int colour_masks[16] = {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + while(sprite_pixels_left--) { uint32_t sprite_colour = pixel_base_[output_column_ - first_pixel_column_]; int sprite_mask = 0; @@ -463,12 +471,8 @@ void TMS9918::run_for(const HalfCycles cycles) { sprite_mask |= mask; sprite.shift_position += shift_advance; - // TODO: can a non-conditional version be found like that commented out below, but - // which accounts for colour 0 being invisible? -// sprite_colour = (sprite_colour & sprite_colour_selection_masks[mask^1]) | (palette[sprite.info[3]&15] & sprite_colour_selection_masks[mask]); - if((sprite.info[3]&15) && mask) { - sprite_colour = palette[sprite.info[3]&15]; - } + mask &= colour_masks[sprite.info[3]&15]; + sprite_colour = (sprite_colour & sprite_colour_selection_masks[mask^1]) | (palette[sprite.info[3]&15] & sprite_colour_selection_masks[mask]); } } @@ -545,7 +549,7 @@ void TMS9918::run_for(const HalfCycles cycles) { } } -void TMS9918::output_border(int cycles) { +void TMS9918Base::output_border(int cycles) { pixel_target_ = reinterpret_cast(crt_->allocate_write_area(1)); if(pixel_target_) *pixel_target_ = palette[background_colour_]; crt_->output_level(static_cast(cycles) * 4); @@ -556,13 +560,11 @@ void TMS9918::set_register(int address, uint8_t value) { // the value and return. if(!(address & 1)) { write_phase_ = false; - read_ahead_buffer_ = value; // Enqueue the write to occur at the next available slot. + read_ahead_buffer_ = value; queued_access_ = MemoryAccess::Write; - queued_address_ = ram_pointer_ & 16383; - ram_pointer_++; return; } @@ -580,7 +582,6 @@ void TMS9918::set_register(int address, uint8_t value) { switch(value & 7) { case 0: next_screen_mode_ = (next_screen_mode_ & 6) | ((low_write_ & 2) >> 1); -// printf("NSM: %02x\n", next_screen_mode_); break; case 1: @@ -593,7 +594,6 @@ void TMS9918::set_register(int address, uint8_t value) { sprite_height_ = 8; if(sprites_16x16_) sprite_height_ <<= 1; if(sprites_magnified_) sprite_height_ <<= 1; -// printf("NSM: %02x\n", next_screen_mode_); break; case 2: @@ -637,13 +637,9 @@ uint8_t TMS9918::get_register(int address) { // Reads from address 0 read video RAM, via the read-ahead buffer. if(!(address & 1)) { - uint8_t result = read_ahead_buffer_; - // Enqueue the write to occur at the next available slot. + uint8_t result = read_ahead_buffer_; queued_access_ = MemoryAccess::Read; - queued_address_ = ram_pointer_ & 16383; - - ram_pointer_++; return result; } diff --git a/Components/9918/9918.hpp b/Components/9918/9918.hpp index 67f0275f1..7613987ab 100644 --- a/Components/9918/9918.hpp +++ b/Components/9918/9918.hpp @@ -6,20 +6,33 @@ // Copyright © 2017 Thomas Harte. All rights reserved. // -#ifndef _918_hpp -#define _918_hpp +#ifndef TMS9918_hpp +#define TMS9918_hpp #include "../../Outputs/CRT/CRT.hpp" #include "../../ClockReceiver/ClockReceiver.hpp" +#include "Implementation/9918Base.hpp" + #include namespace TI { -class TMS9918 { +/*! + Provides emulation of the TMS9918a, TMS9928 and TMS9929. Likely in the future to be the + vessel for emulation of sufficiently close derivatives, such as the Master System VDP. + + The TMS9918 and descendants are video display generators that own their own RAM, making it + accessible through an implicitly-timed register interface, and (depending on model) can generate + PAL and NTSC component and composite video. + + These chips have only one non-on-demand interaction with the outside world: an interrupt line. + See get_time_until_interrupt and get_interrupt_line for asynchronous operation options. +*/ +class TMS9918: public TMS9918Base { public: enum Personality { - TMS9918A, // includes the 9928A; set TV standard as desired. + TMS9918A, // includes the 9928 and 9929; set TV standard and output device as desired. }; /*! @@ -29,10 +42,16 @@ class TMS9918 { TMS9918(Personality p); enum TVStandard { - PAL, NTSC + /*! i.e. 50Hz output at around 312.5 lines/field */ + PAL, + /*! i.e. 60Hz output at around 262.5 lines/field */ + NTSC }; + + /*! Sets the TV standard for this TMS, if that is hard-coded in hardware. */ void set_tv_standard(TVStandard standard); + /*! Provides the CRT this TMS is connected to. */ std::shared_ptr get_crt(); /*! @@ -41,7 +60,10 @@ class TMS9918 { */ void run_for(const HalfCycles cycles); + /*! Sets a register value. */ void set_register(int address, uint8_t value); + + /*! Gets a register value. */ uint8_t get_register(int address); /*! @@ -57,84 +79,8 @@ class TMS9918 { @returns @c true if the interrupt line is currently active; @c false otherwise. */ bool get_interrupt_line(); - - private: - std::shared_ptr crt_; - - uint8_t ram_[16384]; - - uint16_t ram_pointer_ = 0; - uint8_t read_ahead_buffer_ = 0; - enum class MemoryAccess { - Read, Write, None - } queued_access_ = MemoryAccess::None; - uint16_t queued_address_; - - uint8_t status_ = 0; - - bool write_phase_ = false; - uint8_t low_write_ = 0; - - // The various register flags. - int next_screen_mode_ = 0, screen_mode_ = 0; - bool next_blank_screen_ = true, blank_screen_ = true; - bool sprites_16x16_ = false; - bool sprites_magnified_ = false; - bool generate_interrupts_ = false; - int sprite_height_ = 8; - uint16_t pattern_name_address_ = 0; - uint16_t colour_table_address_ = 0; - uint16_t pattern_generator_table_address_ = 0; - uint16_t sprite_attribute_table_address_ = 0; - uint16_t sprite_generator_table_address_ = 0; - - uint8_t text_colour_ = 0; - uint8_t background_colour_ = 0; - - HalfCycles half_cycles_into_frame_; - int column_ = 0, row_ = 0, output_column_ = 0; - int cycles_error_ = 0; - uint32_t *pixel_target_ = nullptr, *pixel_base_ = nullptr; - - void output_border(int cycles); - - // Vertical timing details. - int frame_lines_ = 262; - int first_vsync_line_ = 227; - - // Horizontal selections. - enum class LineMode { - Text = 0, - Character = 1, - Refresh = 2 - } line_mode_ = LineMode::Text; - int first_pixel_column_, first_right_border_column_; - - uint8_t pattern_names_[40]; - uint8_t pattern_buffer_[40]; - uint8_t colour_buffer_[40]; - - struct SpriteSet { - struct ActiveSprite { - int index = 0; - int row = 0; - - uint8_t info[4]; - uint8_t image[2]; - - int shift_position = 0; - } active_sprites[4]; - int active_sprite_slot = 0; - } sprite_sets_[2]; - int active_sprite_set_ = 0; - bool sprites_stopped_ = false; - - int access_pointer_ = 0; - - inline void test_sprite(int sprite_number); - inline void get_sprite_contents(int start, int cycles, int screen_row); }; }; -#endif /* _918_hpp */ +#endif /* TMS9918_hpp */ diff --git a/Components/9918/Implementation/9918Base.cpp b/Components/9918/Implementation/9918Base.cpp new file mode 100644 index 000000000..4e19b3866 --- /dev/null +++ b/Components/9918/Implementation/9918Base.cpp @@ -0,0 +1,11 @@ +// +// 9918Base.cpp +// Clock Signal +// +// Created by Thomas Harte on 14/12/2017. +// Copyright © 2017 Thomas Harte. All rights reserved. +// + +#include "9918Base.hpp" + + diff --git a/Components/9918/Implementation/9918Base.hpp b/Components/9918/Implementation/9918Base.hpp new file mode 100644 index 000000000..8ca8dc834 --- /dev/null +++ b/Components/9918/Implementation/9918Base.hpp @@ -0,0 +1,101 @@ +// +// 9918Base.hpp +// Clock Signal +// +// Created by Thomas Harte on 14/12/2017. +// Copyright © 2017 Thomas Harte. All rights reserved. +// + +#ifndef TMS9918Base_hpp +#define TMS9918Base_hpp + +#include "../../../Outputs/CRT/CRT.hpp" +#include "../../../ClockReceiver/ClockReceiver.hpp" + +#include +#include + +namespace TI { + +class TMS9918Base { + protected: + TMS9918Base(); + + std::shared_ptr crt_; + + uint8_t ram_[16384]; + + uint16_t ram_pointer_ = 0; + uint8_t read_ahead_buffer_ = 0; + enum class MemoryAccess { + Read, Write, None + } queued_access_ = MemoryAccess::None; + + uint8_t status_ = 0; + + bool write_phase_ = false; + uint8_t low_write_ = 0; + + // The various register flags. + int next_screen_mode_ = 0, screen_mode_ = 0; + bool next_blank_screen_ = true, blank_screen_ = true; + bool sprites_16x16_ = false; + bool sprites_magnified_ = false; + bool generate_interrupts_ = false; + int sprite_height_ = 8; + uint16_t pattern_name_address_ = 0; + uint16_t colour_table_address_ = 0; + uint16_t pattern_generator_table_address_ = 0; + uint16_t sprite_attribute_table_address_ = 0; + uint16_t sprite_generator_table_address_ = 0; + + uint8_t text_colour_ = 0; + uint8_t background_colour_ = 0; + + HalfCycles half_cycles_into_frame_; + int column_ = 0, row_ = 0, output_column_ = 0; + int cycles_error_ = 0; + uint32_t *pixel_target_ = nullptr, *pixel_base_ = nullptr; + + void output_border(int cycles); + + // Vertical timing details. + int frame_lines_ = 262; + int first_vsync_line_ = 227; + + // Horizontal selections. + enum class LineMode { + Text = 0, + Character = 1, + Refresh = 2 + } line_mode_ = LineMode::Text; + int first_pixel_column_, first_right_border_column_; + + uint8_t pattern_names_[40]; + uint8_t pattern_buffer_[40]; + uint8_t colour_buffer_[40]; + + struct SpriteSet { + struct ActiveSprite { + int index = 0; + int row = 0; + + uint8_t info[4]; + uint8_t image[2]; + + int shift_position = 0; + } active_sprites[4]; + int active_sprite_slot = 0; + } sprite_sets_[2]; + int active_sprite_set_ = 0; + bool sprites_stopped_ = false; + + int access_pointer_ = 0; + + inline void test_sprite(int sprite_number); + inline void get_sprite_contents(int start, int cycles, int screen_row); +}; + +} + +#endif /* TMS9918Base_hpp */ diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index 24d61fa11..36284538b 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -568,6 +568,7 @@ 4BCF1FA81DADC5250039D2E7 /* CSOric.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BCF1FA71DADC5250039D2E7 /* CSOric.mm */; }; 4BCF1FAB1DADD41B0039D2E7 /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BCF1FA91DADD41B0039D2E7 /* StaticAnalyser.cpp */; }; 4BD14B111D74627C0088EAD6 /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BD14B0F1D74627C0088EAD6 /* StaticAnalyser.cpp */; }; + 4BD388421FE34E010042B588 /* 9918Base.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BD388401FE34E010042B588 /* 9918Base.cpp */; }; 4BD3A30B1EE755C800B5B501 /* Video.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BD3A3091EE755C800B5B501 /* Video.cpp */; }; 4BD468F71D8DF41D0084958B /* 1770.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BD468F51D8DF41D0084958B /* 1770.cpp */; }; 4BD4A8D01E077FD20020D856 /* PCMTrackTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BD4A8CF1E077FD20020D856 /* PCMTrackTests.mm */; }; @@ -1234,6 +1235,8 @@ 4BCF1FAA1DADD41B0039D2E7 /* StaticAnalyser.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = StaticAnalyser.hpp; path = ../../StaticAnalyser/Oric/StaticAnalyser.hpp; sourceTree = ""; }; 4BD14B0F1D74627C0088EAD6 /* StaticAnalyser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StaticAnalyser.cpp; path = ../../StaticAnalyser/Acorn/StaticAnalyser.cpp; sourceTree = ""; }; 4BD14B101D74627C0088EAD6 /* StaticAnalyser.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = StaticAnalyser.hpp; path = ../../StaticAnalyser/Acorn/StaticAnalyser.hpp; sourceTree = ""; }; + 4BD388401FE34E010042B588 /* 9918Base.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = 9918Base.cpp; path = 9918/Implementation/9918Base.cpp; sourceTree = ""; }; + 4BD388411FE34E010042B588 /* 9918Base.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = 9918Base.hpp; path = 9918/Implementation/9918Base.hpp; sourceTree = ""; }; 4BD3A3091EE755C800B5B501 /* Video.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Video.cpp; path = ZX8081/Video.cpp; sourceTree = ""; }; 4BD3A30A1EE755C800B5B501 /* Video.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Video.hpp; path = ZX8081/Video.hpp; sourceTree = ""; }; 4BD468F51D8DF41D0084958B /* 1770.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = 1770.cpp; path = 1770/1770.cpp; sourceTree = ""; }; @@ -1382,6 +1385,7 @@ children = ( 4B0E04F91FC9FA3100F43484 /* 9918.cpp */, 4B0E04F81FC9FA3000F43484 /* 9918.hpp */, + 4BD388431FE34E060042B588 /* Implementation */, ); name = 9918; sourceTree = ""; @@ -2615,6 +2619,15 @@ name = Acorn; sourceTree = ""; }; + 4BD388431FE34E060042B588 /* Implementation */ = { + isa = PBXGroup; + children = ( + 4BD388401FE34E010042B588 /* 9918Base.cpp */, + 4BD388411FE34E010042B588 /* 9918Base.hpp */, + ); + name = Implementation; + sourceTree = ""; + }; 4BD468F81D8DF4290084958B /* 1770 */ = { isa = PBXGroup; children = ( @@ -3388,6 +3401,7 @@ 4BE77A2E1D84ADFB00BC3827 /* File.cpp in Sources */, 4B14978B1EE4AC5E00CE2596 /* StaticAnalyser.cpp in Sources */, 4B12C0ED1FCFA98D005BFD93 /* Keyboard.cpp in Sources */, + 4BD388421FE34E010042B588 /* 9918Base.cpp in Sources */, 4BA0F68E1EEA0E8400E9489E /* ZX8081.cpp in Sources */, 4BD468F71D8DF41D0084958B /* 1770.cpp in Sources */, 4BD3A30B1EE755C800B5B501 /* Video.cpp in Sources */, diff --git a/OSBindings/SDL/SConstruct b/OSBindings/SDL/SConstruct index d85bc85e1..c97ce506a 100644 --- a/OSBindings/SDL/SConstruct +++ b/OSBindings/SDL/SConstruct @@ -15,6 +15,7 @@ SOURCES += glob.glob('../../Components/6522/Implementation/*.cpp') SOURCES += glob.glob('../../Components/6560/*.cpp') SOURCES += glob.glob('../../Components/8272/*.cpp') SOURCES += glob.glob('../../Components/9918/*.cpp') +SOURCES += glob.glob('../../Components/9918/Implementation/*.cpp') SOURCES += glob.glob('../../Components/AY38910/*.cpp') SOURCES += glob.glob('../../Concurrency/*.cpp') From 3da323c6572cfefd6b19e893d17a189285c178fa Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Thu, 14 Dec 2017 20:30:56 -0500 Subject: [PATCH 2/4] Corrects lingering free TMS read. --- Components/9918/9918.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Components/9918/9918.cpp b/Components/9918/9918.cpp index 6cf2ece05..2661f8f75 100644 --- a/Components/9918/9918.cpp +++ b/Components/9918/9918.cpp @@ -626,8 +626,7 @@ void TMS9918::set_register(int address, uint8_t value) { ram_pointer_ = static_cast(low_write_ | (value << 8)); if(!(value & 0x40)) { // Officially a 'read' set, so perform lookahead. - read_ahead_buffer_ = ram_[ram_pointer_ & 16383]; - ram_pointer_++; + queued_access_ = MemoryAccess::Read; } } } From ad50b6b1fbf7e48943835f64cebbfcdb77b13857 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Thu, 14 Dec 2017 21:12:51 -0500 Subject: [PATCH 3/4] Corrects TMS' `get_time_until_interrupt` when the next interrupt is exactly a frame away. --- Components/9918/9918.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Components/9918/9918.cpp b/Components/9918/9918.cpp index 2661f8f75..d3d0af630 100644 --- a/Components/9918/9918.cpp +++ b/Components/9918/9918.cpp @@ -654,7 +654,7 @@ uint8_t TMS9918::get_register(int address) { const int half_cycles_per_frame = frame_lines_ * 228 * 2; int half_cycles_remaining = (192 * 228 * 2 + half_cycles_per_frame - half_cycles_into_frame_.as_int()) % half_cycles_per_frame; - return HalfCycles(half_cycles_remaining); + return HalfCycles(half_cycles_remaining ? half_cycles_remaining : half_cycles_per_frame); } bool TMS9918::get_interrupt_line() { From ec4c259695969f4525e67ff513bccffde8c3678d Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Thu, 14 Dec 2017 21:19:09 -0500 Subject: [PATCH 4/4] Removes unused file. --- Components/9918/Implementation/9918Base.cpp | 11 ----------- OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj | 4 ---- 2 files changed, 15 deletions(-) delete mode 100644 Components/9918/Implementation/9918Base.cpp diff --git a/Components/9918/Implementation/9918Base.cpp b/Components/9918/Implementation/9918Base.cpp deleted file mode 100644 index 4e19b3866..000000000 --- a/Components/9918/Implementation/9918Base.cpp +++ /dev/null @@ -1,11 +0,0 @@ -// -// 9918Base.cpp -// Clock Signal -// -// Created by Thomas Harte on 14/12/2017. -// Copyright © 2017 Thomas Harte. All rights reserved. -// - -#include "9918Base.hpp" - - diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index 36284538b..c70f73d5e 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -568,7 +568,6 @@ 4BCF1FA81DADC5250039D2E7 /* CSOric.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BCF1FA71DADC5250039D2E7 /* CSOric.mm */; }; 4BCF1FAB1DADD41B0039D2E7 /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BCF1FA91DADD41B0039D2E7 /* StaticAnalyser.cpp */; }; 4BD14B111D74627C0088EAD6 /* StaticAnalyser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BD14B0F1D74627C0088EAD6 /* StaticAnalyser.cpp */; }; - 4BD388421FE34E010042B588 /* 9918Base.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BD388401FE34E010042B588 /* 9918Base.cpp */; }; 4BD3A30B1EE755C800B5B501 /* Video.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BD3A3091EE755C800B5B501 /* Video.cpp */; }; 4BD468F71D8DF41D0084958B /* 1770.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4BD468F51D8DF41D0084958B /* 1770.cpp */; }; 4BD4A8D01E077FD20020D856 /* PCMTrackTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4BD4A8CF1E077FD20020D856 /* PCMTrackTests.mm */; }; @@ -1235,7 +1234,6 @@ 4BCF1FAA1DADD41B0039D2E7 /* StaticAnalyser.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = StaticAnalyser.hpp; path = ../../StaticAnalyser/Oric/StaticAnalyser.hpp; sourceTree = ""; }; 4BD14B0F1D74627C0088EAD6 /* StaticAnalyser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StaticAnalyser.cpp; path = ../../StaticAnalyser/Acorn/StaticAnalyser.cpp; sourceTree = ""; }; 4BD14B101D74627C0088EAD6 /* StaticAnalyser.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = StaticAnalyser.hpp; path = ../../StaticAnalyser/Acorn/StaticAnalyser.hpp; sourceTree = ""; }; - 4BD388401FE34E010042B588 /* 9918Base.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = 9918Base.cpp; path = 9918/Implementation/9918Base.cpp; sourceTree = ""; }; 4BD388411FE34E010042B588 /* 9918Base.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = 9918Base.hpp; path = 9918/Implementation/9918Base.hpp; sourceTree = ""; }; 4BD3A3091EE755C800B5B501 /* Video.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Video.cpp; path = ZX8081/Video.cpp; sourceTree = ""; }; 4BD3A30A1EE755C800B5B501 /* Video.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = Video.hpp; path = ZX8081/Video.hpp; sourceTree = ""; }; @@ -2622,7 +2620,6 @@ 4BD388431FE34E060042B588 /* Implementation */ = { isa = PBXGroup; children = ( - 4BD388401FE34E010042B588 /* 9918Base.cpp */, 4BD388411FE34E010042B588 /* 9918Base.hpp */, ); name = Implementation; @@ -3401,7 +3398,6 @@ 4BE77A2E1D84ADFB00BC3827 /* File.cpp in Sources */, 4B14978B1EE4AC5E00CE2596 /* StaticAnalyser.cpp in Sources */, 4B12C0ED1FCFA98D005BFD93 /* Keyboard.cpp in Sources */, - 4BD388421FE34E010042B588 /* 9918Base.cpp in Sources */, 4BA0F68E1EEA0E8400E9489E /* ZX8081.cpp in Sources */, 4BD468F71D8DF41D0084958B /* 1770.cpp in Sources */, 4BD3A30B1EE755C800B5B501 /* Video.cpp in Sources */,