Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //
- // pi/controller.c: Parallel interface controller.
- //
- // CEN64: Cycle-Accurate Nintendo 64 Simulator.
- // Copyright (C) 2014, Tyler J. Stachecki.
- //
- // This file is subject to the terms and conditions defined in
- // 'LICENSE', which is part of this source code package.
- //
- #include "common.h"
- #include "bus/address.h"
- #include "bus/controller.h"
- #include "dd/controller.h"
- #include "pi/controller.h"
- #include "ri/controller.h"
- #include "vr4300/interface.h"
- #include <assert.h>
- #ifdef DEBUG_MMIO_REGISTER_ACCESS
- const char *pi_register_mnemonics[NUM_PI_REGISTERS] = {
- #define X(reg) #reg,
- #include "pi/registers.md"
- #undef X
- };
- #endif
- static int pi_dma_read(struct pi_controller *pi);
- static int pi_dma_write(struct pi_controller *pi);
- // Copies data from the the PI into RDRAM.
- static int pi_dma_read(struct pi_controller *pi) {
- uint32_t dest = pi->regs[PI_CART_ADDR_REG] & 0xFFFFFFF;
- uint32_t source = pi->regs[PI_DRAM_ADDR_REG] & 0x7FFFFF;
- uint32_t length = (pi->regs[PI_RD_LEN_REG] & 0xFFFFFF) + 1;
- if (pi->regs[PI_DRAM_ADDR_REG] == 0xFFFFFFFF) {
- pi->regs[PI_STATUS_REG] &= ~0x1;
- pi->regs[PI_STATUS_REG] |= 0x8;
- signal_rcp_interrupt(pi->bus->vr4300, MI_INTR_PI);
- return 0;
- }
- if (length & 7)
- length = (length + 7) & ~7;
- if (pi->bus->dd->rom && ((dest & 0x05000000) == 0x05000000)) {
- unsigned i;
- source &= ~0xC; // Word-aligned.
- dest &= ~0xC; // Word-aligned.
- for (i = 0; i < length / 4; i++) {
- uint32_t word;
- bus_read_word(pi, source + (i * 4), &word);
- bus_write_word(pi, dest + (i * 4), word, ~0U);
- }
- }
- pi->regs[PI_DRAM_ADDR_REG] += length;
- pi->regs[PI_CART_ADDR_REG] += length;
- pi->regs[PI_STATUS_REG] &= ~0x1;
- pi->regs[PI_STATUS_REG] |= 0x8;
- if ((dest & 0x05FFFFFF) == 0x05000000 || (dest & 0x05FFFFFF) == 0x05000400)
- dd_update_bm(pi->bus->dd);
- signal_rcp_interrupt(pi->bus->vr4300, MI_INTR_PI);
- return 0;
- }
- // Copies data from the the PI into RDRAM.
- static int pi_dma_write(struct pi_controller *pi) {
- uint32_t dest = pi->regs[PI_DRAM_ADDR_REG] & 0x7FFFFF;
- uint32_t source = pi->regs[PI_CART_ADDR_REG] & 0xFFFFFFF;
- uint32_t length = (pi->regs[PI_WR_LEN_REG] & 0xFFFFFF) + 1;
- if (pi->regs[PI_DRAM_ADDR_REG] == 0xFFFFFFFF) {
- pi->regs[PI_STATUS_REG] &= ~0x1;
- pi->regs[PI_STATUS_REG] |= 0x8;
- signal_rcp_interrupt(pi->bus->vr4300, MI_INTR_PI);
- return 0;
- }
- if (length & 7)
- length = (length + 7) & ~7;
- if (pi->bus->dd->ipl_rom && (source & 0x06000000) == 0x06000000) {
- source &= 0x003FFFFF;
- if (source + length > 0x003FFFFF)
- length = 0x003FFFFF - source;
- memcpy(pi->bus->ri->ram + dest, pi->bus->dd->ipl_rom + source, length);
- }
- else if (pi->bus->dd->rom && ((source & 0x05000000) == 0x05000000)) {
- unsigned i;
- source &= ~0xC; // Word-aligned.
- dest &= ~0xC; // Word-aligned.
- for (i = 0; i < length / 4; i++) {
- uint32_t word;
- bus_read_word(pi, source + (i * 4), &word);
- bus_write_word(pi, dest + (i * 4), word, ~0U);
- }
- }
- else if ((source & 0x08000000) == 0x08000000) {
- }
- else if (pi->rom) {
- if (source + length > pi->rom_size) {
- length = pi->rom_size - source;
- //assert(0);
- }
- // TODO: Very hacky.
- if (source < pi->rom_size)
- memcpy(pi->bus->ri->ram + dest, pi->rom + source, length);
- }
- pi->regs[PI_DRAM_ADDR_REG] += length;
- pi->regs[PI_CART_ADDR_REG] += length;
- pi->regs[PI_STATUS_REG] &= ~0x1;
- pi->regs[PI_STATUS_REG] |= 0x8;
- if ((source & 0x05FFFFFF) == 0x05000000 || (source & 0x05FFFFFF) == 0x05000400)
- dd_update_bm(pi->bus->dd);
- signal_rcp_interrupt(pi->bus->vr4300, MI_INTR_PI);
- return 0;
- }
- // Initializes the PI.
- int pi_init(struct pi_controller *pi, struct bus_controller *bus,
- const uint8_t *rom, size_t rom_size) {
- pi->bus = bus;
- pi->rom = rom;
- pi->rom_size = rom_size;
- return 0;
- }
- // Reads a word from cartridge ROM.
- int read_cart_rom(void *opaque, uint32_t address, uint32_t *word) {
- struct pi_controller *pi = (struct pi_controller *) opaque;
- unsigned offset = (address - ROM_CART_BASE_ADDRESS) & ~0x3;
- // TODO: Need to figure out correct behaviour.
- // Should this even happen to begin with?
- if (offset > pi->rom_size) {
- *word = 0;
- return 0;
- }
- memcpy(word, pi->rom + offset, sizeof(*word));
- *word = byteswap_32(*word);
- return 0;
- }
- // Reads a word from the PI MMIO register space.
- int read_pi_regs(void *opaque, uint32_t address, uint32_t *word) {
- struct pi_controller *pi = (struct pi_controller *) opaque;
- unsigned offset = address - PI_REGS_BASE_ADDRESS;
- enum pi_register reg = (offset >> 2);
- // TODO/FIXME: Hacky...
- *word = reg != PI_STATUS_REG
- ? pi->regs[reg]
- : 0x00000000U;
- debug_mmio_read(pi, pi_register_mnemonics[reg], *word);
- return 0;
- }
- // Writes a word to cartridge ROM.
- int write_cart_rom(void *opaque, uint32_t address, uint32_t word, uint32_t dqm) {
- //assert(0 && "Attempt to write to cart ROM.");
- return 0;
- }
- // Writes a word to the PI MMIO register space.
- int write_pi_regs(void *opaque, uint32_t address, uint32_t word, uint32_t dqm) {
- struct pi_controller *pi = (struct pi_controller *) opaque;
- unsigned offset = address - PI_REGS_BASE_ADDRESS;
- enum pi_register reg = (offset >> 2);
- debug_mmio_write(pi, pi_register_mnemonics[reg], word, dqm);
- if (reg == PI_STATUS_REG) {
- pi->regs[reg] &= ~dqm;
- pi->regs[reg] |= word;
- if (word & 0x1)
- pi->regs[reg] = 0;
- if (word & 0x2) {
- clear_rcp_interrupt(pi->bus->vr4300, MI_INTR_PI);
- pi->regs[reg] &= ~0x8;
- }
- }
- else {
- pi->regs[reg] &= ~dqm;
- pi->regs[reg] |= word;
- if (reg == PI_CART_ADDR_REG)
- {
- //64DD
- if (word == 0x05000000) //C2
- dd_clear_c2s(pi->bus->dd);
- if (word == 0x05000400) //Sector
- dd_clear_ds(pi->bus->dd);
- }
- if (reg == PI_WR_LEN_REG)
- return pi_dma_write(pi);
- else if (reg == PI_RD_LEN_REG)
- return pi_dma_read(pi);
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement