Advertisement
LuigiBlood

pi_controller.c (64DD)

Apr 26th, 2015
366
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.25 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.   pi->regs[PI_DRAM_ADDR_REG] += length;
  49.   pi->regs[PI_CART_ADDR_REG] += length;
  50.   pi->regs[PI_STATUS_REG] &= ~0x1;
  51.   pi->regs[PI_STATUS_REG] |= 0x8;
  52.  
  53.   signal_rcp_interrupt(pi->bus->vr4300, MI_INTR_PI);
  54.   return 0;
  55. }
  56.  
  57. // Copies data from the the PI into RDRAM.
  58. static int pi_dma_write(struct pi_controller *pi) {
  59.   uint32_t dest = pi->regs[PI_DRAM_ADDR_REG] & 0x7FFFFF;
  60.   uint32_t source = pi->regs[PI_CART_ADDR_REG] & 0xFFFFFFF;
  61.   uint32_t length = (pi->regs[PI_WR_LEN_REG] & 0xFFFFFF) + 1;
  62.  
  63.   if (pi->regs[PI_DRAM_ADDR_REG] == 0xFFFFFFFF) {
  64.     pi->regs[PI_STATUS_REG] &= ~0x1;
  65.     pi->regs[PI_STATUS_REG] |= 0x8;
  66.  
  67.     signal_rcp_interrupt(pi->bus->vr4300, MI_INTR_PI);
  68.     return 0;
  69.   }
  70.  
  71.   if (length & 7)
  72.     length = (length + 7) & ~7;
  73.  
  74.   if (pi->bus->dd->ipl_rom && (source & 0x06000000) == 0x06000000) {
  75.     source &= 0x003FFFFF;
  76.  
  77.     if (source + length > 0x003FFFFF)
  78.       length = 0x003FFFFF - source;
  79.  
  80.     memcpy(pi->bus->ri->ram + dest, pi->bus->dd->ipl_rom + source, length);
  81.   }
  82.  
  83.   else if (pi->bus->dd->rom && ((source & 0x05000000) == 0x05000000)) {
  84.     unsigned i;
  85.  
  86.     for (i = 0; i < length / 4; i++) {
  87.       uint32_t word;
  88.  
  89.       bus_read_word(pi->bus, source + (i * 4), &word);
  90.       bus_write_word(pi->bus, dest + (i * 4), word, ~0U);
  91.     }
  92.   }
  93.  
  94.   else if ((source & 0x08000000) == 0x08000000) {
  95.  
  96.   }
  97.  
  98.   else if (pi->rom) {
  99.     if (source + length > pi->rom_size) {
  100.       length = pi->rom_size - source;
  101.       //assert(0);
  102.     }
  103.  
  104.     // TODO: Very hacky.
  105.     if (source < pi->rom_size)
  106.       memcpy(pi->bus->ri->ram + dest, pi->rom + source, length);
  107.   }
  108.  
  109.   pi->regs[PI_DRAM_ADDR_REG] += length;
  110.   pi->regs[PI_CART_ADDR_REG] += length;
  111.   pi->regs[PI_STATUS_REG] &= ~0x1;
  112.   pi->regs[PI_STATUS_REG] |= 0x8;
  113.  
  114.   signal_rcp_interrupt(pi->bus->vr4300, MI_INTR_PI);
  115.   return 0;
  116. }
  117.  
  118. // Initializes the PI.
  119. int pi_init(struct pi_controller *pi, struct bus_controller *bus,
  120.   const uint8_t *rom, size_t rom_size) {
  121.   pi->bus = bus;
  122.   pi->rom = rom;
  123.   pi->rom_size = rom_size;
  124.  
  125.   return 0;
  126. }
  127.  
  128. // Reads a word from cartridge ROM.
  129. int read_cart_rom(void *opaque, uint32_t address, uint32_t *word) {
  130.   struct pi_controller *pi = (struct pi_controller *) opaque;
  131.   unsigned offset = (address - ROM_CART_BASE_ADDRESS) & ~0x3;
  132.  
  133.   // TODO: Need to figure out correct behaviour.
  134.   // Should this even happen to begin with?
  135.   if (offset > pi->rom_size) {
  136.     *word = 0;
  137.     return 0;
  138.   }
  139.  
  140.   memcpy(word, pi->rom + offset, sizeof(*word));
  141.   *word = byteswap_32(*word);
  142.   return 0;
  143. }
  144.  
  145. // Reads a word from the PI MMIO register space.
  146. int read_pi_regs(void *opaque, uint32_t address, uint32_t *word) {
  147.   struct pi_controller *pi = (struct pi_controller *) opaque;
  148.   unsigned offset = address - PI_REGS_BASE_ADDRESS;
  149.   enum pi_register reg = (offset >> 2);
  150.  
  151.   // TODO/FIXME: Hacky...
  152.   *word = reg != PI_STATUS_REG
  153.     ? pi->regs[reg]
  154.     : 0x00000000U;
  155.  
  156.   debug_mmio_read(pi, pi_register_mnemonics[reg], *word);
  157.   return 0;
  158. }
  159.  
  160. // Writes a word to cartridge ROM.
  161. int write_cart_rom(void *opaque, uint32_t address, uint32_t word, uint32_t dqm) {
  162.   //assert(0 && "Attempt to write to cart ROM.");
  163.   return 0;
  164. }
  165.  
  166. // Writes a word to the PI MMIO register space.
  167. int write_pi_regs(void *opaque, uint32_t address, uint32_t word, uint32_t dqm) {
  168.   struct pi_controller *pi = (struct pi_controller *) opaque;
  169.   unsigned offset = address - PI_REGS_BASE_ADDRESS;
  170.   enum pi_register reg = (offset >> 2);
  171.  
  172.   debug_mmio_write(pi, pi_register_mnemonics[reg], word, dqm);
  173.  
  174.   if (reg == PI_STATUS_REG) {
  175.     pi->regs[reg] &= ~dqm;
  176.     pi->regs[reg] |= word;
  177.  
  178.     if (word & 0x1)
  179.       pi->regs[reg] = 0;
  180.  
  181.     if (word & 0x2) {
  182.       clear_rcp_interrupt(pi->bus->vr4300, MI_INTR_PI);
  183.       pi->regs[reg] &= ~0x8;
  184.     }
  185.   }
  186.  
  187.   else {
  188.     pi->regs[reg] &= ~dqm;
  189.     pi->regs[reg] |= word;
  190.  
  191.     if (reg == PI_WR_LEN_REG)
  192.       return pi_dma_write(pi);
  193.  
  194.     else if (reg == PI_RD_LEN_REG)
  195.       return pi_dma_read(pi);
  196.   }
  197.  
  198.   return 0;
  199. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement