| 
									
										
										
										
											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; | 
					
						
							|  |  |  |  | } |