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