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 "serialize.hh"
35 
36 namespace openmsx {
37 
38 // MSXDevice
39 
41  : MSXDevice(config)
42  , i8255(*this, getCurrentTime(), getCliComm())
43  , sram(getName() + " SRAM", 0x1000, config)
44 {
46 }
47 
48 void MSXHBI55::reset(EmuTime::param time)
49 {
50  readAddress = 0;
51  writeAddress = 0;
52  addressLatch = 0;
53  writeLatch = 0;
54  mode = 0;
55  i8255.reset(time);
56 }
57 
58 byte MSXHBI55::readIO(word port, EmuTime::param time)
59 {
60  return i8255.read(port & 0x03, time);
61 }
62 
63 byte MSXHBI55::peekIO(word port, EmuTime::param time) const
64 {
65  return i8255.peek(port & 0x03, time);
66 }
67 
68 void MSXHBI55::writeIO(word port, byte value, EmuTime::param time)
69 {
70  i8255.write(port & 0x03, value, time);
71 }
72 
73 
74 // I8255Interface
75 
76 byte MSXHBI55::readA(EmuTime::param time)
77 {
78  return peekA(time);
79 }
80 byte MSXHBI55::peekA(EmuTime::param /*time*/) const
81 {
82  // TODO check this
83  return 255;
84 }
85 byte MSXHBI55::readB(EmuTime::param time)
86 {
87  return peekB(time);
88 }
89 byte MSXHBI55::peekB(EmuTime::param /*time*/) const
90 {
91  // TODO check this
92  return 255;
93 }
94 
95 void MSXHBI55::writeA(byte value, EmuTime::param /*time*/)
96 {
97  addressLatch = value;
98 }
99 void MSXHBI55::writeB(byte value, EmuTime::param /*time*/)
100 {
101  word address = addressLatch | ((value & 0x0F) << 8);
102  mode = value >> 6;
103  switch (mode) {
104  case 0:
105  readAddress = 0;
106  writeAddress = 0;
107  break;
108  case 1:
109  writeAddress = address;
110  break;
111  case 2:
112  sram.write(writeAddress, writeLatch);
113  break;
114  case 3:
115  readAddress = address;
116  break;
117  }
118 }
119 
120 nibble MSXHBI55::readC0(EmuTime::param time)
121 {
122  return peekC0(time);
123 }
124 nibble MSXHBI55::peekC0(EmuTime::param /*time*/) const
125 {
126  return readSRAM(readAddress) & 0x0F;
127 }
128 nibble MSXHBI55::readC1(EmuTime::param time)
129 {
130  return peekC1(time);
131 }
132 nibble MSXHBI55::peekC1(EmuTime::param /*time*/) const
133 {
134  return readSRAM(readAddress) >> 4;
135 }
136 
137 // When only one of the nibbles is written (actually when one is set as
138 // input the other as output), the other nibble gets the value of the
139 // last time that nibble was written. Thanks to Laurens Holst for
140 // investigating this. See this bug report for more details:
141 // https://sourceforge.net/p/openmsx/bugs/536/
142 void MSXHBI55::writeC0(nibble value, EmuTime::param /*time*/)
143 {
144  writeLatch = (writeLatch & 0xF0) | value;
145  if (mode == 1) {
146  sram.write(writeAddress, writeLatch);
147  }
148 }
149 void MSXHBI55::writeC1(nibble value, EmuTime::param /*time*/)
150 {
151  writeLatch = (writeLatch & 0x0F) | (value << 4);
152  if (mode == 1) {
153  sram.write(writeAddress, writeLatch);
154  }
155 }
156 
157 byte MSXHBI55::readSRAM(word address) const
158 {
159  return address ? sram[address] : 0x53;
160 }
161 
162 template<typename Archive>
163 void MSXHBI55::serialize(Archive& ar, unsigned /*version*/)
164 {
165  ar.template serializeBase<MSXDevice>(*this);
166  ar.serialize("i8255", i8255,
167  "SRAM", sram,
168  "readAddress", readAddress,
169  "writeAddress", writeAddress,
170  "addressLatch", addressLatch,
171  "writeLatch", writeLatch,
172  "mode", mode);
173 }
175 REGISTER_MSXDEVICE(MSXHBI55, "MSXHBI55");
176 
177 } // namespace openmsx
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:58
byte peekIO(word port, EmuTime::param time) const override
Read a byte from a given IO port.
Definition: MSXHBI55.cc:63
MSXHBI55(const DeviceConfig &config)
Definition: MSXHBI55.cc:40
void reset(EmuTime::param time) override
This method is called on reset.
Definition: MSXHBI55.cc:48
uint8_t byte
8 bit unsigned integer
Definition: openmsx.hh:26
void write(unsigned addr, byte value)
Definition: SRAM.cc:67
REGISTER_MSXDEVICE(ChakkariCopy, "ChakkariCopy")
void serialize(Archive &ar, unsigned version)
Definition: MSXHBI55.cc:163
byte peek(byte port, EmuTime::param time) const
Definition: I8255.cc:60
EmuTime::param getCurrentTime() const
Definition: MSXDevice.cc:133
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
An MSXDevice is an emulated hardware component connected to the bus of the emulated MSX...
Definition: MSXDevice.hh:31
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:68
uint8_t nibble
4 bit integer
Definition: openmsx.hh:23
byte read(byte port, EmuTime::param time)
Definition: I8255.cc:43
uint16_t word
16 bit unsigned integer
Definition: openmsx.hh:29
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:1006
string getName(KeyCode keyCode)
Translate key code to key name.
Definition: Keys.cc:589
void reset(EmuTime::param time)
Definition: I8255.cc:34
void write(byte port, byte value, EmuTime::param time)
Definition: I8255.cc:77