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 "Cart2K.hxx"
20
21// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
22Cartridge2K::Cartridge2K(const ByteBuffer& image, size_t size,
23 const string& md5, const Settings& settings)
24 : Cartridge(settings, md5)
25{
26 // Size can be a maximum of 2K
27 if(size > 2_KB) size = 2_KB;
28
29 // Set image size to closest power-of-two for the given size
30 mySize = 1;
31 while(mySize < size)
32 mySize <<= 1;
33
34 // We can't use a size smaller than the minimum page size in Stella
35 mySize = std::max<size_t>(mySize, System::PAGE_SIZE);
36
37 // Initialize ROM with illegal 6502 opcode that causes a real 6502 to jam
38 myImage = make_unique<uInt8[]>(mySize);
39 std::fill_n(myImage.get(), mySize, 0x02);
40
41 // Copy the ROM image into my buffer
42 std::copy_n(image.get(), size, myImage.get());
43 createCodeAccessBase(mySize);
44
45 // Set mask for accessing the image buffer
46 // This is guaranteed to work, as mySize is a power of two
47 myMask = static_cast<uInt16>(mySize) - 1;
48}
49
50// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
51void Cartridge2K::reset()
52{
53 myBankChanged = true;
54}
55
56// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
57void Cartridge2K::install(System& system)
58{
59 mySystem = &system;
60
61 // Map ROM image into the system
62 // Note that we don't need our own peek/poke methods, since the mapping
63 // takes care of the entire address space
64 System::PageAccess access(this, System::PageAccessType::READ);
65 for(uInt16 addr = 0x1000; addr < 0x2000; addr += System::PAGE_SIZE)
66 {
67 access.directPeekBase = &myImage[addr & myMask];
68 access.codeAccessBase = &myCodeAccessBase[addr & myMask];
69 mySystem->setPageAccess(addr, access);
70 }
71}
72
73// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
74bool Cartridge2K::patch(uInt16 address, uInt8 value)
75{
76 myImage[address & myMask] = value;
77 return myBankChanged = true;
78}
79
80// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
81const uInt8* Cartridge2K::getImage(size_t& size) const
82{
83 size = mySize;
84 return myImage.get();
85}
86
87// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
88bool Cartridge2K::save(Serializer&) const
89{
90 return true;
91}
92
93// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
94bool Cartridge2K::load(Serializer&)
95{
96 return true;
97}
98