ADVram.cc 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. #include "ADVram.hh"
  2. #include "VDP.hh"
  3. #include "VDPVRAM.hh"
  4. #include "MSXException.hh"
  5. #include "serialize.hh"
  6. #include <algorithm>
  7. namespace openmsx {
  8. ADVram::ADVram(const DeviceConfig& config)
  9. : MSXDevice(config)
  10. , vdp(nullptr)
  11. , vram(nullptr)
  12. , hasEnable(config.getChildDataAsBool("hasEnable", true))
  13. {
  14. reset(EmuTime::dummy());
  15. }
  16. void ADVram::init()
  17. {
  18. MSXDevice::init();
  19. auto& refs = getReferences();
  20. if (refs.size() != 1) {
  21. throw MSXException("Invalid ADVRAM configuration: "
  22. "need reference to VDP device.");
  23. }
  24. vdp = dynamic_cast<VDP*>(refs[0]);
  25. if (!vdp) {
  26. throw MSXException("Invalid ADVRAM configuration: device '",
  27. refs[0]->getName(), "' is not a VDP device.");
  28. }
  29. vram = &vdp->getVRAM();
  30. mask = std::min(vram->getSize(), 128u * 1024) - 1;
  31. }
  32. void ADVram::reset(EmuTime::param /*time*/)
  33. {
  34. // TODO figure out exactly what happens during reset
  35. baseAddr = 0;
  36. planar = false;
  37. enabled = !hasEnable;
  38. }
  39. byte ADVram::readIO(word port, EmuTime::param /*time*/)
  40. {
  41. // ADVram only gets 'read's from 0x9A
  42. if (hasEnable) {
  43. enabled = ((port & 0x8000) != 0);
  44. planar = ((port & 0x4000) != 0);
  45. } else {
  46. planar = ((port & 0x0100) != 0);
  47. }
  48. return 0xFF;
  49. }
  50. void ADVram::writeIO(word /*port*/, byte value, EmuTime::param /*time*/)
  51. {
  52. // set mapper register
  53. baseAddr = (value & 0x07) << 14;
  54. }
  55. unsigned ADVram::calcAddress(word address) const
  56. {
  57. unsigned addr = (address & 0x3FFF) | baseAddr;
  58. if (planar) {
  59. addr = ((addr & 1) << 16) | (addr >> 1);
  60. }
  61. return addr & mask;
  62. }
  63. byte ADVram::readMem(word address, EmuTime::param time)
  64. {
  65. return enabled ? vram->cpuRead(calcAddress(address), time) : 0xFF;
  66. }
  67. void ADVram::writeMem(word address, byte value, EmuTime::param time)
  68. {
  69. if (enabled) {
  70. vram->cpuWrite(calcAddress(address), value, time);
  71. }
  72. }
  73. template<typename Archive>
  74. void ADVram::serialize(Archive& ar, unsigned /*version*/)
  75. {
  76. ar.template serializeBase<MSXDevice>(*this);
  77. ar.serialize("baseAddr", baseAddr,
  78. "enabled", enabled,
  79. "planar", planar);
  80. }
  81. INSTANTIATE_SERIALIZE_METHODS(ADVram);
  82. REGISTER_MSXDEVICE(ADVram, "ADVRAM");
  83. } // namespace openmsx