test

Dependencies:   SDFileSystem mbed-dev

Fork of Nucleo_Ex06_EMU by woodstock .

pNesX_System_Nucleo.cpp

Committer:
beaglescout007
Date:
2016-04-03
Revision:
0:3dac1f1bc9e0

File content as of revision 0:3dac1f1bc9e0:

/*===================================================================*/
/*                                                                   */
/*  pNesX_System_Nucleo.cpp : The function which depends on a system */
/*                         (for Nucleo F446RE)                       */
/*                                                                   */
/*  2016/1/20  Racoon                                                */
/*                                                                   */
/*===================================================================*/

/*-------------------------------------------------------------------*/
/*  Include files                                                    */
/*-------------------------------------------------------------------*/

#include "mbed.h"
#include "SDFileSystem.h"
#include "tft.h"

//#define PS_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);

SDFileSystem *sd; //(PB_15, PB_14, PB_13, PA_9, "sd", NC, SDFileSystem::SWITCH_NONE, 20000000);

DigitalIn userbutton(USER_BUTTON);

extern WORD LineData[][256];
extern WORD *pDrawData;

//#define SHOW_FPS

#if defined(SHOW_FPS)
Timer timer;
int fps = 0;
int dmawait;
#endif

/*-------------------------------------------------------------------*/
/*  ROM image file information                                       */
/*-------------------------------------------------------------------*/

extern char szRomFolder[];
extern char szRomFilename[];
extern char szRomPath[];
    
char szRomName[ 256 ];
char szSaveName[ 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(PS_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(PS_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();
#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 )
{
}

/*===================================================================*/
/*                                                                   */
/*                pNesX Initialise                                   */
/*                                                                   */
/*===================================================================*/
int main()
{
    // TFT initialize    
    tft_init();
    tft_clear(TFT_BLACK);
    tft_set_window(32, 8, NES_DISP_WIDTH + 32 - 1, NES_DISP_HEIGHT + 8 - 1);
        
    // SD card Initialize
    sd = new SDFileSystem(PB_15, PB_14, PB_13, PA_9, "sd", NC, SDFileSystem::SWITCH_NONE, 20000000);
    sd->crc(true);
    sd->large_frames(true);
    sd->write_validation(true);

    strcpy(szRomFolder, "/sd");

#if !defined(PS_GAMEPAD)
    // USB Gmaepad Initialize
    pad = new USBHostGamepad();
    pad->connect();
#else
    pspad_init();
#endif

    // Apu Initialize
    ApuInit();
    
    /*-------------------------------------------------------------------*/
    /*  Start pNesX                                                      */
    /*-------------------------------------------------------------------*/

    pNesX_Main();    
}