00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef ZERORAMBANK_H
00023 #define ZERORAMBANK_H
00024
00025 #include "Bank.h"
00026 #include "sidplayfp/event.h"
00027
00028 #include <stdint.h>
00029
00033 class PLA
00034 {
00035 public:
00036 virtual void setCpuPort(int state) =0;
00037 virtual uint8_t getLastReadByte() const =0;
00038 virtual event_clock_t getPhi2Time() const =0;
00039 };
00040
00055 class ZeroRAMBank : public Bank
00056 {
00057 private:
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074 static const event_clock_t C64_CPU6510_DATA_PORT_FALL_OFF_CYCLES = 350000;
00075
00076
00077
00078
00079
00080
00081
00082
00083 static const bool tape_sense = false;
00084
00085 private:
00086 PLA* pla;
00087
00089 Bank* ramBank;
00090
00093 event_clock_t dataSetClkBit6;
00094 event_clock_t dataSetClkBit7;
00096
00101 bool dataFalloffBit6;
00102 bool dataFalloffBit7;
00104
00107 uint8_t dataSetBit6;
00108 uint8_t dataSetBit7;
00110
00113 uint8_t dir;
00114 uint8_t data;
00116
00118 uint8_t dataRead;
00119
00121 uint8_t procPortPins;
00122
00123 private:
00124 void updateCpuPort()
00125 {
00126
00127 procPortPins = (procPortPins & ~dir) | (data & dir);
00128
00129 dataRead = (data | ~dir) & (procPortPins | 0x17);
00130
00131 pla->setCpuPort((data | ~dir) & 0x07);
00132
00133 if ((dir & 0x20) == 0)
00134 {
00135 dataRead &= ~0x20;
00136 }
00137 if (tape_sense && (dir & 0x10) == 0)
00138 {
00139 dataRead &= ~0x10;
00140 }
00141 }
00142
00143 private:
00144 ZeroRAMBank(const ZeroRAMBank&);
00145 ZeroRAMBank& operator=(const ZeroRAMBank&);
00146
00147 public:
00148 ZeroRAMBank(PLA* pla, Bank* ramBank) :
00149 pla(pla),
00150 ramBank(ramBank) {}
00151
00152 void reset()
00153 {
00154 dataFalloffBit6 = false;
00155 dataFalloffBit7 = false;
00156 dir = 0;
00157 data = 0x3f;
00158 dataRead = 0x3f;
00159 procPortPins = 0x3f;
00160 updateCpuPort();
00161 }
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179 uint8_t peek(uint_least16_t address)
00180 {
00181 switch (address)
00182 {
00183 case 0:
00184 return dir;
00185 case 1:
00186 {
00187
00188 if (dataFalloffBit6 || dataFalloffBit7)
00189 {
00190 const event_clock_t phi2time = pla->getPhi2Time();
00191
00192
00193 if (dataFalloffBit6 && dataSetClkBit6 < phi2time)
00194 {
00195 dataFalloffBit6 = false;
00196 dataSetBit6 = 0;
00197 }
00198
00199
00200 if (dataFalloffBit7 && dataSetClkBit7 < phi2time)
00201 {
00202 dataFalloffBit7 = false;
00203 dataSetBit7 = 0;
00204 }
00205 }
00206
00207 uint8_t retval = dataRead;
00208
00209
00210
00211
00212 if (!(dir & 0x40))
00213 {
00214 retval &= ~0x40;
00215 retval |= dataSetBit6;
00216 }
00217
00218
00219 if (!(dir & 0x80))
00220 {
00221 retval &= ~0x80;
00222 retval |= dataSetBit7;
00223 }
00224
00225 return retval;
00226 }
00227 default:
00228 return ramBank->peek(address);
00229 }
00230 }
00231
00232 void poke(uint_least16_t address, uint8_t value)
00233 {
00234 switch (address)
00235 {
00236 case 0:
00237
00238
00239
00240
00241
00242 if ((dir & 0x40) && !(value & 0x40))
00243 {
00244 dataSetClkBit6 = pla->getPhi2Time() + C64_CPU6510_DATA_PORT_FALL_OFF_CYCLES;
00245 dataSetBit6 = data & 0x40;
00246 dataFalloffBit6 = true;
00247 }
00248
00249
00250 if ((dir & 0x80) && !(value & 0x80))
00251 {
00252 dataSetClkBit7 = pla->getPhi2Time() + C64_CPU6510_DATA_PORT_FALL_OFF_CYCLES;
00253 dataSetBit7 = data & 0x80;
00254 dataFalloffBit7 = true;
00255 }
00256
00257 if (dir != value)
00258 {
00259 dir = value;
00260 updateCpuPort();
00261 }
00262 value = pla->getLastReadByte();
00263 break;
00264 case 1:
00265
00266
00267
00268 if (dir & 0x40)
00269 {
00270 dataSetBit6 = value & 0x40;
00271 dataSetClkBit6 = pla->getPhi2Time() + C64_CPU6510_DATA_PORT_FALL_OFF_CYCLES;
00272 dataFalloffBit6 = true;
00273 }
00274
00275 if (dir & 0x80)
00276 {
00277 dataSetBit7 = value & 0x80;
00278 dataSetClkBit7 = pla->getPhi2Time() + C64_CPU6510_DATA_PORT_FALL_OFF_CYCLES;
00279 dataFalloffBit7 = true;
00280 }
00281
00282 if (data != value)
00283 {
00284 data = value;
00285 updateCpuPort();
00286 }
00287 value = pla->getLastReadByte();
00288 break;
00289 default:
00290 break;
00291 }
00292
00293 ramBank->poke(address, value);
00294 }
00295 };
00296
00297 #endif