mirror of
https://github.com/n64dev/cen64.git
synced 2024-06-15 18:48:02 -04:00
transfer pak: implement transfer pak read and write
This code will not boot Pokemon Stadium 1 or 2 after extensive debugging. The code lacks Game Boy MBC support (though this is not the reason the games refuse to boot).
This commit is contained in:
parent
799b2af628
commit
e83da838f7
|
@ -339,6 +339,7 @@ set(SI_SOURCES
|
|||
${PROJECT_SOURCE_DIR}/si/cic.c
|
||||
${PROJECT_SOURCE_DIR}/si/controller.c
|
||||
${PROJECT_SOURCE_DIR}/si/pak.c
|
||||
${PROJECT_SOURCE_DIR}/si/pak_transfer.c
|
||||
)
|
||||
|
||||
set(VI_SOURCES
|
||||
|
|
18
si/pak.c
18
si/pak.c
|
@ -9,6 +9,7 @@
|
|||
//
|
||||
|
||||
#include "pak.h"
|
||||
#include "pak_transfer.h"
|
||||
|
||||
static uint8_t controller_pak_crc(uint8_t *data);
|
||||
|
||||
|
@ -27,12 +28,13 @@ int controller_pak_read(struct controller *controller,
|
|||
assert(0 && "invalid mempak address");
|
||||
}
|
||||
|
||||
else if (controller->pak == PAK_TRANSFER)
|
||||
transfer_pak_read(controller, send_buf, send_bytes, recv_buf, recv_bytes);
|
||||
|
||||
else {
|
||||
uint8_t peripheral = 0x00;
|
||||
if (controller->pak == PAK_RUMBLE)
|
||||
peripheral = 0x80;
|
||||
else if (controller->pak == PAK_TRANSFER)
|
||||
peripheral = 0x84;
|
||||
memset(recv_buf, peripheral, 0x20);
|
||||
}
|
||||
|
||||
|
@ -49,8 +51,13 @@ int controller_pak_write(struct controller *controller,
|
|||
address &= ~0b11111; // lower 5 bits are a checksum
|
||||
// printf("write to %04x\n", address);
|
||||
|
||||
if (address == 0x8000)
|
||||
; // initializing device, do nothing
|
||||
if (address == 0x8000) {
|
||||
// maybe only for transfer pak, unclear
|
||||
if (send_buf[3] == 0xfe)
|
||||
controller->pak_enabled = 0;
|
||||
else if (send_buf[3] == 0x84)
|
||||
controller->pak_enabled = 1;
|
||||
}
|
||||
|
||||
else if (controller->pak == PAK_MEM) {
|
||||
if (address <= MEMPAK_SIZE - 0x20)
|
||||
|
@ -70,6 +77,9 @@ int controller_pak_write(struct controller *controller,
|
|||
; // printf("Unknown rumble address\n");
|
||||
}
|
||||
|
||||
else if (controller->pak == PAK_TRANSFER)
|
||||
transfer_pak_write(controller, send_buf, send_bytes, recv_buf, recv_bytes);
|
||||
|
||||
recv_buf[0] = controller_pak_crc(send_buf+3);
|
||||
|
||||
return 0;
|
||||
|
|
99
si/pak_transfer.c
Normal file
99
si/pak_transfer.c
Normal file
|
@ -0,0 +1,99 @@
|
|||
//
|
||||
// si/pak.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"
|
||||
|
||||
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 &= ~0b11111; // 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 ? 0b100 : 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 &= ~0b11111; // 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);
|
||||
}
|
||||
}
|
||||
|
||||
// read 0x20 bytes from Game Boy cart at address
|
||||
void gameboy_read(struct controller *controller, uint16_t address,
|
||||
uint8_t *buffer) {
|
||||
// TODO handle mappers
|
||||
if (address < 0x8000)
|
||||
memcpy(buffer, controller->tpak_rom.ptr + address, 0x20);
|
||||
}
|
||||
|
||||
// write 0x20 bytes from buffer to Game Boy cart at address
|
||||
void gameboy_write(struct controller *controller, uint16_t address,
|
||||
uint8_t *buffer) {
|
||||
// TODO
|
||||
}
|
22
si/pak_transfer.h
Normal file
22
si/pak_transfer.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
//
|
||||
// si/pak_transfer.h: Transfer pak handling
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
#ifndef __si_pak_transfer_h__
|
||||
#define __si_pak_transfer_h__
|
||||
#include "common.h"
|
||||
|
||||
void transfer_pak_read(struct controller *controller,
|
||||
uint8_t *send_buf, uint8_t send_bytes,
|
||||
uint8_t *recv_buf, uint8_t recv_bytes);
|
||||
void transfer_pak_write(struct controller *controller,
|
||||
uint8_t *send_buf, uint8_t send_bytes,
|
||||
uint8_t *recv_buf, uint8_t recv_bytes);
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue