cen64/si/pak_transfer.c
Tyler J. Stachecki 3288229a50 Start fixing MSVC builds.
Conflicts:
	rdp/n64video.c
2016-06-26 17:19:17 -04:00

109 lines
3 KiB
C

//
// si/pak_transfer.c: Controller pak routines
//
// CEN64: Cycle-Accurate Nintendo 64 Emulator.
// Copyright (C) 2016, Mike Ryan.
//
// This file is subject to the terms and conditions defined in
// 'LICENSE', which is part of this source code package.
//
#include "pak.h"
#include "gb.h"
static void gameboy_read(struct controller *controller, uint16_t address,
uint8_t *buffer);
static void gameboy_write(struct controller *controller, uint16_t address,
uint8_t *buffer);
void transfer_pak_read(struct controller *controller,
uint8_t *send_buf, uint8_t send_bytes,
uint8_t *recv_buf, uint8_t recv_bytes) {
uint16_t address = send_buf[1] << 8 | send_buf[2];
address &= ~0x1F; // lower 5 bits are address CRC
// printf("read from %04x\n", address);
// get enable/disable state
if (address == 0x8000)
memset(recv_buf, controller->pak_enabled ? 0x84 : 0x00, 0x20);
// get insertion status and access mode
else if (address == 0xB000) {
if (controller->pak_enabled) {
// cart inserted, return mode and mode changed
if (controller->tpak_rom.ptr != NULL) {
memset(recv_buf, controller->tpak_mode == 1 ? 0x89 : 0x80, 0x20);
recv_buf[0] |= controller->tpak_mode_changed ? 0x4 : 0;
}
// cart not inserted
else
memset(recv_buf, 0x40, 0x20);
controller->tpak_mode_changed = 0;
}
}
// read from GB cart
else if (address >= 0xC000) {
if (controller->pak_enabled) {
uint16_t gb_addr = address - 0xC000
+ (controller->tpak_bank & 3) * 0x4000;
gameboy_read(controller, gb_addr, recv_buf);
}
}
}
void transfer_pak_write(struct controller *controller,
uint8_t *send_buf, uint8_t send_bytes,
uint8_t *recv_buf, uint8_t recv_bytes) {
uint16_t address = send_buf[1] << 8 | send_buf[2];
address &= ~0x1F; // lower 5 bits are address CRC
// printf("write to %04x\n", address);
// set bank
if (address == 0xA000) {
if (controller->pak_enabled)
controller->tpak_bank = send_buf[3];
}
// set access mode
else if (address == 0xB000) {
if (controller->pak_enabled) {
controller->tpak_mode = send_buf[3] & 1;
controller->tpak_mode_changed = 1;
}
}
// write to GB cart
else if (address >= 0xC000) {
uint16_t gb_addr = address - 0xC000
+ (controller->tpak_bank & 3) * 0x4000;
gameboy_write(controller, gb_addr, send_buf + 3);
}
}
// read 0x20 bytes from Game Boy cart at address
void gameboy_read(struct controller *controller, uint16_t address,
uint8_t *buffer) {
for(int i=0;i<0x20;i++)
buffer[i] = gb_read(controller, address+i);
// printf("read: %04X: ", address);
// for(int i=0;i<32;i++) {
// if(i==16) printf("\n ");
// printf("%02X ", buffer[i]);
// }
// printf("\n");
}
// write 0x20 bytes from buffer to Game Boy cart at address
void gameboy_write(struct controller *controller, uint16_t address,
uint8_t *buffer) {
for(int i=0;i<0x20;i++)
gb_write(controller, address+i, buffer[i]);
// printf("write: %04X:%02X\n", address, buffer[0]);
}