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