test
Dependencies: SDFileSystem mbed-dev
Fork of Nucleo_Ex06_EMU by
pNesX_System_Nucleo.cpp
- Committer:
- charliex
- Date:
- 2017-05-27
- Revision:
- 4:53ef91c87d74
File content as of revision 4:53ef91c87d74:
/*===================================================================*/ /* */ /* pNesX_System_Nucleo.cpp : The function which depends on a system */ /* (for Nucleo F446RE) */ /* */ /* 2016/1/20 Racoon */ /* */ /*===================================================================*/ #define USE_CAN (1) /*-------------------------------------------------------------------*/ /* Include files */ /*-------------------------------------------------------------------*/ #include "mbed.h" #include "SDFileSystem.h" #include "tft.h" //#include "SWO.h" // added in for SD check int get_filelist ( char *path ); // logo ptrs extern const unsigned char l1_Logo[]; extern const unsigned char asg_logo[]; extern const unsigned char adaptable_conn_logo[]; extern const unsigned char hacker_stickers_logo[]; extern const unsigned char nostarch_logo[]; extern const unsigned char nslmini[]; extern const unsigned char PRO_LG_K_500x200_1CRevGrey_noDSCR[]; extern const unsigned char securitysnobs[]; extern const unsigned char supplyFrame[]; extern const unsigned char WallOfSheep_logo_200px[]; extern const unsigned char tinder_logo[]; // ID that game pad data is sent on #define CAN_SEND_ID (0x7e1) // ID that game pad data is received from #define CAN_RECV_ID (0x7e0) // Memory interface enum { CAN_READ_BYTE = CAN_SEND_ID + 1, CAN_READ_WORD, CAN_READ_DWORD, CAN_WRITE_BYTE, CAN_WRITE_WORD, CAN_WRITE_DWORD }; #ifdef USE_CAN CAN can1 ( PB_8, PB_9 ); //not usng second CAN yet., //CAN can2(PB_5, PB_6); #endif //#define ORIGINAL_GAMEPAD //#define PS_GAMEPAD #define NES_GAMEPAD #if !defined(PS_GAMEPAD) #include "USBHostGamepad.h" USBHostGamepad *pad; #else #include "pspad.h" #endif #include "pNesX.h" #include "pNesX_System.h" extern int pNesX_Filer(); extern void ApuMute ( bool mute ); // temporary store for joystick value static DWORD canval2; #ifdef USE_CAN // if there is a CAN msg available to read from static bool msgAvailable = false; #endif SDFileSystem *sd; //(PB_15, PB_14, PB_13, PA_9, "sd", NC, SDFileSystem::SWITCH_NONE, 20000000); DigitalIn SW1 ( PC_13 ); DigitalIn SW2 ( PC_14 ); DigitalOut bLED1 ( PB_12 ) ; DigitalOut bLED2 ( PB_13 ) ; extern WORD LineData[][256]; extern WORD *pDrawData; //#define SHOW_FPS #if defined(SHOW_FPS) Timer timer; int fps = 0; int dmawait; #endif //SWO_Channel swo; /*-------------------------------------------------------------------*/ /* ROM image file information */ /*-------------------------------------------------------------------*/ extern char szRomFolder[]; extern char szRomFilename[]; extern char szRomPath[]; char szRomName[ 256 ]; int nSRAM_SaveFlag; // Palette data const WORD NesPalette[ 64 ] = { 0xef7b, 0x1f00, 0x1700, 0x5741, 0x1090, 0x04a8, 0x80a8, 0xa088, 0x8051, 0xc003, 0x4003, 0xc002, 0x0b02, 0x0000, 0x0000, 0x0000, 0xf7bd, 0xdf03, 0xdf02, 0x3f6a, 0x19d8, 0x0be0, 0xc0f9, 0xe2e2, 0xe0ab, 0xc005, 0x4005, 0x4805, 0x5104, 0x0000, 0x0000, 0x0000, 0xdfff, 0xff3d, 0x5f6c, 0xdf9b, 0xdffb, 0xd3fa, 0xcbfb, 0x08fd, 0xc0fd, 0xc3bf, 0xca5e, 0xd35f, 0x5b07, 0xcf7b, 0x0000, 0x0000, 0xffff, 0x3fa7, 0xdfbd, 0xdfdd, 0xdffd, 0x38fd, 0x96f6, 0x15ff, 0xcffe, 0xcfdf, 0xd7bf, 0xdbbf, 0xff07, 0xdffe, 0x0000, 0x0000 }; /*-------------------------------------------------------------------*/ /* Function prototypes */ /*-------------------------------------------------------------------*/ int LoadSRAM(); int SaveSRAM(); /*===================================================================*/ /* */ /* LoadSRAM() : Load a SRAM */ /* */ /*===================================================================*/ int LoadSRAM() { /* * Load a SRAM * * Return values * 0 : Normally * -1 : SRAM data couldn't be read */ return 0; } /*===================================================================*/ /* */ /* SaveSRAM() : Save a SRAM */ /* */ /*===================================================================*/ int SaveSRAM() { /* * Save a SRAM * * Return values * 0 : Normally * -1 : SRAM data couldn't be written */ // Successful return 0; } /*===================================================================*/ /* */ /* pNesX_Menu() : Menu screen */ /* */ /*===================================================================*/ int pNesX_Menu() { /* * Menu screen * * Return values * 0 : Normally * -1 : Exit pNesX */ #if defined(SHOW_FPS) timer.stop(); #endif ApuMute ( true ); switch ( pNesX_Filer() ) { case 0: // Selected a file if ( pNesX_Load ( szRomPath ) == 0 ) { // Set a ROM image name strcpy ( szRomName, szRomFilename ); // Load SRAM LoadSRAM(); } break; case 1: // Return to Emu break; case 2: // Reset if ( szRomName[ 0 ] != 0 ) { // Reset pNesX pNesX_Reset(); } break; case -1: // Error //printf ( "Filer Error\r\n" ); while ( 1 ); } tft_clear ( TFT_BLACK ); tft_set_window ( 32, 8, NES_DISP_WIDTH + 32 - 1, NES_DISP_HEIGHT + 8 - 1 ); ApuMute ( false ); #if defined(SHOW_FPS) timer.start(); #endif return 0; } /*===================================================================*/ /* */ /* pNesX_ReadRom() : Read ROM image file */ /* */ /*===================================================================*/ int pNesX_ReadRom ( const char *pszFileName ) { /* * Read ROM image file * * Parameters * const char *pszFileName (Read) * * Return values * 0 : Normally * -1 : Error */ FileHandle* file; /* Open ROM file */ file = sd->open ( pszFileName, O_RDONLY ); if ( file == NULL ) { //printf ( "open error\r\n" ); return -1; } /* Read ROM Header */ file->read ( &NesHeader, sizeof NesHeader ); if ( memcmp ( NesHeader.byID, "NES\x1a", 4 ) != 0 ) { /* not .nes file */ file->close(); return -1; } /* Clear SRAM */ memset ( SRAM, 0, SRAM_SIZE ); /* If trainer presents Read Triner at 0x7000-0x71ff */ if ( NesHeader.byInfo1 & 4 ) { //printf ( "Read Trainer\r\n" ); file->read ( &SRAM[ 0x1000 ], 512 ); } //printf ( "RomSize: %d\r\n", NesHeader.byRomSize ); /* Allocate Memory for ROM Image */ ROM = ( BYTE * ) malloc ( NesHeader.byRomSize * 0x4000 ); //printf ( "ROM addr:%x\r\n", ROM ); /* Read ROM Image */ file->read ( ROM, 0x4000 * NesHeader.byRomSize ); if ( NesHeader.byVRomSize > 0 ) { /* Allocate Memory for VROM Image */ VROM = ( BYTE * ) malloc ( NesHeader.byVRomSize * 0x2000 ); //printf ( "VROM addr:%x\r\n", VROM ); /* Read VROM Image */ file->read ( VROM, 0x2000 * NesHeader.byVRomSize ); } /* File close */ file->close(); /* Successful */ return 0; } /*===================================================================*/ /* */ /* pNesX_ReleaseRom() : Release a memory for ROM */ /* */ /*===================================================================*/ void pNesX_ReleaseRom() { /* * Release a memory for ROM * */ if ( ROM ) { free ( ROM ); ROM = NULL; } if ( VROM ) { free ( VROM ); VROM = NULL; } } /*===================================================================*/ /* */ /* pNesX_LoadFrame() : */ /* Transfer the contents of work frame on the screen */ /* */ /*===================================================================*/ void pNesX_LoadFrame() { /* * Transfer the contents of work frame on the screen * */ #if defined(SHOW_FPS) fps++; if ( timer.read_ms() >= 1000 ) { timer.stop(); //printf ( "%d %d %d\r\n", fps, timer.read_ms(), dmawait ); fps = 0; timer.reset(); timer.start(); } dmawait = 0; #endif } void pNesX_TransmitLinedata() { while ( SpiHandle.State != HAL_SPI_STATE_READY ) { #if defined(SHOW_FPS) dmawait++; #endif } HAL_SPI_Transmit_DMA ( &SpiHandle, ( uint8_t * ) pDrawData, 256 * 2 ); } #if defined(ORIGINAL_GAMEPAD) const BYTE UsbPadTable[] = {0x10, 0x90, 0x80, 0xa0, 0x20, 0x60, 0x40, 0x50}; #endif /*===================================================================*/ /* */ /* pNesX_PadState() : Get a joypad state */ /* */ /*===================================================================*/ void pNesX_PadState ( DWORD *pdwPad1, DWORD *pdwPad2, DWORD *pdwSystem ) { /* * Get a joypad state * * Parameters * DWORD *pdwPad1 (Write) * Joypad 1 State R L D U St Se B A * * DWORD *pdwPad2 (Write) * Joypad 2 State * * DWORD *pdwSystem (Write) * Input for pNesX * */ #if defined(ORIGINAL_GAMEPAD) *pdwPad1 = ( ( pad->report[4] & 0x20 ) >> 5 ) | ( ( pad->report[4] & 0x10 ) >> 3 ) | ( ( pad->report[5] & 0x30 ) >> 2 ); if ( ! ( pad->report[4] & 8 ) ) { *pdwPad1 |= UsbPadTable[pad->report[4] & 7]; } *pdwPad1 = *pdwPad1 | ( *pdwPad1 << 8 ); *pdwPad2 = 0; *pdwSystem = ( ( pad->report[5] & 0x4 ) >> 2 ) | ( ( ( pad->report[5] & 0xa ) == 0xa ) << 1 ); USBHost::poll(); #elif defined(NES_GAMEPAD) *pdwSystem = 0 ; *pdwPad1 = 0 ; /* 01 02 03 04 05 06 07 08 ----------------------- 01 80 80 7f 7f 0f 00 00 LEFT 00 RIGHT FF UP 00 DOWN FF SELECT 10 START 20 B 1F A 2F */ if ( pad->report[3] == 0x00 ) {*pdwPad1 |= KEYPAD_LEFT; *pdwSystem ^= PAD_SYS_LEFT;} if ( pad->report[3] == 0xFF ) {*pdwPad1 |= KEYPAD_RIGHT; *pdwSystem ^= PAD_SYS_RIGHT;} if ( pad->report[4] == 0x00 ) {*pdwPad1 |= KEYPAD_UP; *pdwSystem ^= PAD_SYS_UP;} if ( pad->report[4] == 0xFF ) {*pdwPad1 |= KEYPAD_DOWN; *pdwSystem ^= PAD_SYS_DOWN;} if ( pad->report[6] & 0x10 ) {*pdwPad1 |= KEYPAD_SELECT;} if ( pad->report[6] & 0x20 ) {*pdwPad1 |= KEYPAD_START;} if ( pad->report[5] & 0x10 ) {*pdwPad1 |= KEYPAD_B;} if ( pad->report[5] & 0x20 ) {*pdwPad1 |= KEYPAD_A;} if ( pad->report[6] == 0x30 ) { *pdwSystem = PAD_SYS_QUIT; } #ifdef USE_CAN { static DWORD lastpad; if ( *pdwPad1 != lastpad ) { can1.write ( CANMessage ( CAN_SEND_ID, ( char* ) pdwPad1, 4 ) ); lastpad = *pdwPad1; } } if ( msgAvailable ) { *pdwPad2 = canval2; } else #endif { // network ? *pdwPad2 = 0; } USBHost::poll(); #else unsigned short pad1, pad2; pspad_read ( &pad1, &pad2 ); // R L D U St Se B A // SE -- -- ST U R D L L2 R2 L1 R1 TR O X SQ *pdwPad1 = ( ( pad1 & 0x0400 ) >> 3 ) | ( ( pad1 & 0x0100 ) >> 2 ) | ( ( pad1 & 0x0200 ) >> 4 ) | ( ( pad1 & 0x0800 ) >> 7 ) | ( ( pad1 & 0x1000 ) >> 9 ) | ( ( pad1 & 0x8000 ) >> 13 ) | ( ( pad1 & 1 ) << 1 ) | ( ( pad1 & 2 ) >> 1 ); *pdwPad1 = *pdwPad1 | ( *pdwPad1 << 8 ); *pdwPad2 = 0; *pdwSystem = ( ( pad1 & 0x80 ) >> 7 ) | ( ( ( pad1 & 0x50 ) == 0x50 ) << 1 ); #endif } /*===================================================================*/ /* */ /* pNesX_MemoryCopy() : memcpy */ /* */ /*===================================================================*/ void *pNesX_MemoryCopy ( void *dest, const void *src, int count ) { /* * memcpy * * Parameters * void *dest (Write) * Points to the starting address of the copied block to destination * * const void *src (Read) * Points to the starting address of the block of memory to copy * * int count (Read) * Specifies the size, in bytes, of the block of memory to copy * * Return values * Pointer of destination */ memcpy ( dest, src, count ); return dest; } /*===================================================================*/ /* */ /* pNesX_MemorySet() : */ /* */ /*===================================================================*/ void *pNesX_MemorySet ( void *dest, int c, int count ) { /* * memset * * Parameters * void *dest (Write) * Points to the starting address of the block of memory to fill * * int c (Read) * Specifies the byte value with which to fill the memory block * * int count (Read) * Specifies the size, in bytes, of the block of memory to fill * * Return values * Pointer of destination */ memset ( dest, c, count ); return dest; } /*===================================================================*/ /* */ /* DebugPrint() : Print debug message */ /* */ /*===================================================================*/ void pNesX_DebugPrint ( char *pszMsg ) { } #ifdef USE_CAN /** * @brief 'CAN receive-complete' interrup handler. * @note Called on arrival of new CAN message. * Keep it as short as possible. * @param * @retval */ void onMsgReceived() { CANMessage msg; // address to read/wrte WORD address; // default to SRAM uint8_t *bank_ptr = &RAM[0]; uint8_t bank = 0; memset ( &msg, 0, sizeof ( msg ) ); if ( can1.read ( msg ) ) { // less code address = ( ( WORD ) msg.data[0] << 8 + ( WORD ) msg.data[1] ); // RAM,SRAM,ROM,ROMBANK0/1/2/3,PPURAM,VROM,PPUBANK bank = msg.data[2]; // decide which bank switch ( bank ) { case 0: //RAM break; case 1: bank_ptr = &SRAM[0]; break; case 2: bank_ptr = ROM; break; case 3: bank_ptr = &PPURAM[0]; break; case 4: bank_ptr = VROM; break; case 5: bank_ptr = ( uint8_t* ) &PPUBANK[0]; break; case 6: bank_ptr = ( uint8_t* ) &SPRRAM[0]; break; } switch ( msg.id ) { case CAN_RECV_ID : /// so far only mark it as available when its a gamepad message.. msgAvailable = true; //memcpy(&canval2,(char*)&msg.data[0],4); canval2 = ( unsigned long ) ( msg.data[3] << 24 ) + ( ( unsigned long ) msg.data[2] << 16 ) + ( ( unsigned long ) msg.data[1] << 8 ) + ( ( unsigned long ) msg.data[0] ); break; case CAN_READ_BYTE: break; case CAN_READ_WORD: break; case CAN_READ_DWORD: break; case CAN_WRITE_BYTE: break; case CAN_WRITE_WORD: break; case CAN_WRITE_DWORD: break; } } } #endif const unsigned char * const logoPtrs[] = { l1_Logo, //platinum tinder_logo, supplyFrame, asg_logo, nslmini, //gold securitysnobs, //silver PRO_LG_K_500x200_1CRevGrey_noDSCR, adaptable_conn_logo, WallOfSheep_logo_200px, hacker_stickers_logo, nostarch_logo }; void draw_logos ( void ) { static unsigned char counter = 0; unsigned short w; unsigned char h; const unsigned char *p; for ( float b = 1 ; b > 0 ; b -= 0.05f ) { backlight ( b ); HAL_Delay ( 20 ); } backlight ( 0 ); tft_clear ( TFT_BLACK ); p = logoPtrs[counter]; w = ( unsigned short ) ( p[18] ) + ( ( unsigned short ) p[19] << 8 ); h = p[22]; draw_bmp_4bpp ( p, ( TFT_WIDTH / 2 ) - ( w / 2 ), ( ( TFT_HEIGHT / 2 ) - ( h / 2 ) ) ); for ( float b = 0 ; b < 1 ; b += 0.05f ) { backlight ( b ); HAL_Delay ( 20 ); } HAL_Delay ( 1000 ); counter++ ; if ( counter >= sizeof ( logoPtrs ) / sizeof ( unsigned char * ) ) { counter = 0; } } /*===================================================================*/ /* */ /* pNesX Initialise */ /* */ /*===================================================================*/ int main() { const unsigned char *p ; bLED1 = 0; bLED2 = 0; #ifdef USE_CAN // can1.reset(); can1.frequency ( 1000000 ); can1.attach ( &onMsgReceived ); // attach 'CAN receive-complete' interrupt handler #endif // TFT initialize tft_init(); tft_set_window ( 32, 8, NES_DISP_WIDTH + 32 - 1, NES_DISP_HEIGHT + 8 - 1 ); // SD_CS = PB_2 // SD_SCK = PB_10 // SD_MISO = PC_2 // SD_MOSI = PC_3 if ( sd == NULL ) { // SD card Initialize bLED2 = 1; sd = new SDFileSystem ( PC_3, PC_2, PB_10, PB_2, "sd", NC, SDFileSystem::SWITCH_NONE, 20000000 ); sd->crc ( true ); sd->large_frames ( true ); sd->write_validation ( true ); strcpy ( szRomFolder, "/sd" ); } for ( ;; ) { draw_logos(); if ( get_filelist ( "/sd" ) ) { break; } } #if !defined(PS_GAMEPAD) tft_clear ( TFT_RED + TFT_BLUE ); // USB Gamepad Initialize` pad = new USBHostGamepad(); pad->connect(); #else pspad_init(); #endif // Apu Initialize ApuInit(); /*-------------------------------------------------------------------*/ /* Start pNesX */ /*-------------------------------------------------------------------*/ bLED2 = 1; bLED1 = 1; pNesX_Main(); }