# esplay **Repository Path**: yangyang113/esplay ## Basic Information - **Project Name**: esplay - **Description**: 将github上的esplay项目继续完善,开发。采用camake - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 2 - **Created**: 2025-03-30 - **Last Updated**: 2025-03-30 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## nes模拟器原理说明 ### mapper number校验 > - mapper 是什么含义,数字代表什么暂时没有弄明白 > - 目前支持的在nes/mmclist.c 的mappers结构体中,为0-25 32-34 40 64-66 70 75 78 79 85 94 99 231 > - header 位于nes固件的开头 以二进制打开坦克大战可以看到前8个字节 4e[N] 45[E] 53[S] 1a 01 01 00 00 > - mapper_number = rom_type>>4 | (mapper_hinybble&0xf0) > - 坦克大战计算出来的num = 0 符合 > - 封神榜游戏 打开后4e[N] 45[E] 53[S] 1a 20 40 62 f0 计算出来num=246 不符合,程序会报错。 ```c typedef struct inesheader_s { uint8 ines_magic[4] ; uint8 rom_banks ; uint8 vrom_banks ; uint8 rom_type ; uint8 mapper_hinybble ; uint8 reserved[8] ; } inesheader_t; ``` ### 添加中文支持 1、中文直接采用的16*16字库,字库可以有两种方式存储 - 直接烧录到分区表的某一个位置,然后程序中判断如果有中文就读取该分区 - 直接将字库二进制文件键入到代码中,会编译到.rodata段,具体需要在cmakelist中添加 EMBED_FILES hzk16s - 使用的时候直接定义extern const uint8_t han16data[] asm("_binary_hzk16s_start");其中han16data对应于hzk16s字库的首地址 - 后面就用数组han16data来访问字库,目前采用的该方式,hzk16s,放置在ugui目录下 2、gbk16*16字库索引:gbk编码每个汉字采用16进制编码。比如“大” 的编码是 0xb4 0xf3 其中b4是区码。每个区有94个字,f3是位码,代表大在其区间的位置 3、索引计算公式 offset = (94*(0xb4-0xa0-1) + 0xf3-0xa0-1) * 32。 ![1](pic/1.png) ![2](pic/2.jpg) 4、在ugui.c中写了一个新的函数UG_PutHan16Char用于处理汉字。在UG_PutString函数中先判断字符是不是超过了0x80(127),超过了就认为是中文,没有超过就是正常的asii码 5、当前汉字显示正常,但是汉字只能显示4个,具体原因还未查明 ,已经查到了在sdcard_files_get函数中opendir读到的文件名称就已经有问题了,中文显示有问题 2021-11-19 中文显示异常的原因解决了,现在可以显示一行长中文以及各种字符。如下图 ![3](pic/3.png) 之前显示异常的汉字,只能显示4个。其中"一二三四五六七.NES",就只能显示前四个汉字。下图是直接打印的readdir函数读到的结果。与最终显示在屏幕上的是一致的。 ![2](pic/2.png) **汉字显示异常的原因是,没有再fatffs配置中打开中文简体支持**下图为打开后的menuconfig界面 ![4](pic/4.png) 如果要显示中文,最好将长文件名也打开,毕竟一个汉字要占用两个字节,而英文一个字母仅占用半个字节 为了能够完整显示文件名称要做如下修改在esplay-ui.c的ui_draw_page_list进行如下修改 ```C{.line-numbers} char *filename = files[page + line]; if (!filename) abort(); //原代码会进行在cut_file_name中改变文件名的长度,只计算". [ ("之前的长度 //比如文件名abc.de.nes 长度为10,cut_file_name返回的长度是3 //后面只会将前三个字母拷贝到displayStr中 //这会造成一个问题如果文件名是[ ( 开头的话,就cut_file_name返回的长度就是0,造成该文件名无法显示 // int length = cut_file_name(filename); int length = strlen(filename); displayStr[line] = (char *)malloc(length + 1); strncpy(displayStr[line], filename, length); displayStr[line][length] = 0; char truncnm[MAX_CHR*2]; if(length>MAX_CHR) length = MAX_CHR; // strncpy(truncnm, displayStr[line], MAX_CHR); strcpy(truncnm,displayStr[line]); truncnm[MAX_CHR - 1] = 0; UG_PutString((320 / 2) - (strlen(truncnm) * 9 / 2), top, truncnm); ``` 如果文件名称很长会在 free(displayStr[i]);下面发生异常 2021-11-25 free异常原因找到了 strcpy(truncnm,displayStr[line]); 当 displayStr的长度大于truncnm时,直接内存拷贝就会出问题 解决方案:将struncnm长度改为displayStr长度+1,struncnm最后一个字节设置为'\0',用于标记字符串结束 ![6](pic/6.jpg) 长文件名会导致显示覆盖到了下一行 **待添加文字长文件名滚动效果** 2021-11-26 1、nes增加了汉字支持,在menuconfig中设置,否则会导致找不到中文路径的rom 2、nes修复mapper不支持,后free bitmap内存时报错,内存地址位于堆的外部;原因是bmp_create函数中,引入以一个静态数组的地址。改为动态分配。 3、开启了nes的gui显示system_video函数中开启,默认可以关闭掉