Have basic SNES cart detection and dumping working. Dumping mario paint
works on both inl6 and original kazzo just fine. Dumping v3 prototype has a few byte corruptions on inl6, but is fine on original kazzo. The same bytes often fail, but not consistently. Tinkered with adding delay, but that didn't help. Also have issue with adapter not dumping properly. Prob bug with HIGH ADDR on that board need to sort out still. Going to focus on erasing and dumping next then come back to some of these issues.
This commit is contained in:
parent
dfeaf960ef
commit
4b3c822a24
|
|
@ -32,6 +32,15 @@ uint8_t dump_buff( buffer *buff ) {
|
|||
buff->last_idx, ~FALSE );
|
||||
break;
|
||||
case SNESROM:
|
||||
addrH |= 0x80; //$8000 LOROM space
|
||||
//need to split page_num
|
||||
//A14-8 page_num[7-0]
|
||||
//A15 high (LOROM)
|
||||
//A23-16 page_num[14-8]
|
||||
HADDR_SET( (buff->page_num)>>7 );
|
||||
buff->cur_byte = snes_rom_page_rd_poll( buff->data, addrH, buff->id,
|
||||
//id contains MSb of page when <256B buffer
|
||||
buff->last_idx, ~FALSE );
|
||||
case SNESRAM:
|
||||
//warn addrX = ((buff->page_num)>>8);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include "types.h"
|
||||
#include "buffer.h"
|
||||
#include "nes.h"
|
||||
#include "snes.h"
|
||||
#include "shared_dictionaries.h"
|
||||
#include "shared_errors.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ uint8_t io_call( uint8_t opcode, uint8_t miscdata, uint16_t operand, uint8_t *rd
|
|||
switch (opcode) {
|
||||
case IO_RESET: io_reset(); break;
|
||||
case NES_INIT: nes_init(); break;
|
||||
// case SNES_INIT: snes_init(); break;
|
||||
case SNES_INIT: snes_init(); break;
|
||||
case EXP0_PULLUP_TEST:
|
||||
rdata[RD_LEN] = BYTE_LEN;
|
||||
rdata[RD0] = exp0_pullup_test(); break;
|
||||
|
|
@ -152,11 +152,10 @@ void nes_init()
|
|||
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
//SNES cartridge interfacing setup
|
||||
//set outputs as required
|
||||
//latch address of $000000
|
||||
//latch address of $00:0000
|
||||
//disable cart memories
|
||||
//reset high disables SRAM and puts INL carts in PRGM mode
|
||||
//Excersize extreme caution calling this while NES/FC cart inserted
|
||||
|
|
@ -176,28 +175,26 @@ void snes_init()
|
|||
CSWR_OP();
|
||||
CSWR_HI();
|
||||
|
||||
//disable SRAM and put cart in PRGM mode
|
||||
//disable SRAM and put cart in PLAY mode
|
||||
EXP0_OP();
|
||||
EXP0_HI();
|
||||
|
||||
//other control pins are inputs or unused, leave as IP pullup from reset
|
||||
|
||||
//memories are now disabled Data bus should be clear
|
||||
|
||||
//setup AHL FF
|
||||
AHL_OP();
|
||||
AHL_CLK();
|
||||
//setup AXL FF
|
||||
AXL_OP();
|
||||
AXL_CLK();
|
||||
DATA_ENABLE();
|
||||
DATA_IP_PU();
|
||||
|
||||
//now meet conditions to call other macros
|
||||
//setup address $000000
|
||||
//setup address $0000
|
||||
ADDR_ENABLE();
|
||||
ADDR_SET(0x0000);
|
||||
ADDRX_SET(0x00);
|
||||
|
||||
//setup HIGH ADDR with bank $00
|
||||
HADDR_ENABLE();
|
||||
HADDR_SET(0x00);
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
//Test starts by verifying EXP0 can be driven low, if not, will return one byte of AUX_PIN
|
||||
//followed by alternating 0xAA, 0x55, 0xAA...
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ uint8_t io_call( uint8_t opcode, uint8_t miscdata, uint16_t operand, uint8_t *rd
|
|||
|
||||
void io_reset();
|
||||
void nes_init();
|
||||
//void snes_init();
|
||||
void snes_init();
|
||||
uint8_t exp0_pullup_test();
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -383,6 +383,15 @@ uint8_t pinport_call( uint8_t opcode, uint8_t miscdata, uint16_t operand, uint8_
|
|||
case EXP_DISABLE_: EXP_DISABLE(); break;
|
||||
case EXP_SET_: EXP_SET(operand); break;
|
||||
|
||||
//============================
|
||||
//HIGH ADDR PORT 8bit WIDE ACCESS
|
||||
//opcode: type of operation
|
||||
//operand: value to place on bus
|
||||
//============================
|
||||
case HADDR_ENABLE_: HADDR_ENABLE(); break;
|
||||
case HADDR_DISABLE_: HADDR_DISABLE(); break;
|
||||
case HADDR_SET_: HADDR_SET(operand); break;
|
||||
|
||||
default:
|
||||
//macro doesn't exist or isn't on this PCB version
|
||||
return ERR_UNKN_PP_OPCODE;
|
||||
|
|
|
|||
|
|
@ -478,10 +478,11 @@ void software_AXL_CLK();
|
|||
*/
|
||||
|
||||
|
||||
#define RCC_AHBENR_CTL (RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_GPIODEN)
|
||||
#define RCC_AHBENR_ADDR RCC_AHBENR_GPIOCEN
|
||||
#define RCC_AHBENR_DATA RCC_AHBENR_GPIOBEN
|
||||
#define RCC_AHBENR_EXP (RCC_AHBENR_GPIOBEN | RCC_AHBENR_GPIOBEN)
|
||||
#define RCC_AHBENR_CTL (RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_GPIODEN)
|
||||
#define RCC_AHBENR_ADDR RCC_AHBENR_GPIOCEN
|
||||
#define RCC_AHBENR_HADDR (RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN)
|
||||
#define RCC_AHBENR_DATA RCC_AHBENR_GPIOBEN
|
||||
#define RCC_AHBENR_EXP (RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN)
|
||||
|
||||
|
||||
#endif //STM_INL6
|
||||
|
|
@ -979,7 +980,7 @@ void software_AXL_CLK();
|
|||
|
||||
#define ADDR_EN_CLK() RCC->AHBENR |= RCC_AHBENR_ADDR
|
||||
#define ADDR_EN_FF() CTL_OP(AHLbank, AHL); CTL_SET_LO(AHLbank, AHL)
|
||||
#define ADDR_ENABLE() ADDR_EN_CLK(); ADDR_EN_FF(); ADDR_OP()
|
||||
#define ADDR_ENABLE() DATA_ENABLE(); ADDR_EN_CLK(); ADDR_EN_FF(); ADDR_OP()
|
||||
|
||||
#endif //STM_ADAPTER
|
||||
|
||||
|
|
@ -998,7 +999,7 @@ void software_AXL_CLK();
|
|||
#define ADDR_SET(hword) ADDRL(hword); ADDRH(hword>>8)
|
||||
|
||||
#define ADDR_EN_FF() CTL_OP(AHLbank, AHL); CTL_SET_LO(AHLbank, AHL)
|
||||
#define ADDR_ENABLE() ADDR_EN_FF(); ADDR_OP();
|
||||
#define ADDR_ENABLE() DATA_ENABLE(); ADDR_EN_FF(); ADDR_OP();
|
||||
|
||||
#endif //AVR_KAZZO
|
||||
|
||||
|
|
@ -1046,7 +1047,7 @@ void software_AXL_CLK();
|
|||
#define EXP_ENABLE() ADDR_EN_CLK(); EXP_OP()
|
||||
#define EXP_DISABLE() EXP_PU(); EXP_IP()
|
||||
|
||||
//STM_INL6
|
||||
//end STM_INL6
|
||||
#else //AVR_KAZZO or STM_ADAPTER
|
||||
|
||||
|
||||
|
|
@ -1068,5 +1069,56 @@ void software_AXL_CLK();
|
|||
#endif //AVR_KAZZO or STM_ADAPTER
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------------------
|
||||
// HIGH ADDRESS PORT 8bits A16-23
|
||||
//
|
||||
// This port is present on all devices
|
||||
// Restrictions: CANNOT be used when EXPANSION PORT is enabled
|
||||
// CIRAM_A10 & CIRAM /CE cannot be used on CONTROL PORT
|
||||
// Directionality: All pins are forced output
|
||||
// Driver: All pins are push-pull
|
||||
// Write/Output: Byte access only, no bit accesses
|
||||
// Read/Input: Not supported
|
||||
//
|
||||
// INL6 dual purposes A22-23 for CIRAM_A10 & CIRAM_CE respectively
|
||||
// EXP1-5, & 7 are mapped to A16-21 respectively
|
||||
//
|
||||
// AVR_KAZZO & STM_ADATPER use dual purpose the EXPANSION PORT for this PORT
|
||||
// EXP1-8 map to A16-23 respectively
|
||||
//
|
||||
// ---------------------------------------------------------------------------------------
|
||||
|
||||
#ifdef STM_INL6
|
||||
|
||||
//A16-21 are on PB10-15 these also map to EXP1-5, & 7
|
||||
//A22-23 are on PA9-10 these also map to CIRAM A10 & CIRAM /CE respectively
|
||||
#define A16_21bank GPIOB
|
||||
#define A22_23bank GPIOA
|
||||
|
||||
#define HADDR_PU() A16_21bank->PUPDR |= (PUPDR_PU_ALL & 0xFFF00000); A22_23bank->PUPDR |= (PUPDR_PU_ALL & 0x0003C000)
|
||||
#define HADDR_IP() A16_21bank->MODER &=~(MODER_OP_ALL & 0xFFF00000); A22_23bank->MODER &=~(MODER_OP_ALL & 0x0003C000)
|
||||
#define HADDR_OP() A16_21bank->MODER |= (MODER_OP_ALL & 0xFFF00000); A22_23bank->MODER |= (MODER_OP_ALL & 0x0003C000)
|
||||
|
||||
#define HADDR_SET(val) A16_21bank->ODR = ((A16_21bank->ODR&0x03FF) | (val<<10 & 0xFC00)); A22_23bank->ODR = ((A22_23bank->ODR & 0xF9FF) | (val<<3 & 0x0600))
|
||||
|
||||
#define HADDR_EN_CLK() RCC->AHBENR |= RCC_AHBENR_HADDR
|
||||
#define HADDR_ENABLE() HADDR_EN_CLK(); HADDR_OP()
|
||||
#define HADDR_DISABLE() HADDR_PU(); HADDR_IP()
|
||||
|
||||
//end STM_INL6
|
||||
#else //AVR_KAZZO or STM_ADAPTER
|
||||
|
||||
|
||||
// ADDR16-23 are behind AXL flipflop
|
||||
|
||||
//clocks must be initialized, Data bus clear
|
||||
#define HADDR_SET(val) EXP_SET(val)
|
||||
|
||||
#define HADDR_EN_FF() EXP_EN_FF()
|
||||
#define HADDR_ENABLE() EXP_ENABLE()
|
||||
#define HADDR_DISABLE() EXP_DISABLE()
|
||||
|
||||
#endif //AVR_KAZZO or STM_ADAPTER
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -0,0 +1,589 @@
|
|||
#include "snes.h"
|
||||
|
||||
//=================================================================================================
|
||||
//
|
||||
// SNES operations
|
||||
// This file includes all the snes functions possible to be called from the snes dictionary.
|
||||
//
|
||||
// See description of the commands contained here in shared/shared_dictionaries.h
|
||||
//
|
||||
//=================================================================================================
|
||||
|
||||
/* Desc:Function takes an opcode which was transmitted via USB
|
||||
* then decodes it to call designated function.
|
||||
* shared_dict_snes.h is used in both host and fw to ensure opcodes/names align
|
||||
* Pre: Macros must be defined in firmware pinport.h
|
||||
* opcode must be defined in shared_dict_snes.h
|
||||
* Post:function call complete.
|
||||
* Rtn: SUCCESS if opcode found and completed, error if opcode not present or other problem.
|
||||
*/
|
||||
uint8_t snes_call( uint8_t opcode, uint8_t miscdata, uint16_t operand, uint8_t *rdata )
|
||||
{
|
||||
|
||||
#define RD_LEN 0
|
||||
#define RD0 1
|
||||
#define RD1 2
|
||||
|
||||
#define BYTE_LEN 1
|
||||
#define HWORD_LEN 2
|
||||
|
||||
switch (opcode) {
|
||||
//no return value:
|
||||
case SNES_SET_BANK:
|
||||
HADDR_SET( operand );
|
||||
break;
|
||||
case SNES_ROM_WR:
|
||||
snes_rom_wr( operand, miscdata );
|
||||
break;
|
||||
|
||||
//8bit return values:
|
||||
case SNES_ROM_RD:
|
||||
rdata[RD_LEN] = BYTE_LEN;
|
||||
rdata[RD0] = snes_rom_rd( operand );
|
||||
break;
|
||||
default:
|
||||
//macro doesn't exist
|
||||
return ERR_UNKN_SNES_OPCODE;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
/* Desc:SNES ROM Read without changing high bank
|
||||
* /ROMSEL always set low
|
||||
* EXP0/RESET not affected
|
||||
* Pre: snes_init() setup of io pins
|
||||
* Post:address left on bus
|
||||
* data bus left clear
|
||||
* Rtn: Byte read from ROM at addr
|
||||
*/
|
||||
uint8_t snes_rom_rd( uint16_t addr )
|
||||
{
|
||||
uint8_t read; //return value
|
||||
|
||||
//set address bus
|
||||
ADDR_SET(addr);
|
||||
|
||||
ROMSEL_LO();
|
||||
CSRD_LO();
|
||||
|
||||
//couple more NOP's waiting for data
|
||||
//zero nop's returned previous databus value
|
||||
NOP(); //one nop got most of the bits right
|
||||
NOP(); //two nop got all the bits right
|
||||
NOP(); //add third nop for some extra
|
||||
NOP(); //one more can't hurt
|
||||
//might need to wait longer for some carts...
|
||||
|
||||
//latch data
|
||||
DATA_RD(read);
|
||||
|
||||
//return bus to default
|
||||
CSRD_HI();
|
||||
ROMSEL_HI();
|
||||
|
||||
return read;
|
||||
}
|
||||
|
||||
/* Desc:SNES ROM Write
|
||||
* /ROMSEL always set low
|
||||
* EXP0/RESET unaffected
|
||||
* read value from currently selected bank
|
||||
* Pre: snes_init() setup of io pins
|
||||
* Post:data latched by anything listening on the bus
|
||||
* address left on bus
|
||||
* Rtn: None
|
||||
*/
|
||||
void snes_rom_wr( uint16_t addr, uint8_t data )
|
||||
{
|
||||
|
||||
ADDR_SET(addr);
|
||||
|
||||
//put data on bus
|
||||
DATA_OP();
|
||||
DATA_SET(data);
|
||||
|
||||
//PRG R/W LO
|
||||
ROMSEL_LO();
|
||||
CSWR_LO();
|
||||
|
||||
//give some time
|
||||
NOP();
|
||||
NOP();
|
||||
|
||||
//latch data to cart memory/mapper
|
||||
ROMSEL_HI();
|
||||
CSWR_HI();
|
||||
|
||||
//Free data bus
|
||||
DATA_IP();
|
||||
}
|
||||
|
||||
/* Desc:SNES ROM Page Read with optional USB polling
|
||||
* /ROMSEL always low, EXP0/RESET unaffected
|
||||
* if poll is true calls usbdrv.h usbPoll fuction
|
||||
* this is needed to keep from timing out when double buffering usb data
|
||||
* Pre: snes_init() setup of io pins
|
||||
* num_bytes can't exceed 256B page boundary
|
||||
* Post:address left on bus
|
||||
* data bus left clear
|
||||
* data buffer filled starting at first to last
|
||||
* Rtn: Index of last byte read
|
||||
*/
|
||||
uint8_t snes_rom_page_rd_poll( uint8_t *data, uint8_t addrH, uint8_t first, uint8_t len, uint8_t poll )
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
//set address bus
|
||||
ADDRH(addrH);
|
||||
|
||||
//set /ROMSEL and /RD
|
||||
CSRD_LO();
|
||||
ROMSEL_LO();
|
||||
|
||||
//set lower address bits
|
||||
ADDRL(first); //doing this prior to entry and right after latching
|
||||
//gives longest delay between address out and latching data
|
||||
for( i=0; i<=len; i++ ) {
|
||||
//testing shows that having this if statement doesn't affect overall dumping speed
|
||||
if ( poll == FALSE ) {
|
||||
NOP(); //couple more NOP's waiting for data
|
||||
NOP(); //one prob good enough considering the if/else
|
||||
NOP();
|
||||
NOP();
|
||||
} else {
|
||||
usbPoll(); //Call usbdrv.h usb polling while waiting for data
|
||||
NOP();
|
||||
NOP();
|
||||
NOP();
|
||||
}
|
||||
//latch data
|
||||
DATA_RD(data[i]);
|
||||
|
||||
//set lower address bits
|
||||
//ADDRL(++first); THIS broke things, on stm adapter because macro expands it twice!
|
||||
first++;
|
||||
ADDRL(first);
|
||||
}
|
||||
|
||||
//return bus to default
|
||||
CSRD_HI();
|
||||
ROMSEL_HI();
|
||||
|
||||
//return index of last byte read
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
// /* Desc: Discrete board PRG-ROM only write, does not write to mapper
|
||||
// * PRG-ROM /WE <- EXP0 w/PU
|
||||
// * PRG-ROM /OE <- /ROMSEL
|
||||
// * PRG-ROM /CE <- GND
|
||||
// * PRG-ROM write: /WE & /CE low, /OE high
|
||||
// * mapper '161 CLK <- /ROMSEL
|
||||
// * mapper '161 /LOAD <- PRG R/W
|
||||
// * mapper '161 /LOAD must be low on rising edge of CLK to latch data
|
||||
// * This is a /WE controlled write. Address latched on falling edge,
|
||||
// * and data latched on rising edge EXP0
|
||||
// * Note:addrH bit7 has no effect (ends up on PPU /A13)
|
||||
// * /ROMSEL, M2, & PRG R/W signals untouched
|
||||
// * Pre: nes_init() setup of io pins
|
||||
// * Post:data latched by PRG-ROM, mapper register unaffected
|
||||
// * address left on bus
|
||||
// * data left on bus, but pullup only
|
||||
// * EXP0 left pulled up
|
||||
// * Rtn: None
|
||||
// */
|
||||
// void discrete_exp0_prgrom_wr( uint16_t addr, uint8_t data )
|
||||
// {
|
||||
// ADDR_SET(addr);
|
||||
//
|
||||
// DATA_OP();
|
||||
// DATA_SET(data);
|
||||
//
|
||||
// EXP0_OP(); //Tas = 0ns, Tah = 30ns
|
||||
// EXP0_LO();
|
||||
// EXP0_IP_PU(); //Twp = 40ns, Tds = 40ns, Tdh = 0ns
|
||||
// //16Mhz avr clk = 62.5ns period guarantees timing reqts
|
||||
// DATA_IP();
|
||||
// }
|
||||
//
|
||||
// //
|
||||
// // /* Desc:Emulate NES CPU Read as best possible
|
||||
// // * decode A15 from addrH to set /ROMSEL as expected
|
||||
// // * float EXP0
|
||||
// // * toggle M2 as NES would
|
||||
// // * insert some NOP's in to be slow like NES
|
||||
// // * Note:not the fastest read operation
|
||||
// // * Pre: nes_init() setup of io pins
|
||||
// // * Post:address left on bus
|
||||
// // * data bus left clear
|
||||
// // * EXP0 left floating
|
||||
// // * Rtn: Byte read from PRG-ROM at addrHL
|
||||
// // */
|
||||
// // uint8_t emulate_nes_cpu_rd( uint8_t addrH, uint8_t addrL )
|
||||
// // {
|
||||
// // uint8_t read; //return value
|
||||
// //
|
||||
// // //m2 should be low as it aids in disabling WRAM
|
||||
// // //this is also m2 state at beginging of CPU cycle
|
||||
// // //all these pins should already be in this state, but
|
||||
// // //go ahead and setup just to be sure since we're trying
|
||||
// // //to be as accurate as possible
|
||||
// // _EXP0_FLT(); //this could have been left pulled up
|
||||
// // _M2_LO(); //start of CPU cycle
|
||||
// // _ROMSEL_HI(); //trails M2
|
||||
// // _PRGRW_RD(); //happens just after M2
|
||||
// //
|
||||
// // //set address bus
|
||||
// // ADDR_OUT = addrL;
|
||||
// // _ADDRH_SET(addrH);
|
||||
// //
|
||||
// // //couple NOP's to wait a bit
|
||||
// // NOP();
|
||||
// // NOP();
|
||||
// //
|
||||
// // //set M2 and /ROMSEL
|
||||
// // if( addrH >= 0x80 ) { //addressing cart rom space
|
||||
// // _M2_HI();
|
||||
// // _ROMSEL_LO(); //romsel trails M2 during CPU operations
|
||||
// // } else {
|
||||
// // _M2_HI();
|
||||
// // }
|
||||
// //
|
||||
// // //couple more NOP's waiting for data
|
||||
// // NOP();
|
||||
// // NOP();
|
||||
// // NOP();
|
||||
// // NOP();
|
||||
// // NOP();
|
||||
// // NOP();
|
||||
// //
|
||||
// // //latch data
|
||||
// // read = DATA_IN;
|
||||
// //
|
||||
// // //return bus to default
|
||||
// // _M2_LO();
|
||||
// // _ROMSEL_HI();
|
||||
// //
|
||||
// // return read;
|
||||
// // }
|
||||
// //
|
||||
// /* Desc:NES CPU Read without being so slow
|
||||
// * decode A15 from addrH to set /ROMSEL as expected
|
||||
// * float EXP0
|
||||
// * toggle M2 as NES would
|
||||
// * Pre: nes_init() setup of io pins
|
||||
// * Post:address left on bus
|
||||
// * data bus left clear
|
||||
// * EXP0 left floating
|
||||
// * Rtn: Byte read from PRG-ROM at addrHL
|
||||
// */
|
||||
// uint8_t nes_cpu_rd( uint16_t addr )
|
||||
// {
|
||||
// uint8_t read; //return value
|
||||
//
|
||||
// //set address bus
|
||||
// ADDR_SET(addr);
|
||||
//
|
||||
// //set M2 and /ROMSEL
|
||||
// MCO_HI();
|
||||
// if( addr >= 0x8000 ) { //addressing cart rom space
|
||||
// ROMSEL_LO(); //romsel trails M2 during CPU operations
|
||||
// }
|
||||
//
|
||||
// //couple more NOP's waiting for data
|
||||
// //zero nop's returned previous databus value
|
||||
// NOP(); //one nop got most of the bits right
|
||||
// NOP(); //two nop got all the bits right
|
||||
// NOP(); //add third nop for some extra
|
||||
// NOP(); //one more can't hurt
|
||||
// //might need to wait longer for some carts...
|
||||
//
|
||||
// //latch data
|
||||
// DATA_RD(read);
|
||||
//
|
||||
// //return bus to default
|
||||
// MCO_LO();
|
||||
// ROMSEL_HI();
|
||||
//
|
||||
// return read;
|
||||
// }
|
||||
//
|
||||
// /* Desc:NES CPU Write
|
||||
// * Just as you would expect NES's CPU to perform
|
||||
// * A15 decoded to enable /ROMSEL
|
||||
// * This ends up as a M2 and/or /ROMSEL controlled write
|
||||
// * Note:addrH bit7 has no effect (ends up on PPU /A13)
|
||||
// * EXP0 floating
|
||||
// * Pre: nes_init() setup of io pins
|
||||
// * Post:data latched by anything listening on the bus
|
||||
// * address left on bus
|
||||
// * data left on bus, but pullup only
|
||||
// * Rtn: None
|
||||
// */
|
||||
// void nes_cpu_wr( uint16_t addr, uint8_t data )
|
||||
// {
|
||||
// //Float EXP0 as it should be in NES
|
||||
// EXP0_IP_FL();
|
||||
//
|
||||
// //need for whole function
|
||||
// //_DATA_OP();
|
||||
//
|
||||
// //set addrL
|
||||
// //ADDR_OUT = addrL;
|
||||
// //latch addrH
|
||||
// //DATA_OUT = addrH;
|
||||
// //_AHL_CLK();
|
||||
// ADDR_SET(addr);
|
||||
//
|
||||
// //PRG R/W LO
|
||||
// PRGRW_LO();
|
||||
//
|
||||
// //put data on bus
|
||||
// DATA_OP();
|
||||
// DATA_SET(data);
|
||||
//
|
||||
// //set M2 and /ROMSEL
|
||||
// MCO_HI();
|
||||
// if( addr >= 0x8000 ) { //addressing cart rom space
|
||||
// ROMSEL_LO(); //romsel trails M2 during CPU operations
|
||||
// }
|
||||
//
|
||||
// //give some time
|
||||
// NOP();
|
||||
// NOP();
|
||||
//
|
||||
// //latch data to cart memory/mapper
|
||||
// MCO_LO();
|
||||
// ROMSEL_HI();
|
||||
//
|
||||
// //retore PRG R/W to default
|
||||
// PRGRW_HI();
|
||||
//
|
||||
// //Free data bus
|
||||
// DATA_IP();
|
||||
// }
|
||||
//
|
||||
// /* Desc:NES PPU Read
|
||||
// * decode A13 from addrH to set /A13 as expected
|
||||
// * Pre: nes_init() setup of io pins
|
||||
// * Post:address left on bus
|
||||
// * data bus left clear
|
||||
// * Rtn: Byte read from CHR-ROM/RAM at addrHL
|
||||
// */
|
||||
// uint8_t nes_ppu_rd( uint16_t addr )
|
||||
// {
|
||||
// uint8_t read; //return value
|
||||
//
|
||||
// //addr with PPU /A13
|
||||
// if (addr < 0x2000) { //below $2000 A13 clear, /A13 set
|
||||
// addr |= PPU_A13N_WORD;
|
||||
// } //above PPU $1FFF, A13 set, /A13 clear
|
||||
//
|
||||
// ADDR_SET( addr );
|
||||
//
|
||||
// //set CHR /RD and /WR
|
||||
// CSRD_LO();
|
||||
//
|
||||
// //couple more NOP's waiting for data
|
||||
// //zero nop's returned previous databus value
|
||||
// NOP(); //one nop got most of the bits right
|
||||
// NOP(); //two nop got all the bits right
|
||||
// NOP(); //add third nop for some extra
|
||||
// NOP(); //one more can't hurt
|
||||
// //might need to wait longer for some carts...
|
||||
//
|
||||
// //latch data
|
||||
// DATA_RD(read);
|
||||
//
|
||||
// //return bus to default
|
||||
// CSRD_HI();
|
||||
//
|
||||
// return read;
|
||||
// }
|
||||
//
|
||||
// /* Desc:NES PPU Write
|
||||
// * decode A13 from addrH to set /A13 as expected
|
||||
// * flash: address clocked falling edge, data rising edge of /WE
|
||||
// * Pre: nes_init() setup of io pins
|
||||
// * Post:data written to addrHL
|
||||
// * address left on bus
|
||||
// * data bus left clear
|
||||
// * Rtn: None
|
||||
// */
|
||||
//
|
||||
// void nes_ppu_wr( uint16_t addr, uint8_t data )
|
||||
// {
|
||||
//
|
||||
// //addr with PPU /A13
|
||||
// if (addr < 0x2000) { //below $2000 A13 clear, /A13 set
|
||||
// addr |= PPU_A13N_WORD;
|
||||
// } //above PPU $1FFF, A13 set, /A13 clear
|
||||
//
|
||||
// ADDR_SET( addr );
|
||||
//
|
||||
// //put data on bus
|
||||
// DATA_OP();
|
||||
// DATA_SET(data);
|
||||
//
|
||||
// NOP();
|
||||
//
|
||||
// //set CHR /RD and /WR
|
||||
// CSWR_LO();
|
||||
//
|
||||
// //might need to wait longer for some carts...
|
||||
// NOP(); //one can't hurt
|
||||
//
|
||||
// //latch data to memory
|
||||
// CSWR_HI();
|
||||
//
|
||||
// //clear data bus
|
||||
// DATA_IP();
|
||||
//
|
||||
// }
|
||||
//
|
||||
//
|
||||
// /* Desc:PPU CIRAM A10 NT arrangement sense
|
||||
// * Toggle A11 and A10 and read back CIRAM A10
|
||||
// * report back if vert/horiz/1scnA/1scnB
|
||||
// * reports nesdev defined mirroring
|
||||
// * does not report Nintendo's "Name Table Arrangement"
|
||||
// * Pre: nes_init() setup of io pins
|
||||
// * Post:address left on bus
|
||||
// * Rtn: MIR_VERT, MIR_HORIZ, MIR_1SCNA, MIR_1SCNB
|
||||
// * errors not really possible since all combinations
|
||||
// * of CIRAM A10 level designate something valid
|
||||
// */
|
||||
// uint8_t ciram_a10_mirroring( void )
|
||||
// {
|
||||
// uint16_t readV, readH;
|
||||
//
|
||||
// //set A10, clear A11
|
||||
// ADDRH(A10_BYTE);
|
||||
// CIA10_RD(readV);
|
||||
//
|
||||
// //set A11, clear A10
|
||||
// ADDRH(A11_BYTE);
|
||||
// CIA10_RD(readH);
|
||||
//
|
||||
// //if CIRAM A10 was always low -> 1 screen A
|
||||
// if ((readV==0) & (readH==0)) return MIR_1SCNA;
|
||||
// //if CIRAM A10 was always hight -> 1screen B
|
||||
// if ((readV!=0) & (readH!=0)) return MIR_1SCNB;
|
||||
// //if CIRAM A10 toggled with A10 -> Vertical mirroring, horizontal arrangement
|
||||
// if ((readV!=0) & (readH==0)) return MIR_VERT;
|
||||
// //if CIRAM A10 toggled with A11 -> Horizontal mirroring, vertical arrangement
|
||||
// if ((readV==0) & (readH!=0)) return MIR_HORZ;
|
||||
//
|
||||
// //shouldn't be here...
|
||||
// return GEN_FAIL;
|
||||
// }
|
||||
//
|
||||
// /* Desc:NES CPU Page Read with optional USB polling
|
||||
// * decode A15 from addrH to set /ROMSEL as expected
|
||||
// * float EXP0
|
||||
// * toggle M2 as NES would
|
||||
// * if poll is true calls usbdrv.h usbPoll fuction
|
||||
// * this is needed to keep from timing out when double buffering usb data
|
||||
// * Pre: nes_init() setup of io pins
|
||||
// * num_bytes can't exceed 256B page boundary
|
||||
// * Post:address left on bus
|
||||
// * data bus left clear
|
||||
// * EXP0 left floating
|
||||
// * data buffer filled starting at first to last
|
||||
// * Rtn: Index of last byte read
|
||||
// */
|
||||
// uint8_t nes_cpu_page_rd_poll( uint8_t *data, uint8_t addrH, uint8_t first, uint8_t len, uint8_t poll )
|
||||
// {
|
||||
// uint8_t i;
|
||||
//
|
||||
// //set address bus
|
||||
// ADDRH(addrH);
|
||||
//
|
||||
// //set M2 and /ROMSEL
|
||||
// MCO_HI();
|
||||
// if( addrH >= 0x80 ) { //addressing cart rom space
|
||||
// ROMSEL_LO(); //romsel trails M2 during CPU operations
|
||||
// }
|
||||
//
|
||||
// //set lower address bits
|
||||
// ADDRL(first); //doing this prior to entry and right after latching
|
||||
// //gives longest delay between address out and latching data
|
||||
// for( i=0; i<=len; i++ ) {
|
||||
// //testing shows that having this if statement doesn't affect overall dumping speed
|
||||
// if ( poll == FALSE ) {
|
||||
// NOP(); //couple more NOP's waiting for data
|
||||
// NOP(); //one prob good enough considering the if/else
|
||||
// } else {
|
||||
// usbPoll(); //Call usbdrv.h usb polling while waiting for data
|
||||
// }
|
||||
// //latch data
|
||||
// DATA_RD(data[i]);
|
||||
// //set lower address bits
|
||||
// //ADDRL(++first); THIS broke things, on stm adapter because macro expands it twice!
|
||||
// first++;
|
||||
// ADDRL(first);
|
||||
// }
|
||||
//
|
||||
// //return bus to default
|
||||
// MCO_LO();
|
||||
// ROMSEL_HI();
|
||||
//
|
||||
// //return index of last byte read
|
||||
// return i;
|
||||
// }
|
||||
//
|
||||
// /* Desc:NES PPU Page Read with optional USB polling
|
||||
// * decode A13 from addrH to set /A13 as expected
|
||||
// * if poll is true calls usbdrv.h usbPoll fuction
|
||||
// * this is needed to keep from timing out when double buffering usb data
|
||||
// * Pre: nes_init() setup of io pins
|
||||
// * num_bytes can't exceed 256B page boundary
|
||||
// * Post:address left on bus
|
||||
// * data bus left clear
|
||||
// * data buffer filled starting at first for len number of bytes
|
||||
// * Rtn: Index of last byte read
|
||||
// */
|
||||
// uint8_t nes_ppu_page_rd_poll( uint8_t *data, uint8_t addrH, uint8_t first, uint8_t len, uint8_t poll )
|
||||
// {
|
||||
// uint8_t i;
|
||||
//
|
||||
// if (addrH < 0x20) { //below $2000 A13 clear, /A13 set
|
||||
// //ADDRH(addrH | PPU_A13N_BYTE);
|
||||
// //Don't do weird stuff like above! logic inside macro expansions can have weird effects!!
|
||||
// addrH |= PPU_A13N_BYTE;
|
||||
// ADDRH(addrH);
|
||||
// } else { //above PPU $1FFF, A13 set, /A13 clear
|
||||
// ADDRH(addrH);
|
||||
// }
|
||||
//
|
||||
// //set CHR /RD and /WR
|
||||
// CSRD_LO();
|
||||
//
|
||||
// //set lower address bits
|
||||
// ADDRL(first); //doing this prior to entry and right after latching
|
||||
// //gives longest delay between address out and latching data
|
||||
//
|
||||
// for( i=0; i<=len; i++ ) {
|
||||
// //couple more NOP's waiting for data
|
||||
// if ( poll == FALSE ) {
|
||||
// NOP(); //one prob good enough considering the if/else
|
||||
// NOP();
|
||||
// } else {
|
||||
// usbPoll();
|
||||
// }
|
||||
// //latch data
|
||||
// DATA_RD(data[i]);
|
||||
// //set lower address bits
|
||||
// first ++;
|
||||
// ADDRL(first);
|
||||
// }
|
||||
//
|
||||
// //return bus to default
|
||||
// CSRD_HI();
|
||||
//
|
||||
// //return index of last byte read
|
||||
// return i;
|
||||
// }
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef _snes_h
|
||||
#define _snes_h
|
||||
|
||||
#include "pinport.h"
|
||||
#include "buffer.h" //TODO remove this junk when get rid of FALSE
|
||||
#include "shared_dictionaries.h"
|
||||
#include "shared_errors.h"
|
||||
|
||||
uint8_t snes_call( uint8_t opcode, uint8_t miscdata, uint16_t operand, uint8_t *rdata );
|
||||
uint8_t snes_rom_rd( uint16_t addr );
|
||||
void snes_rom_wr( uint16_t addr, uint8_t data );
|
||||
uint8_t snes_rom_page_rd_poll( uint8_t *data, uint8_t addrH, uint8_t first, uint8_t len, uint8_t poll );
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -113,6 +113,10 @@ uint16_t usbFunctionSetup(uint8_t data[8]) {
|
|||
rv[RETURN_ERR_IDX] = nes_call( spacket->opcode, spacket->miscdata, spacket->operand, &rv[RETURN_LEN_IDX] );
|
||||
break; //end of NES
|
||||
|
||||
case DICT_SNES:
|
||||
rv[RETURN_ERR_IDX] = snes_call( spacket->opcode, spacket->miscdata, spacket->operand, &rv[RETURN_LEN_IDX] );
|
||||
break; //end of NES
|
||||
|
||||
|
||||
case DICT_BUFFER:
|
||||
//just give buffer.c the setup packet and let it figure things out for itself
|
||||
|
|
@ -120,10 +124,6 @@ uint16_t usbFunctionSetup(uint8_t data[8]) {
|
|||
break; //end of BUFFER
|
||||
|
||||
/*
|
||||
case DICT_SNES:
|
||||
//break; //end of SNES
|
||||
|
||||
|
||||
case DICT_USB:
|
||||
//currently just a simple way to read back usbFunctionWrite status SUCCESS/ERROR
|
||||
//if there are future status' to read back may have to create some functions
|
||||
|
|
|
|||
|
|
@ -15,13 +15,13 @@
|
|||
#include "pinport.h"
|
||||
#include "io.h"
|
||||
#include "nes.h"
|
||||
#include "snes.h"
|
||||
#include "buffer.h"
|
||||
#include "types.h"
|
||||
#include "shared_usb.h"
|
||||
#include "shared_errors.h"
|
||||
#include "shared_dictionaries.h"
|
||||
|
||||
//#include "snes.h"
|
||||
|
||||
#define ENDPOINT_BIT 0x80 //Bit 7 of bmRequest type determines endpoint
|
||||
#define ENDPOINT_IN 0x80 //In: device-to-host.
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ local cart = {}
|
|||
-- import required modules
|
||||
local dict = require "scripts.app.dict"
|
||||
local nes = require "scripts.app.nes"
|
||||
local snes = require "scripts.app.snes"
|
||||
|
||||
-- file constants
|
||||
|
||||
|
|
@ -48,14 +49,26 @@ local function detect_console( debug )
|
|||
|
||||
-- //if couldn't detect NES/FC check for SNES cartridge
|
||||
-- //want to keep from outputting on EXP bus if NES cart was found
|
||||
-- if ( cart->console == UNKNOWN ) {
|
||||
-- //only way I can think of is if memory is enabled by certain addresses and control signals
|
||||
-- snes_init( transfer );
|
||||
-- if ( snes_mem_visible( transfer, 0x00, 0xFFFC )) {
|
||||
-- //CHECK for memory visible near NES reset vector
|
||||
-- debug("SNES memories detected");
|
||||
-- cart->console = SNES_CART;
|
||||
-- }
|
||||
if cart_console == nil then
|
||||
|
||||
--currently detect SNES cartridge by reading reset vector
|
||||
--ensuring it's valid by range and differing between banks
|
||||
dict.io("SNES_INIT")
|
||||
|
||||
local bank0vect = snes.read_reset_vector( 0, debug ) --actual reset vector
|
||||
local bank1vect = snes.read_reset_vector( 1, debug )
|
||||
--bank 0 and bank 1 would have same reset vector on a NES cart
|
||||
--these probably differ on a SNES if there's more than 32/64KB of ROM.
|
||||
|
||||
if bank0vect ~= bank1vect then
|
||||
if (bank0vect >= 0x8000) and (bank0vect < 0xFFFA) then
|
||||
if debug then print("valid SNES reset vector found that differs between bank0 & bank1") end
|
||||
cart_console = "SNES"
|
||||
end
|
||||
else
|
||||
if debug then print("invalid SNES reset vector or same vector found on bank0 & bank1") end
|
||||
end
|
||||
|
||||
-- //now it's possible that rom is there, but data is 0xFF so above test would fail
|
||||
-- //one option would be to drive bus low for short period and see if bus can be
|
||||
-- //driven low. This could damage pin drivers though, best to create command in
|
||||
|
|
@ -66,6 +79,7 @@ local function detect_console( debug )
|
|||
--
|
||||
-- //playable SNES carts should have data somewhere in reset vector...
|
||||
-- }
|
||||
end
|
||||
--
|
||||
-- //always end with resetting i/o
|
||||
dict.io("IO_RESET")
|
||||
|
|
|
|||
|
|
@ -319,6 +319,61 @@ local function nes( opcode, operand, misc, data )
|
|||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
-- external call for snes dictionary
|
||||
local function snes( opcode, operand, misc, data )
|
||||
|
||||
if not op_snes[opcode] then
|
||||
print("ERROR undefined opcode:", opcode, "must be defined in shared_dict_snes.h")
|
||||
return nil
|
||||
end
|
||||
|
||||
if not operand then
|
||||
operand = 0
|
||||
elseif type(operand) == "string" then
|
||||
if not op_snes[operand] then
|
||||
print("ERROR undefined operand:", operand, "must be defined in shared_dict_snes.h")
|
||||
return nil
|
||||
end
|
||||
--decode string operands into
|
||||
operand = op_snes[operand]
|
||||
end
|
||||
|
||||
if not misc then misc = 0 end
|
||||
|
||||
local wLength, ep = default_rlen_1_in(op_snes[opcode.."rlen"])
|
||||
|
||||
local count
|
||||
count, data = usb_vend_xfr(
|
||||
-- ep, dictionary wValue[misc:opcode] wIndex wLength data
|
||||
ep, dict["DICT_SNES"], ( misc<<8 | op_snes[opcode]), operand, wLength, data)
|
||||
--print(count)
|
||||
local error_code, data_len
|
||||
if ep == USB_IN then
|
||||
error_code = data:byte(RETURN_ERR_IDX)
|
||||
data_len = data:byte(RETURN_LEN_IDX)
|
||||
end
|
||||
--print("error:", error_code, "data_len:", data_len)
|
||||
|
||||
assert ( (error_code == err_codes["SUCCESS"]), "ERROR!!! device error code:", error_code)
|
||||
--if error_code ~= err_codes["SUCCESS"] then
|
||||
-- print("ERROR!!! device error code:", error_code)
|
||||
--end
|
||||
|
||||
if data_len and data_len ~= (wLength - RETURN_LEN_IDX) then
|
||||
print("WARNING!! Device's return data length:", data_len, "did not match expected:", wLength-RETURN_LEN_IDX)
|
||||
end
|
||||
|
||||
--process the return data string and return it to calling function
|
||||
if data_len then
|
||||
return string_to_int( data:sub(RETURN_DATA, data_len+RETURN_DATA), data_len)
|
||||
else
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
local function buffer_payload_in( wLength, buff_num )
|
||||
|
|
@ -510,13 +565,14 @@ create_dict_tables( op_buffer, "../shared/shared_dict_buffer.h")
|
|||
create_dict_tables( op_io, "../shared/shared_dict_io.h")
|
||||
create_dict_tables( op_operation, "../shared/shared_dict_operation.h")
|
||||
create_dict_tables( op_nes, "../shared/shared_dict_nes.h")
|
||||
--create_dict_tables( op_snes, "../shared/shared_dict_snes.h")
|
||||
create_dict_tables( op_snes, "../shared/shared_dict_snes.h")
|
||||
create_dict_tables( err_codes, "../shared/shared_errors.h")
|
||||
|
||||
-- functions other modules are able to call
|
||||
dict.pinport = pinport
|
||||
dict.io = io
|
||||
dict.nes = nes
|
||||
dict.snes = snes
|
||||
dict.buffer = buffer
|
||||
dict.buffer_payload_in = buffer_payload_in
|
||||
dict.buffer_payload_out = buffer_payload_out
|
||||
|
|
|
|||
|
|
@ -232,6 +232,108 @@ local function dump_nes( file, debug )
|
|||
end
|
||||
|
||||
|
||||
local function dump_snes( file, mapping, debug )
|
||||
|
||||
local buff0 = 0
|
||||
local buff1 = 1
|
||||
local cur_buff_status = 0
|
||||
local data = nil --lua stores data in strings
|
||||
|
||||
if mapping ~= "LOROM" then
|
||||
print("currently only support LOROM SNES mapping!!!")
|
||||
end
|
||||
|
||||
if debug then print("dumping cart") end
|
||||
|
||||
--start with reset and init
|
||||
dict.io("IO_RESET")
|
||||
dict.io("SNES_INIT")
|
||||
|
||||
--setup buffers and manager
|
||||
dict.operation("SET_OPERATION", op_buffer["RESET"] )
|
||||
--reset buffers first
|
||||
dict.buffer("RAW_BUFFER_RESET")
|
||||
|
||||
--need to allocate some buffers for dumping
|
||||
--2x 128Byte buffers
|
||||
local num_buffers = 2
|
||||
local buff_size = 128
|
||||
print("allocating buffers")
|
||||
assert(buffers.allocate( num_buffers, buff_size ), "fail to allocate buffers")
|
||||
|
||||
--set buffer elements as needed
|
||||
--set reload which gets added to page_num after each buffer read
|
||||
--set reload to 256 = 1 when translated to page_num (done in allocate buffers funct)
|
||||
--set page_num to non-zero if offset arg sent
|
||||
--set mem_type and part_num to designate how to get/write data
|
||||
print("setting map n part")
|
||||
dict.buffer("SET_MEM_N_PART", (op_buffer["SNESROM"]<<8 | op_buffer["MASKROM"]), buff0 )
|
||||
dict.buffer("SET_MEM_N_PART", (op_buffer["SNESROM"]<<8 | op_buffer["MASKROM"]), buff1 )
|
||||
|
||||
--set multiple and add_mult only when flashing
|
||||
--set mapper, map_var, and function to designate read/write algo
|
||||
|
||||
print("setting map n mapvar")
|
||||
dict.buffer("SET_MAP_N_MAPVAR", (op_buffer[mapping]<<8 | op_buffer["NOVAR"]), buff0 )
|
||||
dict.buffer("SET_MAP_N_MAPVAR", (op_buffer[mapping]<<8 | op_buffer["NOVAR"]), buff1 )
|
||||
|
||||
-- //tell buffers what function to use for dumping
|
||||
-- //TODO when start implementing other mappers
|
||||
|
||||
--debugging print out buffer elements
|
||||
--print("\nget operation:")
|
||||
--dict.operation("GET_OPERATION" )
|
||||
--print("\n\ngetting cur_buff status")
|
||||
--dict.buffer("GET_CUR_BUFF_STATUS" )
|
||||
--print("\n\ngetting elements")
|
||||
--dict.buffer("GET_PRI_ELEMENTS", nil, buff0 )
|
||||
--dict.buffer("GET_PRI_ELEMENTS", nil, buff1 )
|
||||
--dict.buffer("GET_SEC_ELEMENTS", nil, buff0 )
|
||||
--dict.buffer("GET_SEC_ELEMENTS", nil, buff1 )
|
||||
--dict.buffer("GET_PAGE_NUM", nil, buff0 )
|
||||
--dict.buffer("GET_PAGE_NUM", nil, buff1 )
|
||||
|
||||
print("\n\nsetting operation STARTDUMP");
|
||||
--inform buffer manager to start dumping operation now that buffers are initialized
|
||||
dict.operation("SET_OPERATION", op_buffer["STARTDUMP"] )
|
||||
|
||||
--need these calls to delay things a bit to let first buffer dump complete..
|
||||
--wait for first buffer to finish dumping before calling payload
|
||||
buffers.status_wait({buff0}, {"DUMPED"})
|
||||
|
||||
print("starting first payload");
|
||||
--now just need to call series of payload IN transfers to retrieve data
|
||||
for i=1, (2048*1024/buff_size) do
|
||||
file:write( dict.buffer_payload_in( buff_size ))
|
||||
end
|
||||
|
||||
print("payload done");
|
||||
--buffer manager updates from USB_UNLOADING -> DUMPING -> DUMPED
|
||||
--while one buffer is unloading, it sends next buffer off to dump
|
||||
--payout opcode updates from DUMPED -> USB_LOADING
|
||||
--so end result is buff0 will get sent off to dump extra data that's not needed
|
||||
--but we never call payload on it, so buff1 never moves from USB_UNLOADING
|
||||
--but it has to be done unloading if we sent a subsequent setup packet
|
||||
--buffers.status_wait({buff0, buff1}, {"DUMPED","USB_UNLOADING"})
|
||||
--in reality I don't think this wait is needed. Because we've already gotten our data if
|
||||
--we're at this point..
|
||||
--what we really need to do is set the buffer's status' to a reset state
|
||||
--that way we can give them new instructions before restarting DUMP of CHR portion
|
||||
--best way can think of doing this is a operation "RESET" which updates buffer status,
|
||||
--without deallocating them. In reality should be able to do this by setting operation to reset.
|
||||
--and having STARTDUMP/FLASH initialize buffer status' as well.
|
||||
dict.operation("SET_OPERATION", op_buffer["RESET"] )
|
||||
dict.buffer("RAW_BUFFER_RESET")
|
||||
|
||||
--close file in main
|
||||
--reset io at end
|
||||
dict.operation("SET_OPERATION", op_buffer["RESET"] )
|
||||
dict.buffer("RAW_BUFFER_RESET")
|
||||
dict.io("IO_RESET")
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
-- global variables so other modules can use them
|
||||
|
||||
|
||||
|
|
@ -240,6 +342,7 @@ end
|
|||
|
||||
-- functions other modules are able to call
|
||||
dump.dump_nes = dump_nes
|
||||
dump.dump_snes = dump_snes
|
||||
|
||||
-- return the module's table
|
||||
return dump
|
||||
|
|
|
|||
|
|
@ -0,0 +1,106 @@
|
|||
|
||||
-- create the module's table
|
||||
local snes = {}
|
||||
|
||||
-- import required modules
|
||||
local dict = require "scripts.app.dict"
|
||||
|
||||
-- file constants
|
||||
local RESET_VECT_HI = 0xFFFD
|
||||
local RESET_VECT_LO = 0xFFFC
|
||||
|
||||
-- local functions
|
||||
|
||||
-- Desc:read reset vector from passed in bank
|
||||
-- Pre: snes_init() been called to setup i/o
|
||||
-- Post:Address left on bus memories disabled
|
||||
-- Rtn: reset vector that was found
|
||||
local function read_reset_vector( bank, debug )
|
||||
|
||||
--ensure cart is in play mode
|
||||
dict.pinport("CTL_SET_HI", "SNES_RST")
|
||||
|
||||
--first set SNES bank A16-23
|
||||
dict.snes("SNES_SET_BANK", bank)
|
||||
|
||||
--read reset vector high byte
|
||||
vector = dict.snes("SNES_ROM_RD", RESET_VECT_HI)
|
||||
--shift high byte of vector to where it belongs
|
||||
vector = vector << 8
|
||||
--read low byte of vector
|
||||
vector = vector | dict.snes("SNES_ROM_RD", RESET_VECT_LO)
|
||||
|
||||
if debug then print("SNES bank:", bank, "reset vector", string.format("$%x", vector) ) end
|
||||
|
||||
return vector
|
||||
end
|
||||
|
||||
-- Desc: attempt to read flash rom ID
|
||||
-- Pre: snes_init() been called to setup i/o
|
||||
-- Post:Address left on bus memories disabled
|
||||
-- Rtn: true if flash ID found
|
||||
local function read_flashID( debug )
|
||||
|
||||
local rv
|
||||
--enter software mode A11 is highest address bit that needs to be valid
|
||||
--datasheet not exactly explicit, A11 might not need to be valid
|
||||
--part has A-1 (negative 1) since it's in byte mode, meaning the part's A11 is actually A12
|
||||
--WR $AAA:AA $555:55 $AAA:AA
|
||||
dict.snes("SNES_SET_BANK", 0x00)
|
||||
|
||||
--put cart in program mode
|
||||
dict.pinport("CTL_SET_LO", "SNES_RST")
|
||||
|
||||
dict.snes("SNES_ROM_WR", 0x0AAA, 0xAA)
|
||||
dict.snes("SNES_ROM_WR", 0x0555, 0x55)
|
||||
dict.snes("SNES_ROM_WR", 0x0AAA, 0x90)
|
||||
--read manf ID
|
||||
rv = dict.snes("SNES_ROM_RD", 0x0000)
|
||||
if debug then print("attempted read SNES ROM manf ID:", string.format("%X", rv)) end
|
||||
-- if ( rv[RV_DATA0_IDX] != SST_MANF_ID ) {
|
||||
-- return GEN_FAIL;
|
||||
-- //no need for software exit since failed to enter
|
||||
-- }
|
||||
--
|
||||
--read prod ID
|
||||
rv = dict.snes("SNES_ROM_RD", 0x0002)
|
||||
if debug then print("attempted read SNES ROM prod ID:", string.format("%X", rv)) end
|
||||
rv = dict.snes("SNES_ROM_RD", 0x001C)
|
||||
if debug then print("attempted read SNES density ID: ", string.format("%X", rv)) end
|
||||
rv = dict.snes("SNES_ROM_RD", 0x001E)
|
||||
if debug then print("attempted read SNES boot sect ID:", string.format("%X", rv)) end
|
||||
-- if ( (rv[RV_DATA0_IDX] == SST_PROD_128)
|
||||
-- || (rv[RV_DATA0_IDX] == SST_PROD_256)
|
||||
-- || (rv[RV_DATA0_IDX] == SST_PROD_512) ) {
|
||||
-- //found expected manf and prod ID
|
||||
-- flash->manf = SST_MANF_ID;
|
||||
-- flash->part = rv[RV_DATA0_IDX];
|
||||
-- flash->wr_dict = DICT_NES;
|
||||
-- flash->wr_opcode = NES_PPU_WR;
|
||||
-- }
|
||||
--
|
||||
--exit software
|
||||
-- dict.nes("NES_PPU_WR", 0x0000, 0xF0)
|
||||
dict.snes("SNES_ROM_WR", 0x0000, 0xF0)
|
||||
--
|
||||
|
||||
--exit program mode
|
||||
dict.pinport("CTL_SET_HI", "SNES_RST")
|
||||
|
||||
--return true
|
||||
|
||||
end
|
||||
|
||||
-- global variables so other modules can use them
|
||||
|
||||
|
||||
-- call functions desired to run when script is called/imported
|
||||
|
||||
|
||||
-- functions other modules are able to call
|
||||
snes.read_reset_vector = read_reset_vector
|
||||
snes.read_flashID = read_flashID
|
||||
|
||||
-- return the module's table
|
||||
return snes
|
||||
|
||||
|
|
@ -155,6 +155,10 @@
|
|||
//operand LSB mapper variant
|
||||
#define NOVAR 0
|
||||
|
||||
|
||||
#define LOROM 0
|
||||
#define HIROM 1
|
||||
|
||||
//set function
|
||||
//miscdata: buffer number
|
||||
//operMSB: (might be needed if this is a ponter..?) or might need more than one function def..
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@
|
|||
// PC8 "EXP0" NES EXP0, cart-console /RESET
|
||||
#define C8_ 8
|
||||
#define EXP0_ 8
|
||||
#define SNES_RST_ 8
|
||||
// PC9 "LED" kazzos tied this to NES EXP9, INL6 connects to CIC CLK
|
||||
#define C9_ 9
|
||||
#define LED_ 9
|
||||
|
|
@ -169,5 +170,13 @@
|
|||
#define EXP_DISABLE_ 19
|
||||
#define EXP_SET_ 20
|
||||
|
||||
//============================
|
||||
//HIGH ADDR PORT 8bit WIDE ACCESS
|
||||
//opcode: type of operation
|
||||
//operand: value to place on bus
|
||||
//============================
|
||||
#define HADDR_ENABLE_ 21
|
||||
#define HADDR_DISABLE_ 22
|
||||
#define HADDR_SET_ 23
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -17,80 +17,18 @@
|
|||
//=============================================================================================
|
||||
|
||||
|
||||
// OPCODES with no operand and no return value besides SUCCESS/ERROR_CODE
|
||||
//set A16-23 aka bank number
|
||||
#define SNES_SET_BANK 0x00
|
||||
|
||||
//read from current bank at provided address
|
||||
//SNES reset is unaffected
|
||||
#define SNES_ROM_RD 0x01 //RL=3
|
||||
|
||||
//write from current bank at provided address
|
||||
//SNES reset is unaffected
|
||||
#define SNES_ROM_WR 0x02
|
||||
|
||||
|
||||
//=============================================================================================
|
||||
// OPCODES WITH OPERAND and no return value besides SUCCESS/ERROR_CODE
|
||||
//=============================================================================================
|
||||
// Detect this opcode/operand setup with opcode between the following defines:
|
||||
#define SNES_OPCODE_24BOP_MIN 0x00
|
||||
#define SNES_OPCODE_24BOP_MAX 0x7F
|
||||
//
|
||||
//=============================================================================================
|
||||
//=============================================================================================
|
||||
|
||||
|
||||
//SNES has 24bit address bus which is max operands we can send
|
||||
//So have to get a little creative for writing to 24bit address
|
||||
//prob easiest to just keep last latched value of A23-16
|
||||
|
||||
//write to SNES in program mode (/RESET low)
|
||||
//only can send A15-A0
|
||||
//A23-16 are last latched values
|
||||
//SNES /ROMSEL always goes low
|
||||
//program writes don't allow access to SRAM
|
||||
//program access aligns ROM linearly and is independent of Hi/Lo switch
|
||||
#define SNES_A15_A0_PRGM_WR 0x00
|
||||
|
||||
//write to SNES in play mode (/RESET high)
|
||||
//only can send A15-A0
|
||||
//A23-16 are last latched values
|
||||
//SNES /ROMSEL always goes low
|
||||
//play writes allow access to SRAM
|
||||
//program access aligns ROM based on position of Hi/Lo switch
|
||||
#define SNES_A15_A0_PLAY_WR 0x01
|
||||
|
||||
//write to SNES in play mode (/RESET high)
|
||||
//only can send A15-A0
|
||||
//A23-16 are last latched values
|
||||
//SNES /ROMSEL not affected
|
||||
//play writes allow access to SRAM
|
||||
//program access aligns ROM based on position of Hi/Lo switch
|
||||
#define SNES_A15_A0_NO_ROMSEL_PLAY_WR 0x02
|
||||
|
||||
//=============================================================================================
|
||||
// OPCODES WITH OPERAND 8bit RETURN VALUE plus SUCCESS/ERROR_CODE
|
||||
//=============================================================================================
|
||||
// Detect this opcode/operand setup with opcode between the following defines:
|
||||
#define SNES_OPCODE_24BOP_8BRV_MIN 0x80
|
||||
#define SNES_OPCODE_24BOP_8BRV_MAX 0xFF
|
||||
//
|
||||
//=============================================================================================
|
||||
//=============================================================================================
|
||||
|
||||
//can supply entire 24bit address
|
||||
|
||||
//write to SNES in program mode (/RESET low)
|
||||
//SNES /ROMSEL always goes low
|
||||
//program reads don't allow access to SRAM
|
||||
//program access aligns ROM linearly and is independent of Hi/Lo switch
|
||||
#define SNES_PRGM_RD 0x80
|
||||
|
||||
//write to SNES in play mode (/RESET high)
|
||||
//SNES /ROMSEL always goes low
|
||||
//play reads allow access to SRAM
|
||||
//program access aligns ROM based on position of Hi/Lo switch
|
||||
#define SNES_PLAY_RD 0x81
|
||||
|
||||
//write to SNES in play mode (/RESET high)
|
||||
//SNES /ROMSEL not active
|
||||
//play reads allow access to SRAM
|
||||
//program access aligns ROM based on position of Hi/Lo switch
|
||||
#define SNES_NO_ROMSEL_PLAY_RD 0x82
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -65,8 +65,8 @@
|
|||
|
||||
//=============================================================================================
|
||||
//=============================================================================================
|
||||
//#define DICT_SNES 4
|
||||
//#include "shared_dict_snes.h"
|
||||
#define DICT_SNES 4
|
||||
#include "shared_dict_snes.h"
|
||||
//snes dictionary contains commands
|
||||
//These commands rely on io initialization from io dictionary prior to calling
|
||||
//This library is intended to contain all SNES related opcodes/commands
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@
|
|||
//
|
||||
////reserved libusb erro 165
|
||||
//
|
||||
//#define ERR_UNKN_SNES_OPCODE 170
|
||||
//
|
||||
#define ERR_UNKN_SNES_OPCODE 170
|
||||
|
||||
#define ERR_UNKN_BUFF_OPCODE 180
|
||||
#define ERR_BUFN_DOES_NOT_EXIST 181
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue