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 "CartF6.hxx"
20
21// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
22CartridgeF6::CartridgeF6(const ByteBuffer& image, size_t size,
23 const string& md5, const Settings& settings)
24 : Cartridge(settings, md5),
25 myBankOffset(0)
26{
27 // Copy the ROM image into my buffer
28 std::copy_n(image.get(), std::min(myImage.size(), size), myImage.begin());
29 createCodeAccessBase(myImage.size());
30}
31
32// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
33void CartridgeF6::reset()
34{
35 // Upon reset we switch to the startup bank
36 initializeStartBank(0);
37 bank(startBank());
38}
39
40// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
41void CartridgeF6::install(System& system)
42{
43 mySystem = &system;
44
45 // Upon install we'll setup the startup bank
46 bank(startBank());
47}
48
49// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
50uInt8 CartridgeF6::peek(uInt16 address)
51{
52 address &= 0x0FFF;
53
54 // Switch banks if necessary
55 switch(address)
56 {
57 case 0x0FF6:
58 // Set the current bank to the first 4k bank
59 bank(0);
60 break;
61
62 case 0x0FF7:
63 // Set the current bank to the second 4k bank
64 bank(1);
65 break;
66
67 case 0x0FF8:
68 // Set the current bank to the third 4k bank
69 bank(2);
70 break;
71
72 case 0x0FF9:
73 // Set the current bank to the forth 4k bank
74 bank(3);
75 break;
76
77 default:
78 break;
79 }
80
81 return myImage[myBankOffset + address];
82}
83
84// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
85bool CartridgeF6::poke(uInt16 address, uInt8)
86{
87 address &= 0x0FFF;
88
89 // Switch banks if necessary
90 switch(address)
91 {
92 case 0x0FF6:
93 // Set the current bank to the first 4k bank
94 bank(0);
95 break;
96
97 case 0x0FF7:
98 // Set the current bank to the second 4k bank
99 bank(1);
100 break;
101
102 case 0x0FF8:
103 // Set the current bank to the third 4k bank
104 bank(2);
105 break;
106
107 case 0x0FF9:
108 // Set the current bank to the forth 4k bank
109 bank(3);
110 break;
111
112 default:
113 break;
114 }
115 return false;
116}
117
118// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
119bool CartridgeF6::bank(uInt16 bank)
120{
121 if(bankLocked()) return false;
122
123 // Remember what bank we're in
124 myBankOffset = bank << 12;
125
126 System::PageAccess access(this, System::PageAccessType::READ);
127
128 // Set the page accessing methods for the hot spots
129 for(uInt16 addr = (0x1FF6 & ~System::PAGE_MASK); addr < 0x2000;
130 addr += System::PAGE_SIZE)
131 {
132 access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
133 mySystem->setPageAccess(addr, access);
134 }
135
136 // Setup the page access methods for the current bank
137 for(uInt16 addr = 0x1000; addr < (0x1FF6U & ~System::PAGE_MASK);
138 addr += System::PAGE_SIZE)
139 {
140 access.directPeekBase = &myImage[myBankOffset + (addr & 0x0FFF)];
141 access.codeAccessBase = &myCodeAccessBase[myBankOffset + (addr & 0x0FFF)];
142 mySystem->setPageAccess(addr, access);
143 }
144 return myBankChanged = true;
145}
146
147// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
148uInt16 CartridgeF6::getBank(uInt16) const
149{
150 return myBankOffset >> 12;
151}
152
153// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
154uInt16 CartridgeF6::bankCount() const
155{
156 return 4;
157}
158
159// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
160bool CartridgeF6::patch(uInt16 address, uInt8 value)
161{
162 myImage[myBankOffset + (address & 0x0FFF)] = value;
163 return myBankChanged = true;
164}
165
166// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
167const uInt8* CartridgeF6::getImage(size_t& size) const
168{
169 size = myImage.size();
170 return myImage.data();
171}
172
173// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
174bool CartridgeF6::save(Serializer& out) const
175{
176 try
177 {
178 out.putShort(myBankOffset);
179 }
180 catch(...)
181 {
182 cerr << "ERROR: CartridgeF6::save" << endl;
183 return false;
184 }
185
186 return true;
187}
188
189// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
190bool CartridgeF6::load(Serializer& in)
191{
192 try
193 {
194 myBankOffset = in.getShort();
195 }
196 catch(...)
197 {
198 cerr << "ERROR: CartridgeF6::load" << endl;
199 return false;
200 }
201
202 // Remember what bank we were in
203 bank(myBankOffset >> 12);
204
205 return true;
206}
207