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 "M6532.hxx"
20#include "TIA.hxx"
21#include "CartX07.hxx"
22
23// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
24CartridgeX07::CartridgeX07(const ByteBuffer& image, size_t size,
25 const string& md5, const Settings& settings)
26 : Cartridge(settings, md5),
27 myCurrentBank(0)
28{
29 // Copy the ROM image into my buffer
30 std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
31 createCodeAccessBase(myImage.size());
32}
33
34// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
35void CartridgeX07::reset()
36{
37 // Upon reset we switch to the startup bank
38 initializeStartBank(0);
39 bank(startBank());
40}
41
42// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
43void CartridgeX07::install(System& system)
44{
45 mySystem = &system;
46
47 // Set the page accessing methods for the hot spots
48 // The hotspots use almost all addresses below 0x1000, so we simply grab them
49 // all and forward the TIA/RIOT calls from the peek and poke methods.
50 System::PageAccess access(this, System::PageAccessType::READWRITE);
51 for(uInt16 addr = 0x00; addr < 0x1000; addr += System::PAGE_SIZE)
52 mySystem->setPageAccess(addr, access);
53
54 // Install pages for the startup bank
55 bank(startBank());
56}
57
58// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
59uInt8 CartridgeX07::peek(uInt16 address)
60{
61 uInt8 value = 0;
62
63 // Check for RAM or TIA mirroring
64 uInt16 lowAddress = address & 0x3ff;
65 if(lowAddress & 0x80)
66 value = mySystem->m6532().peek(address);
67 else if(!(lowAddress & 0x200))
68 value = mySystem->tia().peek(address);
69
70 // Switch banks if necessary
71 if((address & 0x180f) == 0x080d)
72 bank((address & 0xf0) >> 4);
73 else if((address & 0x1880) == 0)
74 {
75 if((myCurrentBank & 0xe) == 0xe)
76 bank(((address & 0x40) >> 6) | (myCurrentBank & 0xe));
77 }
78
79 return value;
80}
81
82// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
83bool CartridgeX07::poke(uInt16 address, uInt8 value)
84{
85 // Check for RAM or TIA mirroring
86 uInt16 lowAddress = address & 0x3ff;
87 if(lowAddress & 0x80)
88 mySystem->m6532().poke(address, value);
89 else if(!(lowAddress & 0x200))
90 mySystem->tia().poke(address, value);
91
92 // Switch banks if necessary
93 if((address & 0x180f) == 0x080d)
94 bank((address & 0xf0) >> 4);
95 else if((address & 0x1880) == 0)
96 {
97 if((myCurrentBank & 0xe) == 0xe)
98 bank(((address & 0x40) >> 6) | (myCurrentBank & 0xe));
99 }
100 return false;
101}
102
103// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
104bool CartridgeX07::bank(uInt16 bank)
105{
106 if(bankLocked()) return false;
107
108 // Remember what bank we're in
109 myCurrentBank = (bank & 0x0f);
110 uInt32 offset = myCurrentBank << 12;
111
112 // Setup the page access methods for the current bank
113 System::PageAccess access(this, System::PageAccessType::READ);
114
115 // Map ROM image into the system
116 for(uInt16 addr = 0x1000; addr < 0x2000; addr += System::PAGE_SIZE)
117 {
118 access.directPeekBase = &myImage[offset + (addr & 0x0FFF)];
119 access.codeAccessBase = &myCodeAccessBase[offset + (addr & 0x0FFF)];
120 mySystem->setPageAccess(addr, access);
121 }
122 return myBankChanged = true;
123}
124
125// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
126uInt16 CartridgeX07::getBank(uInt16) const
127{
128 return myCurrentBank;
129}
130
131// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
132uInt16 CartridgeX07::bankCount() const
133{
134 return 16;
135}
136
137// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
138bool CartridgeX07::patch(uInt16 address, uInt8 value)
139{
140 myImage[(myCurrentBank << 12) + (address & 0x0FFF)] = value;
141 return myBankChanged = true;
142}
143
144// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
145const uInt8* CartridgeX07::getImage(size_t& size) const
146{
147 size = myImage.size();
148 return myImage.data();
149}
150
151// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
152bool CartridgeX07::save(Serializer& out) const
153{
154 try
155 {
156 out.putShort(myCurrentBank);
157 }
158 catch(...)
159 {
160 cerr << "ERROR: CartridgeX07::save" << endl;
161 return false;
162 }
163
164 return true;
165}
166
167// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
168bool CartridgeX07::load(Serializer& in)
169{
170 try
171 {
172 myCurrentBank = in.getShort();
173 }
174 catch(...)
175 {
176 cerr << "ERROR: CartridgeX07::load" << endl;
177 return false;
178 }
179
180 // Remember what bank we were in
181 bank(myCurrentBank);
182
183 return true;
184}
185