openMSX
MSXHBI55.cc
Go to the documentation of this file.
1 /* Submitted By: Albert Beevendorp (bifimsx)
2  *
3  * Some Sony MSX machines have built-in firmware
4  * containing an address 'book', memo and scheduler and a
5  * few of these can store these data on a data cartridge.
6  *
7  * In Basic it's possible to use it with the "CAT:" device.
8  *
9  * I'm not sure if there are more types, though the HBI-55
10  * is a 4KB SRAM containing cartridge accessed by I/O
11  * ports connected to a 8255 chip:
12  *
13  * B0 = LSB address
14  * B1 = MSB address (D7-D6 = 01 write, 11 read)
15  * B2 = Data port
16  * B3 = Access control
17  *
18  * Sample basic program:
19  *
20  * 10 FOR I=0 TO 4095: OUT &HB3,128: OUT &HB0,I MOD 256:
21  * OUT &HB1,64 OR I\256: OUT &HB2,I MOD 256: NEXT I
22  * 20 FOR I=0 TO 4095:OUT &HB3,128-9*(I<>0): OUT &HB0,I MOD 256:
23  * OUT &HB1,192 OR I\256: IF I MOD 256=INP(&HB2) THEN NEXT
24  * ELSE PRINT "Error comparing byte:";I: END
25  * 30 PRINT "Done!"
26  *
27  * -----
28  *
29  * Improved code mostly copied from blueMSX, many thanks to Daniel Vik.
30  * http://cvs.sourceforge.net/viewcvs.py/bluemsx/blueMSX/Src/Memory/romMapperSonyHBI55.c
31  */
32 
33 #include "MSXHBI55.hh"
34 #include "GlobalSettings.hh"
35 #include "serialize.hh"
36 
37 namespace openmsx {
38 
39 // MSXDevice
40 
42  : MSXDevice(config)
43  , i8255(*this, getCurrentTime(), config.getGlobalSettings().getInvalidPpiModeSetting())
44  , sram(getName() + " SRAM", 0x1000, config)
45 {
47 }
48 
49 void MSXHBI55::reset(EmuTime::param time)
50 {
51  readAddress = 0;
52  writeAddress = 0;
53  addressLatch = 0;
54  writeLatch = 0;
55  mode = 0;
56  i8255.reset(time);
57 }
58 
59 byte MSXHBI55::readIO(word port, EmuTime::param time)
60 {
61  return i8255.read(port & 0x03, time);
62 }
63 
64 byte MSXHBI55::peekIO(word port, EmuTime::param time) const
65 {
66  return i8255.peek(port & 0x03, time);
67 }
68 
69 void MSXHBI55::writeIO(word port, byte value, EmuTime::param time)
70 {
71  i8255.write(port & 0x03, value, time);
72 }
73 
74 
75 // I8255Interface
76 
77 byte MSXHBI55::readA(EmuTime::param time)
78 {
79  return peekA(time);
80 }
81 byte MSXHBI55::peekA(EmuTime::param /*time*/) const
82 {
83  // TODO check this
84  return 255;
85 }
86 byte MSXHBI55::readB(EmuTime::param time)
87 {
88  return peekB(time);
89 }
90 byte MSXHBI55::peekB(EmuTime::param /*time*/) const
91 {
92  // TODO check this
93  return 255;
94 }
95 
96 void MSXHBI55::writeA(byte value, EmuTime::param /*time*/)
97 {
98  addressLatch = value;
99 }
100 void MSXHBI55::writeB(byte value, EmuTime::param /*time*/)
101 {
102  word address = addressLatch | ((value & 0x0F) << 8);
103  mode = value >> 6;
104  switch (mode) {
105  case 0:
106  readAddress = 0;
107  writeAddress = 0;
108  break;
109  case 1:
110  writeAddress = address;
111  break;
112  case 2:
113  sram.write(writeAddress, writeLatch);
114  break;
115  case 3:
116  readAddress = address;
117  break;
118  }
119 }
120 
121 nibble MSXHBI55::readC0(EmuTime::param time)
122 {
123  return peekC0(time);
124 }
125 nibble MSXHBI55::peekC0(EmuTime::param /*time*/) const
126 {
127  return readSRAM(readAddress) & 0x0F;
128 }
129 nibble MSXHBI55::readC1(EmuTime::param time)
130 {
131  return peekC1(time);
132 }
133 nibble MSXHBI55::peekC1(EmuTime::param /*time*/) const
134 {
135  return readSRAM(readAddress) >> 4;
136 }
137 
138 // When only one of the nibbles is written (actually when one is set as
139 // input the other as output), the other nibble gets the value of the
140 // last time that nibble was written. Thanks to Laurens Holst for
141 // investigating this. See this bug report for more details:
142 // https://sourceforge.net/p/openmsx/bugs/536/
143 void MSXHBI55::writeC0(nibble value, EmuTime::param /*time*/)
144 {
145  writeLatch = (writeLatch & 0xF0) | value;
146  if (mode == 1) {
147  sram.write(writeAddress, writeLatch);
148  }
149 }
150 void MSXHBI55::writeC1(nibble value, EmuTime::param /*time*/)
151 {
152  writeLatch = (writeLatch & 0x0F) | (value << 4);
153  if (mode == 1) {
154  sram.write(writeAddress, writeLatch);
155  }
156 }
157 
158 byte MSXHBI55::readSRAM(word address) const
159 {
160  return address ? sram[address] : 0x53;
161 }
162 
163 template<typename Archive>
164 void MSXHBI55::serialize(Archive& ar, unsigned /*version*/)
165 {
166  ar.template serializeBase<MSXDevice>(*this);
167  ar.serialize("i8255", i8255,
168  "SRAM", sram,
169  "readAddress", readAddress,
170  "writeAddress", writeAddress,
171  "addressLatch", addressLatch,
172  "writeLatch", writeLatch,
173  "mode", mode);
174 }
177 
178 } // namespace openmsx
openmsx::MSXDevice
An MSXDevice is an emulated hardware component connected to the bus of the emulated MSX.
Definition: MSXDevice.hh:32
serialize.hh
openmsx::I8255::write
void write(byte port, byte value, EmuTime::param time)
Definition: I8255.cc:76
openmsx::I8255::peek
byte peek(byte port, EmuTime::param time) const
Definition: I8255.cc:59
openmsx::DeviceConfig
Definition: DeviceConfig.hh:20
MSXHBI55.hh
openmsx::MSXHBI55
Definition: MSXHBI55.hh:12
openmsx::MSXHBI55::MSXHBI55
MSXHBI55(const DeviceConfig &config)
Definition: MSXHBI55.cc:41
openmsx::MSXHBI55::readIO
byte readIO(word port, EmuTime::param time) override
Read a byte from an IO port at a certain time from this device.
Definition: MSXHBI55.cc:59
openmsx::REGISTER_MSXDEVICE
REGISTER_MSXDEVICE(ChakkariCopy, "ChakkariCopy")
openmsx::I8255::reset
void reset(EmuTime::param time)
Definition: I8255.cc:33
openmsx::MSXHBI55::peekIO
byte peekIO(word port, EmuTime::param time) const override
Read a byte from a given IO port.
Definition: MSXHBI55.cc:64
openmsx::Keys::getName
string getName(KeyCode keyCode)
Translate key code to key name.
Definition: Keys.cc:740
openmsx::nibble
uint8_t nibble
4 bit integer
Definition: openmsx.hh:23
openmsx::MSXDevice::getCurrentTime
EmuTime::param getCurrentTime() const
Definition: MSXDevice.cc:131
INSTANTIATE_SERIALIZE_METHODS
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:981
openmsx::SRAM::write
void write(unsigned addr, byte value)
Definition: SRAM.cc:67
openmsx::I8255::read
byte read(byte port, EmuTime::param time)
Definition: I8255.cc:42
GlobalSettings.hh
openmsx::MSXHBI55::serialize
void serialize(Archive &ar, unsigned version)
Definition: MSXHBI55.cc:164
openmsx::word
uint16_t word
16 bit unsigned integer
Definition: openmsx.hh:29
openmsx::MSXHBI55::reset
void reset(EmuTime::param time) override
This method is called on reset.
Definition: MSXHBI55.cc:49
openmsx
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
openmsx::MSXHBI55::writeIO
void writeIO(word port, byte value, EmuTime::param time) override
Write a byte to a given IO port at a certain time to this device.
Definition: MSXHBI55.cc:69