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