SRAM support

This commit is contained in:
CrashOveride95
2021-01-11 00:46:56 -05:00
parent ba58de803a
commit 02e6466e5c
8 changed files with 233 additions and 11 deletions

View File

@@ -43,6 +43,20 @@ COMPILER ?= gcc
$(eval $(call validate-option,COMPILER,ido gcc)) $(eval $(call validate-option,COMPILER,ido gcc))
# SAVETYPE - selects the save type
# eep4k - uses EEPROM 4kbit
# eep16k - uses EEPROM 16kbit (There aren't any differences in syntax, but this is provided just in case)
# sram - uses SRAM 256Kbit
SAVETYPE ?= eep4k
$(eval $(call validate-option,SAVETYPE,eep4k eep16k sram))
ifeq ($(SAVETYPE),eep4k)
DEFINES += EEP=1 EEP4K=1
else ifeq ($(SAVETYPE),eep16k)
DEFINES += EEP=1 EEP16K=1
else ifeq ($(SAVETYPE),sram)
DEFINES += SRAM=1
endif
COMPRESS ?= yay0 COMPRESS ?= yay0
$(eval $(call validate-option,COMPRESS,yay0 gzip)) $(eval $(call validate-option,COMPRESS,yay0 gzip))
ifeq ($(COMPRESS),gzip) ifeq ($(COMPRESS),gzip)
@@ -804,8 +818,6 @@ $(ROM): $(ELF)
$(BUILD_DIR)/$(TARGET).objdump: $(ELF) $(BUILD_DIR)/$(TARGET).objdump: $(ELF)
$(OBJDUMP) -D $< > $@ $(OBJDUMP) -D $< > $@
.PHONY: all clean distclean default diff test load .PHONY: all clean distclean default diff test load
# with no prerequisites, .SECONDARY causes no intermediate target to be removed # with no prerequisites, .SECONDARY causes no intermediate target to be removed
.SECONDARY: .SECONDARY:

View File

@@ -5,6 +5,7 @@
- It has been edited to allow for the usage of the final "N64 OS" library, version ``2.0L`` - It has been edited to allow for the usage of the final "N64 OS" library, version ``2.0L``
- Shindou Rumble Pak code is on for all regions. - Shindou Rumble Pak code is on for all regions.
- Targeting the iQue Player is supported. - Targeting the iQue Player is supported.
- Saving to 32kbyte/256kbit SRAM is supported.
- It has been patched with someone2639's shiftable segments patch - It has been patched with someone2639's shiftable segments patch
- Getting HVQM FMV support to work with the game is in progress. - Getting HVQM FMV support to work with the game is in progress.
- Getting UNFLoader (flashcart USB library) to work with the game is in progress. - Getting UNFLoader (flashcart USB library) to work with the game is in progress.

View File

@@ -26,6 +26,9 @@
#include "usb/usb.h" #include "usb/usb.h"
#include "usb/debug.h" #include "usb/debug.h"
#endif #endif
#ifdef SRAM
#include "sram.h"
#endif
#include <prevent_bss_reordering.h> #include <prevent_bss_reordering.h>
// FIXME: I'm not sure all of these variables belong in this file, but I don't // FIXME: I'm not sure all of these variables belong in this file, but I don't
@@ -38,7 +41,12 @@ struct GfxPool *gGfxPool;
OSContStatus gControllerStatuses[4]; OSContStatus gControllerStatuses[4];
OSContPad gControllerPads[4]; OSContPad gControllerPads[4];
u8 gControllerBits; u8 gControllerBits;
#ifdef EEP
s8 gEepromProbe; s8 gEepromProbe;
#endif
#ifdef SRAM
s8 gSramProbe;
#endif
OSMesgQueue gGameVblankQueue; OSMesgQueue gGameVblankQueue;
OSMesgQueue D_80339CB8; OSMesgQueue D_80339CB8;
OSMesg D_80339CD0; OSMesg D_80339CD0;
@@ -555,9 +563,14 @@ void init_controllers(void) {
gControllers[0].controllerData = &gControllerPads[0]; gControllers[0].controllerData = &gControllerPads[0];
osContInit(&gSIEventMesgQueue, &gControllerBits, &gControllerStatuses[0]); osContInit(&gSIEventMesgQueue, &gControllerBits, &gControllerStatuses[0]);
#ifdef EEP
// strangely enough, the EEPROM probe for save data is done in this function. // strangely enough, the EEPROM probe for save data is done in this function.
// save pak detection? // save pak detection?
gEepromProbe = osEepromProbe(&gSIEventMesgQueue); gEepromProbe = osEepromProbe(&gSIEventMesgQueue);
#endif
#ifdef SRAM
gSramProbe = nuPiInitSram();
#endif
// loop over the 4 ports and link the controller structs to the appropriate // loop over the 4 ports and link the controller structs to the appropriate
// status and pad. Interestingly, although there are pointers to 3 controllers, // status and pad. Interestingly, although there are pointers to 3 controllers,

View File

@@ -41,7 +41,12 @@ extern Gfx *gDisplayListHead;
extern u8 *gGfxPoolEnd; extern u8 *gGfxPoolEnd;
extern struct GfxPool *gGfxPool; extern struct GfxPool *gGfxPool;
extern u8 gControllerBits; extern u8 gControllerBits;
#ifdef EEP
extern s8 gEepromProbe; extern s8 gEepromProbe;
#endif
#ifdef SRAM
extern s8 gSramProbe;
#endif
extern void (*gGoddardVblankCallback)(void); extern void (*gGoddardVblankCallback)(void);
extern struct Controller *gPlayer1Controller; extern struct Controller *gPlayer1Controller;

55
src/game/nupiinitsram.c Normal file
View File

@@ -0,0 +1,55 @@
/*======================================================================*/
/* NuSYS */
/* nupisraminit.c */
/* */
/* Copyright (C) 1997, NINTENDO Co,Ltd. */
/* */
/*----------------------------------------------------------------------*/
/* Ver 1.2 98/07/4 Created by Kensaku Ohki(SLANP) */
/*----------------------------------------------------------------------*/
/* $Id: nupiinitsram.c,v 1.2 1998/07/11 11:22:46 ohki Exp $ */
/*======================================================================*/
#include <ultra64.h>
#define SRAM_START_ADDR 0x08000000
#define SRAM_SIZE 0x8000
#define SRAM_LATENCY 0x5
#define SRAM_PULSE 0x0c
#define SRAM_PAGE_SIZE 0xd
#define SRAM_REL_DURATION 0x2
OSPiHandle* nuPiSramHandle;
static OSPiHandle SramHandle;
/*----------------------------------------------------------------------*/
/* nuPiSramInit - Initialization of handle for SRAM */
/* Initialize handle for SRAM */
/* IN: None */
/* RET: If detected, return 1, otherwise 0 */
/*----------------------------------------------------------------------*/
int nuPiInitSram()
{
if (SramHandle.baseAddress == PHYS_TO_K1(SRAM_START_ADDR))
return 0;
/* Fill basic information */
SramHandle.type = DEVICE_TYPE_SRAM;
SramHandle.baseAddress = PHYS_TO_K1(SRAM_START_ADDR);
/* Get Domain parameters */
SramHandle.latency = (u8)SRAM_LATENCY;
SramHandle.pulse = (u8)SRAM_PULSE;
SramHandle.pageSize = (u8)SRAM_PAGE_SIZE;
SramHandle.relDuration = (u8)SRAM_REL_DURATION;
SramHandle.domain = PI_DOMAIN2;
/* Fill speed and transferInfo to zero */
SramHandle.speed = 0;
bzero((void *)&(SramHandle.transferInfo),
sizeof(SramHandle.transferInfo));
/* Put the SramHandle onto PiTable*/
osEPiLinkHandle(&SramHandle);
nuPiSramHandle = &SramHandle;
return 1;
}

View File

@@ -0,0 +1,52 @@
/*======================================================================*/
/* NuSYS */
/* nupireadsram.c */
/* */
/* Copyright (C) 1997, NINTENDO Co,Ltd. */
/* */
/*----------------------------------------------------------------------*/
/* Ver 1.2 98/07/11 Created by Kensaku Ohki(SLANP) */
/*----------------------------------------------------------------------*/
/* $Id: nupireadwritesram.c,v 1.3 1999/06/09 02:33:22 ohki Exp $ */
/*======================================================================*/
#include <ultra64.h>
extern OSPiHandle* nuPiSramHandle;
/*----------------------------------------------------------------------*/
/* nuPiReadWriteSram - DMA transfers data to and from SRAM. */
/* The message queue is a local variable so it can be used */
/* between threads. */
/* IN: addr SRAM address. */
/* buf_ptr RDRAM address. */
/* size Transfer size. */
/* RET: None */
/*----------------------------------------------------------------------*/
int nuPiReadWriteSram(u32 addr, void* buf_ptr, u32 size, s32 flag)
{
OSIoMesg dmaIoMesgBuf;
OSMesgQueue dmaMesgQ;
OSMesg dmaMesgBuf;
/* Create the message queue. */
osCreateMesgQueue(&dmaMesgQ, &dmaMesgBuf, 1);
dmaIoMesgBuf.hdr.pri = OS_MESG_PRI_NORMAL;
dmaIoMesgBuf.hdr.retQueue = &dmaMesgQ;
dmaIoMesgBuf.dramAddr = buf_ptr;
dmaIoMesgBuf.devAddr = (u32)addr;
dmaIoMesgBuf.size = size;
if(flag == OS_READ){
/* Make CPU cache invalid */
osInvalDCache((void*)buf_ptr, (s32)size);
} else {
/* Write back */
osWritebackDCache((void*)buf_ptr, (s32)size);
}
osEPiStartDma(nuPiSramHandle, &dmaIoMesgBuf, flag);
/* Wait for the end */
(void)osRecvMesg(&dmaMesgQ, &dmaMesgBuf, OS_MESG_BLOCK);
return 0;
}

View File

@@ -11,6 +11,9 @@
#include "level_table.h" #include "level_table.h"
#include "course_table.h" #include "course_table.h"
#include "rumble_init.h" #include "rumble_init.h"
#ifdef SRAM
#include "sram.h"
#endif
#define MENU_DATA_MAGIC 0x4849 #define MENU_DATA_MAGIC 0x4849
#define SAVE_FILE_MAGIC 0x4441 #define SAVE_FILE_MAGIC 0x4441
@@ -43,13 +46,7 @@ s8 gLevelToCourseNumTable[] = {
STATIC_ASSERT(ARRAY_COUNT(gLevelToCourseNumTable) == LEVEL_COUNT - 1, STATIC_ASSERT(ARRAY_COUNT(gLevelToCourseNumTable) == LEVEL_COUNT - 1,
"change this array if you are adding levels"); "change this array if you are adding levels");
#ifdef EEP
// This was probably used to set progress to 100% for debugging, but
// it was removed from the release ROM.
static void stub_save_file_1(void) {
UNUSED s32 pad;
}
/** /**
* Read from EEPROM to a given address. * Read from EEPROM to a given address.
* The EEPROM address is computed using the offset of the destination address from gSaveBuffer. * The EEPROM address is computed using the offset of the destination address from gSaveBuffer.
@@ -105,6 +102,65 @@ static s32 write_eeprom_data(void *buffer, s32 size) {
return status; return status;
} }
#endif
#ifdef SRAM
/**
* Read from SRAM to a given address.
* The SRAM address is computed using the offset of the destination address from gSaveBuffer.
* Try at most 4 times, and return 0 on success. On failure, return the status returned from
* nuPiReadSram. It also returns 0 if SRAM isn't loaded correctly in the system.
*/
static s32 read_eeprom_data(void *buffer, s32 size) {
s32 status = 0;
if (gSramProbe != 0) {
s32 triesLeft = 4;
u32 offset = (u32)((u8 *) buffer - (u8 *) &gSaveBuffer) / 8;
do {
#if ENABLE_RUMBLE
block_until_rumble_pak_free();
#endif
triesLeft--;
status = nuPiReadSram(offset, buffer, size);
#if ENABLE_RUMBLE
release_rumble_pak_control();
#endif
} while (triesLeft > 0 && status != 0);
}
return status;
}
/**
* Write data to SRAM.
* The SRAM address is computed using the offset of the source address from gSaveBuffer.
* Try at most 4 times, and return 0 on success. On failure, return the status returned from
* nuPiWriteSram. Unlike read_eeprom_data, return 1 if SRAM isn't loaded.
*/
static s32 write_eeprom_data(void *buffer, s32 size) {
s32 status = 1;
if (gSramProbe != 0) {
s32 triesLeft = 4;
u32 offset = (u32)((u8 *) buffer - (u8 *) &gSaveBuffer) >> 3;
do {
#if ENABLE_RUMBLE
block_until_rumble_pak_free();
#endif
triesLeft--;
status = nuPiWriteSram(offset, buffer, size);
#if ENABLE_RUMBLE
release_rumble_pak_control();
#endif
} while (triesLeft > 0 && status != 0);
}
return status;
}
#endif
/** /**
* Sum the bytes in data to data + size - 2. The last two bytes are ignored * Sum the bytes in data to data + size - 2. The last two bytes are ignored
@@ -329,8 +385,6 @@ void save_file_load_all(void) {
break; break;
} }
} }
stub_save_file_1();
} }
/** /**

30
src/game/sram.h Normal file
View File

@@ -0,0 +1,30 @@
#ifndef SRAM_H
#define SRAM_H
/*----------------------------------------------------------------------*/
/* nuPiSramInit - Initialization of handle for SRAM */
/*----------------------------------------------------------------------*/
extern int nuPiInitSram();
/*----------------------------------------------------------------------*/
/* nuPiReadWriteSram - DMA transfers data to and from SRAM. */
/* IN: addr SRAM address. */
/* buf_ptr RDRAM address. */
/* size Transfer size. */
/* RET: None */
/*----------------------------------------------------------------------*/
extern int nuPiReadWriteSram(u32 addr, void* buf_ptr, u32 size, s32 flag);
/*----------------------------------------------------------------------*/
/* nuPiReadSram - Read from SRAM */
/*----------------------------------------------------------------------*/
#define nuPiReadSram(addr, buf_ptr, size) \
nuPiReadWriteSram(addr, buf_ptr, size, OS_READ)
/*----------------------------------------------------------------------*/
/* nuPiWriteSram - Write to SRAM */
/*----------------------------------------------------------------------*/
#define nuPiWriteSram(addr, buf_ptr, size) \
nuPiReadWriteSram(addr, buf_ptr, size, OS_WRITE)
#endif // SRAM_H