2025-07-10 11:30:57 +08:00
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֲ<EFBFBD><D6B2><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ye781205<30><35>NESģ<53><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
// ALIENTEK STM32F407<30><37><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
// NES<45><53><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
|
|
|
|
|
// <20><><EFBFBD><EFBFBD>ԭ<EFBFBD><D4AD>@ALIENTEK
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>̳:www.openedv.com
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:2014/7/1
|
|
|
|
|
// <20>汾<EFBFBD><E6B1BE>V1.0
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
#include "nes_main.h"
|
|
|
|
|
#include "dac.h"
|
2025-06-27 00:32:57 +08:00
|
|
|
|
#include "main.h"
|
|
|
|
|
#include "mymem.h"
|
2025-07-10 11:30:57 +08:00
|
|
|
|
#include "nes_apu.h"
|
|
|
|
|
#include "nes_mapper.h"
|
|
|
|
|
#include "nes_ppu.h"
|
|
|
|
|
#include "stm32f4xx.h"
|
2025-06-27 00:32:57 +08:00
|
|
|
|
|
|
|
|
|
#include "ff.h"
|
|
|
|
|
#include "string.h"
|
|
|
|
|
|
2025-07-10 11:30:57 +08:00
|
|
|
|
uint8_t nes_frame_cnt; // nes֡<73><D6A1><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
int MapperNo; // map<61><70><EFBFBD><EFBFBD>
|
|
|
|
|
int NES_scanline; // nesɨ<73><C9A8><EFBFBD><EFBFBD>
|
2025-06-27 00:32:57 +08:00
|
|
|
|
int VROM_1K_SIZE;
|
|
|
|
|
int VROM_8K_SIZE;
|
|
|
|
|
|
2025-07-10 11:30:57 +08:00
|
|
|
|
uint8_t PADdata; // <20>ֱ<EFBFBD>1<EFBFBD><31>ֵ [7:0]<5D><>7 <20><>6 <20><>5 <20><>4 Start3 Select2 B1 A0
|
|
|
|
|
uint8_t PADdata1; // <20>ֱ<EFBFBD>2<EFBFBD><32>ֵ [7:0]<5D><>7 <20><>6 <20><>5 <20><>4 Start3 Select2 B1 A0
|
|
|
|
|
uint8_t *NES_RAM; // <20><><EFBFBD><EFBFBD>1024<32>ֽڶ<D6BD><DAB6><EFBFBD>
|
|
|
|
|
uint8_t *NES_SRAM;
|
|
|
|
|
NES_header *RomHeader; // rom<6F>ļ<EFBFBD>ͷ
|
|
|
|
|
MAPPER *NES_Mapper;
|
|
|
|
|
MapperCommRes *MAPx;
|
|
|
|
|
|
|
|
|
|
uint8_t *spr_ram; // <20><><EFBFBD><EFBFBD>RAM,256<35>ֽ<EFBFBD>
|
|
|
|
|
ppu_data *ppu; // ppuָ<75><D6B8>
|
|
|
|
|
uint8_t *VROM_banks;
|
|
|
|
|
uint8_t *VROM_tiles;
|
|
|
|
|
|
|
|
|
|
apu_t *apu; // apuָ<75><D6B8>
|
|
|
|
|
uint16_t *wave_buffers;
|
|
|
|
|
uint16_t *i2sbuf1; // <20><>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD>֡,ռ<><D5BC><EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD> 367*4 <20>ֽ<EFBFBD>@22050Hz
|
|
|
|
|
uint16_t *i2sbuf2; // <20><>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD>֡,ռ<><D5BC><EFBFBD>ڴ<EFBFBD><DAB4><EFBFBD> 367*4 <20>ֽ<EFBFBD>@22050Hz
|
|
|
|
|
|
|
|
|
|
uint8_t *romfile; // nes<65>ļ<EFBFBD>ָ<EFBFBD><D6B8>,ָ<><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>nes<65>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><CABC>ַ.
|
2025-06-27 00:32:57 +08:00
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2025-07-10 11:30:57 +08:00
|
|
|
|
// <20><>¼nes<65>Ƿ<EFBFBD><C7B7><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>
|
|
|
|
|
static uint8_t g_nes_break = 0;
|
|
|
|
|
|
|
|
|
|
// <20><><EFBFBD><EFBFBD>ROM
|
|
|
|
|
// <20><><EFBFBD><EFBFBD>ֵ:0,<2C>ɹ<EFBFBD>
|
|
|
|
|
// 1,<2C>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
// 3,map<61><70><EFBFBD><EFBFBD>
|
|
|
|
|
uint8_t nes_load_rom(void) {
|
|
|
|
|
uint8_t *p;
|
|
|
|
|
uint8_t i;
|
|
|
|
|
uint8_t res = 0;
|
|
|
|
|
p = (uint8_t *)romfile;
|
|
|
|
|
if (strncmp((char *)p, "NES", 3) == 0) {
|
|
|
|
|
RomHeader->ctrl_z = p[3];
|
|
|
|
|
RomHeader->num_16k_rom_banks = p[4];
|
|
|
|
|
RomHeader->num_8k_vrom_banks = p[5];
|
|
|
|
|
RomHeader->flags_1 = p[6];
|
|
|
|
|
RomHeader->flags_2 = p[7];
|
|
|
|
|
if (RomHeader->flags_1 & 0x04)
|
|
|
|
|
p += 512; // <20><>512<31>ֽڵ<D6BD>trainer:
|
|
|
|
|
if (RomHeader->num_8k_vrom_banks > 0) // <20><><EFBFBD><EFBFBD>VROM,<2C><><EFBFBD><EFBFBD>Ԥ<EFBFBD><D4A4><EFBFBD><EFBFBD>
|
|
|
|
|
{
|
|
|
|
|
VROM_banks = p + 16 + (RomHeader->num_16k_rom_banks * 0x4000);
|
|
|
|
|
#if NES_RAM_SPEED == 1 // 1:<3A>ڴ<EFBFBD>ռ<EFBFBD><D5BC>С 0:<3A>ٶȿ<D9B6>
|
|
|
|
|
VROM_tiles = VROM_banks;
|
|
|
|
|
#else
|
|
|
|
|
VROM_tiles = mymalloc(RomHeader->num_8k_vrom_banks * 8 *
|
|
|
|
|
1024); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>1MB<4D>ڴ<EFBFBD>!!!
|
|
|
|
|
if (VROM_tiles == 0)
|
|
|
|
|
VROM_tiles =
|
|
|
|
|
VROM_banks; // <20>ڴ治<DAB4><E6B2BB><EFBFBD>õ<EFBFBD><C3B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>,<2C><><EFBFBD><EFBFBD>VROM_titles<65><73>VROM_banks<6B><73><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>
|
|
|
|
|
compile(RomHeader->num_8k_vrom_banks * 8 * 1024 / 16, VROM_banks,
|
|
|
|
|
VROM_tiles);
|
|
|
|
|
#endif
|
|
|
|
|
} else {
|
|
|
|
|
VROM_banks = mymalloc(8 * 1024);
|
|
|
|
|
VROM_tiles = mymalloc(8 * 1024);
|
|
|
|
|
if (!VROM_banks || !VROM_tiles)
|
|
|
|
|
res = 1;
|
|
|
|
|
}
|
|
|
|
|
VROM_1K_SIZE = RomHeader->num_8k_vrom_banks * 8;
|
|
|
|
|
VROM_8K_SIZE = RomHeader->num_8k_vrom_banks;
|
|
|
|
|
MapperNo = (RomHeader->flags_1 >> 4) | (RomHeader->flags_2 & 0xf0);
|
|
|
|
|
if (RomHeader->flags_2 & 0x0E)
|
|
|
|
|
MapperNo = RomHeader->flags_1 >> 4; // <20><><EFBFBD>Ը<EFBFBD><D4B8><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͷ<EFBFBD><CDB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
// printf("use map:%d\r\n",MapperNo);
|
|
|
|
|
for (i = 0; i < 255; i++) // <20><><EFBFBD><EFBFBD>֧<EFBFBD>ֵ<EFBFBD>Mapper<65><72>
|
|
|
|
|
{
|
|
|
|
|
if (MapTab[i] == MapperNo)
|
|
|
|
|
break;
|
|
|
|
|
if (MapTab[i] == -1)
|
|
|
|
|
res = 3;
|
|
|
|
|
}
|
|
|
|
|
if (res == 0) {
|
|
|
|
|
switch (MapperNo) {
|
|
|
|
|
case 1:
|
|
|
|
|
MAP1 = mymalloc(sizeof(Mapper1Res));
|
|
|
|
|
if (!MAP1)
|
|
|
|
|
res = 1;
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
case 6:
|
|
|
|
|
case 16:
|
|
|
|
|
case 17:
|
|
|
|
|
case 18:
|
|
|
|
|
case 19:
|
|
|
|
|
case 21:
|
|
|
|
|
case 23:
|
|
|
|
|
case 24:
|
|
|
|
|
case 25:
|
|
|
|
|
case 64:
|
|
|
|
|
case 65:
|
|
|
|
|
case 67:
|
|
|
|
|
case 69:
|
|
|
|
|
case 85:
|
|
|
|
|
case 189:
|
|
|
|
|
MAPx = mymalloc(sizeof(MapperCommRes));
|
|
|
|
|
if (!MAPx)
|
|
|
|
|
res = 1;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return res; // <20><><EFBFBD><EFBFBD>ִ<EFBFBD>н<EFBFBD><D0BD><EFBFBD>
|
|
|
|
|
}
|
|
|
|
|
// <20><><EFBFBD><EFBFBD>NES_RAM<41><4D><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>ʱ<EFBFBD>ĸ<EFBFBD><C4B8><EFBFBD>ָ<EFBFBD><D6B8>
|
2025-06-27 00:32:57 +08:00
|
|
|
|
void *nes_ram_alignment;
|
2025-07-10 11:30:57 +08:00
|
|
|
|
// <20>ͷ<EFBFBD><CDB7>ڴ<EFBFBD>
|
|
|
|
|
void nes_sram_free(void) {
|
|
|
|
|
// myfree(NES_RAM);
|
|
|
|
|
myfree(nes_ram_alignment);
|
|
|
|
|
myfree(NES_SRAM);
|
|
|
|
|
myfree(RomHeader);
|
|
|
|
|
myfree(NES_Mapper);
|
|
|
|
|
myfree(spr_ram);
|
|
|
|
|
myfree(ppu);
|
|
|
|
|
myfree(apu);
|
|
|
|
|
myfree(wave_buffers);
|
|
|
|
|
myfree(i2sbuf1);
|
|
|
|
|
myfree(i2sbuf2);
|
|
|
|
|
myfree(romfile);
|
|
|
|
|
if ((VROM_tiles != VROM_banks) && VROM_banks &&
|
|
|
|
|
VROM_tiles) // <20><><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD>ΪVROM_banks<6B><73>VROM_tiles<65><73><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>,<2C><><EFBFBD>ͷ<EFBFBD>
|
|
|
|
|
{
|
|
|
|
|
myfree(VROM_banks);
|
|
|
|
|
myfree(VROM_tiles);
|
|
|
|
|
}
|
|
|
|
|
switch (MapperNo) // <20>ͷ<EFBFBD>map<61>ڴ<EFBFBD>
|
|
|
|
|
{
|
|
|
|
|
case 1: // <20>ͷ<EFBFBD><CDB7>ڴ<EFBFBD>
|
|
|
|
|
myfree(MAP1);
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
case 6:
|
|
|
|
|
case 16:
|
|
|
|
|
case 17:
|
|
|
|
|
case 18:
|
|
|
|
|
case 19:
|
|
|
|
|
case 21:
|
|
|
|
|
case 23:
|
|
|
|
|
case 24:
|
|
|
|
|
case 25:
|
|
|
|
|
case 64:
|
|
|
|
|
case 65:
|
|
|
|
|
case 67:
|
|
|
|
|
case 69:
|
|
|
|
|
case 85:
|
|
|
|
|
case 189:
|
|
|
|
|
myfree(MAPx);
|
|
|
|
|
break; // <20>ͷ<EFBFBD><CDB7>ڴ<EFBFBD>
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
NES_RAM = 0;
|
|
|
|
|
NES_SRAM = 0;
|
|
|
|
|
RomHeader = 0;
|
|
|
|
|
NES_Mapper = 0;
|
|
|
|
|
spr_ram = 0;
|
|
|
|
|
ppu = 0;
|
|
|
|
|
apu = 0;
|
|
|
|
|
wave_buffers = 0;
|
|
|
|
|
i2sbuf1 = 0;
|
|
|
|
|
i2sbuf2 = 0;
|
|
|
|
|
romfile = 0;
|
|
|
|
|
VROM_banks = 0;
|
|
|
|
|
VROM_tiles = 0;
|
|
|
|
|
MAP1 = 0;
|
|
|
|
|
MAPx = 0;
|
2025-06-27 00:32:57 +08:00
|
|
|
|
}
|
2025-07-10 11:30:57 +08:00
|
|
|
|
// ΪNES<45><53><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>
|
|
|
|
|
// romsize:nes<65>ļ<EFBFBD><C4BC><EFBFBD>С
|
|
|
|
|
// <20><><EFBFBD><EFBFBD>ֵ:0,<2C><><EFBFBD><EFBFBD><EFBFBD>ɹ<EFBFBD>
|
|
|
|
|
// 1,<2C><><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>
|
|
|
|
|
uint8_t nes_sram_malloc(uint32_t romsize) {
|
|
|
|
|
uint16_t i = 0;
|
|
|
|
|
|
|
|
|
|
// NES_RAM<41><4D>Ҫ0x800<30><30>С<EFBFBD><D0A1><EFBFBD>ڴ棬<DAB4><E6A3AC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>0x400<30><30><EFBFBD>ڴ棬<DAB4><E6A3AC><EFBFBD><EFBFBD>1024<32>ֽڶ<D6BD><DAB6><EFBFBD>
|
|
|
|
|
nes_ram_alignment = mymalloc(0x800 + 0x400);
|
|
|
|
|
NES_RAM = (void *)(((uint32_t)nes_ram_alignment + 0x400) & 0xfffffc00);
|
|
|
|
|
|
|
|
|
|
NES_SRAM = mymalloc(0X2000);
|
|
|
|
|
RomHeader = mymalloc(sizeof(NES_header));
|
|
|
|
|
NES_Mapper = mymalloc(sizeof(MAPPER));
|
|
|
|
|
spr_ram = mymalloc(0X100);
|
|
|
|
|
ppu = mymalloc(sizeof(ppu_data));
|
|
|
|
|
apu = mymalloc(sizeof(apu_t)); // sizeof(apu_t)= 12588
|
|
|
|
|
wave_buffers = mymalloc(APU_PCMBUF_SIZE * 2);
|
|
|
|
|
i2sbuf1 = mymalloc(APU_PCMBUF_SIZE * 4 + 10);
|
|
|
|
|
i2sbuf2 = mymalloc(APU_PCMBUF_SIZE * 4 + 10);
|
|
|
|
|
romfile = mymalloc(romsize); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϸrom<6F>ռ<EFBFBD>,<2C><><EFBFBD><EFBFBD>nes<65>ļ<EFBFBD><C4BC><EFBFBD>С
|
|
|
|
|
if (i == 64 || !NES_RAM || !NES_SRAM || !RomHeader || !NES_Mapper ||
|
|
|
|
|
!spr_ram || !ppu || !apu || !wave_buffers || !i2sbuf1 || !i2sbuf2 ||
|
|
|
|
|
!romfile) {
|
|
|
|
|
nes_sram_free();
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
memset(NES_SRAM, 0, 0X2000); // <20><><EFBFBD><EFBFBD>
|
|
|
|
|
memset(RomHeader, 0, sizeof(NES_header)); // <20><><EFBFBD><EFBFBD>
|
|
|
|
|
memset(NES_Mapper, 0, sizeof(MAPPER)); // <20><><EFBFBD><EFBFBD>
|
|
|
|
|
memset(spr_ram, 0, 0X100); // <20><><EFBFBD><EFBFBD>
|
|
|
|
|
memset(ppu, 0, sizeof(ppu_data)); // <20><><EFBFBD><EFBFBD>
|
|
|
|
|
memset(apu, 0, sizeof(apu_t)); // <20><><EFBFBD><EFBFBD>
|
|
|
|
|
memset(wave_buffers, 0, APU_PCMBUF_SIZE * 2); // <20><><EFBFBD><EFBFBD>
|
|
|
|
|
memset(i2sbuf1, 0, APU_PCMBUF_SIZE * 4 + 10); // <20><><EFBFBD><EFBFBD>
|
|
|
|
|
memset(i2sbuf2, 0, APU_PCMBUF_SIZE * 4 + 10); // <20><><EFBFBD><EFBFBD>
|
|
|
|
|
memset(romfile, 0, romsize); // <20><><EFBFBD><EFBFBD>
|
|
|
|
|
return 0;
|
2025-06-27 00:32:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
2025-07-10 11:30:57 +08:00
|
|
|
|
int nes_xoff = 0; // <20><>ʾ<EFBFBD><CABE>x<EFBFBD>᷽<EFBFBD><E1B7BD><EFBFBD><EFBFBD>ƫ<EFBFBD><C6AB><EFBFBD><EFBFBD>(ʵ<><CAB5><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD>=256-2*nes_xoff)
|
|
|
|
|
int nes_yoff = 0;
|
|
|
|
|
|
|
|
|
|
// <20><>ʼnes<65><73>Ϸ
|
|
|
|
|
// pname:nes<65><73>Ϸ·<CFB7><C2B7>
|
|
|
|
|
// <20><><EFBFBD><EFBFBD>ֵ:
|
|
|
|
|
// 0,<2C><><EFBFBD><EFBFBD><EFBFBD>˳<EFBFBD>
|
|
|
|
|
// 1,<2C>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
// 2,<2C>ļ<EFBFBD><C4BC><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
// 3,<2C><>֧<EFBFBD>ֵ<EFBFBD>map
|
|
|
|
|
uint8_t nes_load(uint8_t *pname, void *lcd_addr, int x, int y) {
|
|
|
|
|
nes_xoff = x;
|
|
|
|
|
nes_yoff = y;
|
|
|
|
|
FIL *file;
|
|
|
|
|
FILINFO *file_info;
|
|
|
|
|
UINT br;
|
|
|
|
|
uint8_t res = 0;
|
|
|
|
|
g_nes_break = 0;
|
|
|
|
|
file = mymalloc(sizeof(FIL));
|
|
|
|
|
file_info = mymalloc(sizeof(FILINFO));
|
|
|
|
|
if (file == 0)
|
|
|
|
|
return 1; // <20>ڴ<EFBFBD><DAB4><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7>.
|
|
|
|
|
|
|
|
|
|
res = f_stat((char *)pname, file_info);
|
|
|
|
|
if (res != FR_OK) // <20><><EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD>ʧ<EFBFBD><CAA7>
|
|
|
|
|
{
|
|
|
|
|
myfree(file);
|
|
|
|
|
myfree(file_info);
|
|
|
|
|
return 2;
|
|
|
|
|
}
|
|
|
|
|
res = nes_sram_malloc(file_info->fsize); // <20><><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>
|
|
|
|
|
if (res == 0) {
|
|
|
|
|
f_open(file, (char *)pname, FA_READ);
|
|
|
|
|
f_read(file, romfile, file_info->fsize, &br); // <20><>ȡnes<65>ļ<EFBFBD>
|
|
|
|
|
res = nes_load_rom(); // <20><><EFBFBD><EFBFBD>ROM
|
|
|
|
|
if (res == 0) {
|
|
|
|
|
Mapper_Init(); // map<61><70>ʼ<EFBFBD><CABC>
|
|
|
|
|
cpu6502_init(); // <20><>ʼ<EFBFBD><CABC>6502,<2C><><EFBFBD><EFBFBD>λ
|
|
|
|
|
PPU_reset(lcd_addr); // ppu<70><75>λ
|
|
|
|
|
apu_init(); // apu<70><75>ʼ<EFBFBD><CABC>
|
|
|
|
|
nes_sound_open(0, APU_SAMPLE_RATE); // <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>豸
|
|
|
|
|
nes_emulate_frame(); // <20><><EFBFBD><EFBFBD>NESģ<53><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><D1AD>
|
|
|
|
|
nes_sound_close(); // <20>ر<EFBFBD><D8B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
f_close(file);
|
|
|
|
|
myfree(file); // <20>ͷ<EFBFBD><CDB7>ڴ<EFBFBD>
|
|
|
|
|
myfree(file_info);
|
|
|
|
|
nes_sram_free(); // <20>ͷ<EFBFBD><CDB7>ڴ<EFBFBD>
|
|
|
|
|
return res;
|
2025-06-27 00:32:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
2025-07-10 11:30:57 +08:00
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD>Ѿ<EFBFBD><D1BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD><DAB4>е<EFBFBD><D0B5><EFBFBD>Ϸ
|
|
|
|
|
uint8_t nes_start(uint8_t *file, int fileSize, void *lcd_addr, int x, int y) {
|
|
|
|
|
nes_xoff = x;
|
|
|
|
|
nes_yoff = y;
|
|
|
|
|
uint8_t res = 0;
|
|
|
|
|
g_nes_break = 0;
|
|
|
|
|
res = nes_sram_malloc(fileSize); // <20><><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>
|
|
|
|
|
|
|
|
|
|
if (res == 0) {
|
|
|
|
|
mymemcpy(romfile, file, fileSize); // <20><><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>пռ<D0BF>
|
|
|
|
|
res = nes_load_rom(); // <20><><EFBFBD><EFBFBD>ROM
|
|
|
|
|
if (res == 0) {
|
|
|
|
|
Mapper_Init(); // map<61><70>ʼ<EFBFBD><CABC>
|
|
|
|
|
cpu6502_init(); // <20><>ʼ<EFBFBD><CABC>6502,<2C><><EFBFBD><EFBFBD>λ
|
|
|
|
|
PPU_reset(lcd_addr); // ppu<70><75>λ
|
|
|
|
|
apu_init(); // apu<70><75>ʼ<EFBFBD><CABC>
|
|
|
|
|
nes_sound_open(0, APU_SAMPLE_RATE); // <20><>ʼ<EFBFBD><CABC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>豸
|
|
|
|
|
nes_emulate_frame(); // <20><><EFBFBD><EFBFBD>NESģ<53><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><D1AD>
|
|
|
|
|
nes_sound_close(); // <20>ر<EFBFBD><D8B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
nes_sram_free(); // <20>ͷ<EFBFBD><CDB7>ڴ<EFBFBD>
|
|
|
|
|
return res;
|
|
|
|
|
}
|
2025-06-27 00:32:57 +08:00
|
|
|
|
|
2025-07-10 11:30:57 +08:00
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϸ<EFBFBD><CFB7>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD>
|
|
|
|
|
void nes_set_window(void) {}
|
2025-06-27 00:32:57 +08:00
|
|
|
|
|
2025-07-10 11:30:57 +08:00
|
|
|
|
// <20><>ȡ<EFBFBD><C8A1>Ϸ<EFBFBD>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
void nes_get_gamepadval(void) {
|
|
|
|
|
#include "usart.h"
|
|
|
|
|
PADdata = USART3_GetKey();
|
|
|
|
|
PADdata1 = 0;
|
2025-06-27 00:32:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
2025-07-10 11:30:57 +08:00
|
|
|
|
// nesģ<73><C4A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ѭ<EFBFBD><D1AD>
|
|
|
|
|
void nes_emulate_frame(void) {
|
|
|
|
|
uint8_t nes_frame;
|
|
|
|
|
// TIM3_Int_Init(10000-1,8400-1);//<2F><><EFBFBD><EFBFBD>TIM3 ,1s<31>ж<EFBFBD>һ<EFBFBD><D2BB>
|
|
|
|
|
nes_set_window(); // <20><><EFBFBD>ô<EFBFBD><C3B4><EFBFBD>
|
|
|
|
|
while (1) {
|
|
|
|
|
// LINES 0-239
|
|
|
|
|
PPU_start_frame();
|
|
|
|
|
// LCD_SwitchLayerBuff();//<2F>л<EFBFBD>֡
|
|
|
|
|
for (NES_scanline = 0; NES_scanline < 240; NES_scanline++) {
|
|
|
|
|
run6502(113 * 256);
|
|
|
|
|
NES_Mapper->HSync(NES_scanline);
|
|
|
|
|
// ɨ<><C9A8>һ<EFBFBD><D2BB>
|
|
|
|
|
if (nes_frame == 0)
|
|
|
|
|
scanline_draw(NES_scanline);
|
|
|
|
|
else
|
|
|
|
|
do_scanline_and_dont_draw(NES_scanline);
|
|
|
|
|
}
|
|
|
|
|
// LCD_ExitLayerBuff ();
|
|
|
|
|
|
|
|
|
|
NES_scanline = 240;
|
|
|
|
|
run6502(113 * 256); // <20><><EFBFBD><EFBFBD>1<EFBFBD><31>
|
|
|
|
|
NES_Mapper->HSync(NES_scanline);
|
|
|
|
|
start_vblank();
|
|
|
|
|
if (NMI_enabled()) {
|
|
|
|
|
cpunmi = 1;
|
|
|
|
|
run6502(7 * 256); // <20><><EFBFBD><EFBFBD><EFBFBD>ж<EFBFBD>
|
|
|
|
|
}
|
|
|
|
|
NES_Mapper->VSync();
|
|
|
|
|
// LINES 242-261
|
|
|
|
|
for (NES_scanline = 241; NES_scanline < 262; NES_scanline++) {
|
|
|
|
|
run6502(113 * 256);
|
|
|
|
|
NES_Mapper->HSync(NES_scanline);
|
|
|
|
|
}
|
|
|
|
|
end_vblank();
|
|
|
|
|
nes_get_gamepadval(); // ÿ3֡<33><D6A1>ѯһ<D1AF><D2BB>USB
|
|
|
|
|
apu_soundoutput(); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϸ<EFBFBD><CFB7><EFBFBD><EFBFBD>
|
|
|
|
|
nes_frame_cnt++;
|
|
|
|
|
nes_frame++;
|
|
|
|
|
if (nes_frame > NES_SKIP_FRAME)
|
|
|
|
|
nes_frame = 0; // <20><>֡
|
|
|
|
|
uint8_t nesBreak(void);
|
|
|
|
|
if (nesBreak())
|
|
|
|
|
break;
|
|
|
|
|
if (Touch_GetState()->x[1] != 0)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
// TIM3->CR1&=~(1<<0);//<2F>رն<D8B1>ʱ<EFBFBD><CAB1>3
|
|
|
|
|
}
|
2025-06-27 00:32:57 +08:00
|
|
|
|
|
2025-07-10 11:30:57 +08:00
|
|
|
|
uint8_t nesBreak(void) {
|
|
|
|
|
uint8_t t = 0;
|
|
|
|
|
if ((PADdata & 0x0c) == 0x0c) {
|
|
|
|
|
g_nes_break = 0x0c;
|
|
|
|
|
}
|
|
|
|
|
if ((g_nes_break) && (t = USART3_GetKeyPressed(), t & 0x0c)) {
|
|
|
|
|
g_nes_break &= ~t;
|
|
|
|
|
if (g_nes_break == 0)
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2025-06-27 00:32:57 +08:00
|
|
|
|
|
2025-07-10 11:30:57 +08:00
|
|
|
|
// <20><>6502.s<><73><EFBFBD>汻<EFBFBD><E6B1BB><EFBFBD><EFBFBD>
|
|
|
|
|
void debug_6502(uint16_t reg0, uint8_t reg1) {
|
|
|
|
|
// printf("6502 error:%x,%d\r\n",reg0,reg1);
|
|
|
|
|
}
|
2025-06-27 00:32:57 +08:00
|
|
|
|
|
2025-07-10 11:30:57 +08:00
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// nes,<2C><>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD>֧<EFBFBD>ֲ<EFBFBD><D6B2><EFBFBD>
|
2025-06-27 00:32:57 +08:00
|
|
|
|
|
2025-07-10 11:30:57 +08:00
|
|
|
|
static vu8 g_buff_Invalid = 0; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ЧʱҪ<CAB1><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
static vu8 g_buff_useing; // <20><>ǰDMA<4D><41>ʹ<EFBFBD><CAB9><EFBFBD>ĸ<EFBFBD><C4B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
2025-06-27 00:32:57 +08:00
|
|
|
|
static DAC_UserStruct g_dac;
|
|
|
|
|
|
2025-07-10 11:30:57 +08:00
|
|
|
|
static void dma_tx_callback(DAC_UserStruct *dac) {
|
|
|
|
|
uint16_t i;
|
|
|
|
|
g_buff_useing = dac->buff_useing;
|
|
|
|
|
g_buff_Invalid = 1;
|
2025-06-27 00:32:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
2025-07-10 11:30:57 +08:00
|
|
|
|
// NES<45><53><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD>
|
|
|
|
|
int nes_sound_open(int samples_per_sync, int sample_rate) {
|
|
|
|
|
|
|
|
|
|
// <20><>ʼ<EFBFBD><CABC>DAC
|
|
|
|
|
g_dac.buff1 = (uint32_t *)i2sbuf1;
|
|
|
|
|
g_dac.buff2 = (uint32_t *)i2sbuf2;
|
|
|
|
|
g_dac.buff_size = APU_PCMBUF_SIZE * 4;
|
|
|
|
|
g_dac.rate = RATE22050;
|
|
|
|
|
g_dac.call_back = dma_tx_callback;
|
|
|
|
|
DAC_NormalInit(&g_dac);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
2025-06-27 00:32:57 +08:00
|
|
|
|
|
2025-07-10 11:30:57 +08:00
|
|
|
|
// NES<45>ر<EFBFBD><D8B1><EFBFBD>Ƶ<EFBFBD><C6B5><EFBFBD><EFBFBD>
|
|
|
|
|
void nes_sound_close(void) { DAC_NormalDeInit(&g_dac); }
|
|
|
|
|
|
|
|
|
|
void nes_apu_fill_buffer(int samples, uint16_t *wavebuf) {
|
|
|
|
|
if (DAC_GetDacHander() != &g_dac)
|
|
|
|
|
return;
|
|
|
|
|
uint16_t i;
|
|
|
|
|
uint16_t *p;
|
|
|
|
|
while (g_buff_Invalid == 0) // <20>ȴ<EFBFBD><C8B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|
|
|
|
{
|
|
|
|
|
rt_thread_delay(5);
|
|
|
|
|
};
|
|
|
|
|
if (g_buff_useing == 0) {
|
|
|
|
|
p = (uint16_t *)i2sbuf2;
|
|
|
|
|
} else {
|
|
|
|
|
p = (uint16_t *)i2sbuf1;
|
|
|
|
|
}
|
|
|
|
|
{
|
|
|
|
|
for (i = 0; i < APU_PCMBUF_SIZE; i++) {
|
|
|
|
|
p[2 * i] = ((wavebuf[i] + 0x8000) >> 4);
|
|
|
|
|
p[2 * i + 1] = p[2 * i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮<EFBFBD><D6AE><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD><CEAA>Ч
|
|
|
|
|
g_buff_Invalid = 0;
|
|
|
|
|
}
|