sdd1.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. #include <../base.hpp>
  2. #include <../cart/cart.hpp>
  3. #define SDD1_CPP
  4. #include "sdd1.hpp"
  5. #include "sdd1emu.cpp"
  6. void SDD1::init() {}
  7. void SDD1::enable() {
  8. //hook S-CPU DMA MMIO registers to gather information for struct dma[];
  9. //buffer address and transfer size information for use in SDD1::read()
  10. for(unsigned i = 0x4300; i <= 0x437f; i++) {
  11. cpu_mmio[i & 0x7f] = memory::mmio.get(i);
  12. memory::mmio.map(i, *this);
  13. }
  14. //hook S-DD1 MMIO registers
  15. for(unsigned i = 0x4800; i <= 0x4807; i++) {
  16. memory::mmio.map(i, *this);
  17. }
  18. }
  19. void SDD1::power() {
  20. reset();
  21. }
  22. void SDD1::reset() {
  23. sdd1_enable = 0x00;
  24. xfer_enable = 0x00;
  25. mmc[0] = 0 << 20;
  26. mmc[1] = 1 << 20;
  27. mmc[2] = 2 << 20;
  28. mmc[3] = 3 << 20;
  29. for(unsigned i = 0; i < 8; i++) {
  30. dma[i].addr = 0;
  31. dma[i].size = 0;
  32. }
  33. buffer.ready = false;
  34. bus.map(Bus::MapDirect, 0xc0, 0xff, 0x0000, 0xffff, *this);
  35. }
  36. uint8 SDD1::mmio_read(unsigned addr) {
  37. addr &= 0xffff;
  38. if((addr & 0x4380) == 0x4300) {
  39. return cpu_mmio[addr & 0x7f]->mmio_read(addr);
  40. }
  41. switch(addr) {
  42. case 0x4804: return (mmc[0] >> 20) & 7;
  43. case 0x4805: return (mmc[1] >> 20) & 7;
  44. case 0x4806: return (mmc[2] >> 20) & 7;
  45. case 0x4807: return (mmc[3] >> 20) & 7;
  46. }
  47. return cpu.regs.mdr;
  48. }
  49. void SDD1::mmio_write(unsigned addr, uint8 data) {
  50. addr &= 0xffff;
  51. if((addr & 0x4380) == 0x4300) {
  52. unsigned channel = (addr >> 4) & 7;
  53. switch(addr & 15) {
  54. case 2: dma[channel].addr = (dma[channel].addr & 0xffff00) + (data << 0); break;
  55. case 3: dma[channel].addr = (dma[channel].addr & 0xff00ff) + (data << 8); break;
  56. case 4: dma[channel].addr = (dma[channel].addr & 0x00ffff) + (data << 16); break;
  57. case 5: dma[channel].size = (dma[channel].size & 0xff00) + (data << 0); break;
  58. case 6: dma[channel].size = (dma[channel].size & 0x00ff) + (data << 8); break;
  59. }
  60. return cpu_mmio[addr & 0x7f]->mmio_write(addr, data);
  61. }
  62. switch(addr) {
  63. case 0x4800: sdd1_enable = data; break;
  64. case 0x4801: xfer_enable = data; break;
  65. case 0x4804: mmc[0] = (data & 7) << 20; break;
  66. case 0x4805: mmc[1] = (data & 7) << 20; break;
  67. case 0x4806: mmc[2] = (data & 7) << 20; break;
  68. case 0x4807: mmc[3] = (data & 7) << 20; break;
  69. }
  70. }
  71. //SDD1::read() is mapped to $[c0-ff]:[0000-ffff]
  72. //the design is meant to be as close to the hardware design as possible, thus this code
  73. //avoids adding S-DD1 hooks inside S-CPU::DMA emulation.
  74. //
  75. //the real S-DD1 cannot see $420b (DMA enable) writes, as they are not placed on the bus.
  76. //however, $43x0-$43xf writes (DMAx channel settings) most likely do appear on the bus.
  77. //the S-DD1 also requires fixed addresses for transfers, which wouldn't be necessary if
  78. //it could see $420b writes (eg it would know when the transfer should begin.)
  79. //
  80. //the hardware needs a way to distinguish program code after $4801 writes from DMA
  81. //decompression that follows soon after.
  82. //
  83. //the only plausible design for hardware would be for the S-DD1 to spy on DMAx settings,
  84. //and begin spooling decompression on writes to $4801 that activate a channel. after that,
  85. //it feeds decompressed data only when the ROM read address matches the DMA channel address.
  86. //
  87. //the actual S-DD1 transfer can occur on any channel, but it is most likely limited to
  88. //one transfer per $420b write (for spooling purposes). however, this is not known for certain.
  89. uint8 SDD1::read(unsigned addr) {
  90. if(sdd1_enable & xfer_enable) {
  91. //at least one channel has S-DD1 decompression enabled ...
  92. for(unsigned i = 0; i < 8; i++) {
  93. if(sdd1_enable & xfer_enable & (1 << i)) {
  94. //S-DD1 always uses fixed transfer mode, so address will not change during transfer
  95. if(addr == dma[i].addr) {
  96. if(!buffer.ready) {
  97. //first byte read for channel performs full decompression.
  98. //this really should stream byte-by-byte, but it's not necessary since the size is known
  99. buffer.offset = 0;
  100. buffer.size = dma[i].size ? dma[i].size : 65536;
  101. //sdd1emu calls this function; it needs to access uncompressed data;
  102. //so temporarily disable decompression mode for decompress() call.
  103. uint8 temp = sdd1_enable;
  104. sdd1_enable = false;
  105. sdd1emu.decompress(addr, buffer.size, buffer.data);
  106. sdd1_enable = temp;
  107. buffer.ready = true;
  108. }
  109. //fetch a decompressed byte; once buffer is depleted, disable channel and invalidate buffer
  110. uint8 data = buffer.data[(uint16)buffer.offset++];
  111. if(buffer.offset >= buffer.size) {
  112. buffer.ready = false;
  113. xfer_enable &= ~(1 << i);
  114. }
  115. return data;
  116. } //address matched
  117. } //channel enabled
  118. } //channel loop
  119. } //S-DD1 decompressor enabled
  120. //S-DD1 decompression mode inactive; return ROM data
  121. return memory::cartrom.read(mmc[(addr >> 20) & 3] + (addr & 0x0fffff));
  122. }
  123. void SDD1::write(unsigned addr, uint8 data) {
  124. }
  125. SDD1::SDD1() {
  126. buffer.data = new uint8[65536];
  127. }
  128. SDD1::~SDD1() {
  129. delete[] buffer.data;
  130. }