1//============================================================================
2//
3// SSSS tt lll lll
4// SS SS tt ll ll
5// SS tttttt eeee ll ll aaaa
6// SSSS tt ee ee ll ll aa
7// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
8// SS SS tt ee ll ll aa aa
9// SSSS ttt eeeee llll llll aaaaa
10//
11// Copyright (c) 1995-2019 by Bradford W. Mott, Stephen Anthony
12// and the Stella Team
13//
14// See the file "License.txt" for information on usage and redistribution of
15// this file, and for a DISCLAIMER OF ALL WARRANTIES.
16//============================================================================
17
18#include "System.hxx"
19#include "Cart4KSC.hxx"
20
21// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
22Cartridge4KSC::Cartridge4KSC(const ByteBuffer& image, size_t size,
23 const string& md5, const Settings& settings)
24 : Cartridge(settings, md5)
25{
26 // Copy the ROM image into my buffer
27 std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
28 createCodeAccessBase(myImage.size());
29}
30
31// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
32void Cartridge4KSC::reset()
33{
34 initializeRAM(myRAM.data(), myRAM.size());
35
36 myBankChanged = true;
37}
38
39// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
40void Cartridge4KSC::install(System& system)
41{
42 mySystem = &system;
43
44 System::PageAccess access(this, System::PageAccessType::READ);
45
46 // Set the page accessing method for the RAM writing pages
47 // Map access to this class, since we need to inspect all accesses to
48 // check if RWP happens
49 access.type = System::PageAccessType::WRITE;
50 for(uInt16 addr = 0x1000; addr < 0x1080; addr += System::PAGE_SIZE)
51 {
52 access.codeAccessBase = &myCodeAccessBase[addr & 0x007F];
53 mySystem->setPageAccess(addr, access);
54 }
55
56 // Set the page accessing method for the RAM reading pages
57 access.type = System::PageAccessType::READ;
58 for(uInt16 addr = 0x1080; addr < 0x1100; addr += System::PAGE_SIZE)
59 {
60 access.directPeekBase = &myRAM[addr & 0x007F];
61 access.codeAccessBase = &myCodeAccessBase[0x80 + (addr & 0x007F)];
62 mySystem->setPageAccess(addr, access);
63 }
64
65 // Map ROM image into the system
66 for(uInt16 addr = 0x1100; addr < 0x2000; addr += System::PAGE_SIZE)
67 {
68 access.directPeekBase = &myImage[addr & 0x0FFF];
69 access.codeAccessBase = &myCodeAccessBase[addr & 0x0FFF];
70 mySystem->setPageAccess(addr, access);
71 }
72}
73
74// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
75uInt8 Cartridge4KSC::peek(uInt16 address)
76{
77 // The only way we can get to this method is if we attempt to read from
78 // the write port (0xF000 - 0xF07F, 128 bytes), in which case an
79 // unwanted write is potentially triggered
80 return peekRAM(myRAM[address & 0x007F], address);
81}
82
83// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
84bool Cartridge4KSC::poke(uInt16 address, uInt8 value)
85{
86 if (!(address & 0x080))
87 {
88 pokeRAM(myRAM[address & 0x007F], address, value);
89 return true;
90 }
91 else
92 {
93 // Writing to the read port should be ignored, but trigger a break if option enabled
94 uInt8 dummy;
95
96 pokeRAM(dummy, address, value);
97 myRamWriteAccess = address;
98 return false;
99 }
100}
101
102// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
103bool Cartridge4KSC::patch(uInt16 address, uInt8 value)
104{
105 address &= 0x0FFF;
106
107 if(address < 0x0100)
108 {
109 // Normally, a write to the read port won't do anything
110 // However, the patch command is special in that ignores such
111 // cart restrictions
112 myRAM[address & 0x007F] = value;
113 }
114 else
115 myImage[address & 0xFFF] = value;
116
117 return myBankChanged = true;
118}
119
120// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
121const uInt8* Cartridge4KSC::getImage(size_t& size) const
122{
123 size = myImage.size();
124 return myImage.data();
125}
126
127// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
128bool Cartridge4KSC::save(Serializer& out) const
129{
130 try
131 {
132 out.putByteArray(myRAM.data(), myRAM.size());
133 }
134 catch(...)
135 {
136 cerr << "ERROR: Cartridge4KSC::save" << endl;
137 return false;
138 }
139
140 return true;
141}
142
143// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
144bool Cartridge4KSC::load(Serializer& in)
145{
146 try
147 {
148 in.getByteArray(myRAM.data(), myRAM.size());
149 }
150 catch(...)
151 {
152 cerr << "ERROR: Cartridge4KSC::load" << endl;
153 return false;
154 }
155
156 return true;
157}
158