Advertisement
LuigiBlood

pi/controller.c (64DD 04/26)

Apr 26th, 2015
326
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.13 KB | None | 0 0
  1. //
  2. // pi/controller.c: Parallel interface controller.
  3. //
  4. // CEN64: Cycle-Accurate Nintendo 64 Simulator.
  5. // Copyright (C) 2014, Tyler J. Stachecki.
  6. //
  7. // This file is subject to the terms and conditions defined in
  8. // 'LICENSE', which is part of this source code package.
  9. //
  10.  
  11. #include "common.h"
  12. #include "bus/address.h"
  13. #include "bus/controller.h"
  14. #include "dd/controller.h"
  15. #include "pi/controller.h"
  16. #include "ri/controller.h"
  17. #include "vr4300/interface.h"
  18. #include <assert.h>
  19.  
  20. #ifdef DEBUG_MMIO_REGISTER_ACCESS
  21. const char *pi_register_mnemonics[NUM_PI_REGISTERS] = {
  22. #define X(reg) #reg,
  23. #include "pi/registers.md"
  24. #undef X
  25. };
  26. #endif
  27.  
  28. static int pi_dma_read(struct pi_controller *pi);
  29. static int pi_dma_write(struct pi_controller *pi);
  30.  
  31. // Copies data from the the PI into RDRAM.
  32. static int pi_dma_read(struct pi_controller *pi) {
  33.   uint32_t dest = pi->regs[PI_CART_ADDR_REG] & 0xFFFFFFF;
  34.   uint32_t source = pi->regs[PI_DRAM_ADDR_REG] & 0x7FFFFF;
  35.   uint32_t length = (pi->regs[PI_RD_LEN_REG] & 0xFFFFFF) + 1;
  36.  
  37.   if (pi->regs[PI_DRAM_ADDR_REG] == 0xFFFFFFFF) {
  38.     pi->regs[PI_STATUS_REG] &= ~0x1;
  39.     pi->regs[PI_STATUS_REG] |= 0x8;
  40.  
  41.     signal_rcp_interrupt(pi->bus->vr4300, MI_INTR_PI);
  42.     return 0;
  43.   }
  44.  
  45.   if (length & 7)
  46.     length = (length + 7) & ~7;
  47.  
  48.   if (pi->bus->dd->rom && ((dest & 0x05000000) == 0x05000000)) {
  49.     unsigned i;
  50.  
  51.     source &= ~0xC; // Word-aligned.
  52.     dest &= ~0xC; // Word-aligned.
  53.  
  54.     for (i = 0; i < length / 4; i++) {
  55.       uint32_t word;
  56.  
  57.       bus_read_word(pi, source + (i * 4), &word);
  58.       bus_write_word(pi, dest + (i * 4), word, ~0U);
  59.     }
  60.   }
  61.  
  62.   pi->regs[PI_DRAM_ADDR_REG] += length;
  63.   pi->regs[PI_CART_ADDR_REG] += length;
  64.   pi->regs[PI_STATUS_REG] &= ~0x1;
  65.   pi->regs[PI_STATUS_REG] |= 0x8;
  66.  
  67.   if ((dest & 0x05FFFFFF) == 0x05000000 || (dest & 0x05FFFFFF) == 0x05000400)
  68.     dd_update_bm(pi->bus->dd);
  69.  
  70.   signal_rcp_interrupt(pi->bus->vr4300, MI_INTR_PI);
  71.   return 0;
  72. }
  73.  
  74. // Copies data from the the PI into RDRAM.
  75. static int pi_dma_write(struct pi_controller *pi) {
  76.   uint32_t dest = pi->regs[PI_DRAM_ADDR_REG] & 0x7FFFFF;
  77.   uint32_t source = pi->regs[PI_CART_ADDR_REG] & 0xFFFFFFF;
  78.   uint32_t length = (pi->regs[PI_WR_LEN_REG] & 0xFFFFFF) + 1;
  79.  
  80.   if (pi->regs[PI_DRAM_ADDR_REG] == 0xFFFFFFFF) {
  81.     pi->regs[PI_STATUS_REG] &= ~0x1;
  82.     pi->regs[PI_STATUS_REG] |= 0x8;
  83.  
  84.     signal_rcp_interrupt(pi->bus->vr4300, MI_INTR_PI);
  85.     return 0;
  86.   }
  87.  
  88.   if (length & 7)
  89.     length = (length + 7) & ~7;
  90.  
  91.   if (pi->bus->dd->ipl_rom && (source & 0x06000000) == 0x06000000) {
  92.     source &= 0x003FFFFF;
  93.  
  94.     if (source + length > 0x003FFFFF)
  95.       length = 0x003FFFFF - source;
  96.  
  97.     memcpy(pi->bus->ri->ram + dest, pi->bus->dd->ipl_rom + source, length);
  98.   }
  99.  
  100.   else if (pi->bus->dd->rom && ((source & 0x05000000) == 0x05000000)) {
  101.     unsigned i;
  102.  
  103.     source &= ~0xC; // Word-aligned.
  104.     dest &= ~0xC; // Word-aligned.
  105.  
  106.     for (i = 0; i < length / 4; i++) {
  107.       uint32_t word;
  108.  
  109.       bus_read_word(pi, source + (i * 4), &word);
  110.       bus_write_word(pi, dest + (i * 4), word, ~0U);
  111.     }
  112.   }
  113.  
  114.   else if ((source & 0x08000000) == 0x08000000) {
  115.  
  116.   }
  117.  
  118.   else if (pi->rom) {
  119.     if (source + length > pi->rom_size) {
  120.       length = pi->rom_size - source;
  121.       //assert(0);
  122.     }
  123.  
  124.     // TODO: Very hacky.
  125.     if (source < pi->rom_size)
  126.       memcpy(pi->bus->ri->ram + dest, pi->rom + source, length);
  127.   }
  128.  
  129.   pi->regs[PI_DRAM_ADDR_REG] += length;
  130.   pi->regs[PI_CART_ADDR_REG] += length;
  131.   pi->regs[PI_STATUS_REG] &= ~0x1;
  132.   pi->regs[PI_STATUS_REG] |= 0x8;
  133.  
  134.   if ((source & 0x05FFFFFF) == 0x05000000 || (source & 0x05FFFFFF) == 0x05000400)
  135.     dd_update_bm(pi->bus->dd);
  136.  
  137.   signal_rcp_interrupt(pi->bus->vr4300, MI_INTR_PI);
  138.   return 0;
  139. }
  140.  
  141. // Initializes the PI.
  142. int pi_init(struct pi_controller *pi, struct bus_controller *bus,
  143.   const uint8_t *rom, size_t rom_size) {
  144.   pi->bus = bus;
  145.   pi->rom = rom;
  146.   pi->rom_size = rom_size;
  147.  
  148.   return 0;
  149. }
  150.  
  151. // Reads a word from cartridge ROM.
  152. int read_cart_rom(void *opaque, uint32_t address, uint32_t *word) {
  153.   struct pi_controller *pi = (struct pi_controller *) opaque;
  154.   unsigned offset = (address - ROM_CART_BASE_ADDRESS) & ~0x3;
  155.  
  156.   // TODO: Need to figure out correct behaviour.
  157.   // Should this even happen to begin with?
  158.   if (offset > pi->rom_size) {
  159.     *word = 0;
  160.     return 0;
  161.   }
  162.  
  163.   memcpy(word, pi->rom + offset, sizeof(*word));
  164.   *word = byteswap_32(*word);
  165.   return 0;
  166. }
  167.  
  168. // Reads a word from the PI MMIO register space.
  169. int read_pi_regs(void *opaque, uint32_t address, uint32_t *word) {
  170.   struct pi_controller *pi = (struct pi_controller *) opaque;
  171.   unsigned offset = address - PI_REGS_BASE_ADDRESS;
  172.   enum pi_register reg = (offset >> 2);
  173.  
  174.   // TODO/FIXME: Hacky...
  175.   *word = reg != PI_STATUS_REG
  176.     ? pi->regs[reg]
  177.     : 0x00000000U;
  178.  
  179.   debug_mmio_read(pi, pi_register_mnemonics[reg], *word);
  180.   return 0;
  181. }
  182.  
  183. // Writes a word to cartridge ROM.
  184. int write_cart_rom(void *opaque, uint32_t address, uint32_t word, uint32_t dqm) {
  185.   //assert(0 && "Attempt to write to cart ROM.");
  186.   return 0;
  187. }
  188.  
  189. // Writes a word to the PI MMIO register space.
  190. int write_pi_regs(void *opaque, uint32_t address, uint32_t word, uint32_t dqm) {
  191.   struct pi_controller *pi = (struct pi_controller *) opaque;
  192.   unsigned offset = address - PI_REGS_BASE_ADDRESS;
  193.   enum pi_register reg = (offset >> 2);
  194.  
  195.   debug_mmio_write(pi, pi_register_mnemonics[reg], word, dqm);
  196.  
  197.   if (reg == PI_STATUS_REG) {
  198.     pi->regs[reg] &= ~dqm;
  199.     pi->regs[reg] |= word;
  200.  
  201.     if (word & 0x1)
  202.       pi->regs[reg] = 0;
  203.  
  204.     if (word & 0x2) {
  205.       clear_rcp_interrupt(pi->bus->vr4300, MI_INTR_PI);
  206.       pi->regs[reg] &= ~0x8;
  207.     }
  208.   }
  209.  
  210.   else {
  211.     pi->regs[reg] &= ~dqm;
  212.     pi->regs[reg] |= word;
  213.  
  214.     if (reg == PI_CART_ADDR_REG)
  215.     {
  216.       //64DD
  217.       if (word == 0x05000000)     //C2
  218.         dd_clear_c2s(pi->bus->dd);
  219.       if (word == 0x05000400)     //Sector
  220.         dd_clear_ds(pi->bus->dd);
  221.     }
  222.  
  223.     if (reg == PI_WR_LEN_REG)
  224.       return pi_dma_write(pi);
  225.  
  226.     else if (reg == PI_RD_LEN_REG)
  227.       return pi_dma_read(pi);
  228.   }
  229.  
  230.   return 0;
  231. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement