第四篇:手把手教你移植任天堂,没有声音、无需外置SD卡、可使用独立按键也可使用外置手柄,本人使用的芯片为ESP32,移植到STM32均可使用。(本篇主要介绍joypad这个文件,按键移植)
作者:互联网
这篇相对第三篇就稍微复杂那么一点点了,话不多说,直接贴代码,完整代码文章最后贴出、
先看.h文件
#ifndef _JOYPAD_H_
#define _JOYPAD_H_
#include "KeyNum.h" //获取按键值头文件
#include "adcrock.h" //获取方向值头文件
#include "type.h" //数据类型头文件
#define JOYPAD_0 0 //是否读取键值得开关 0读取
#define JOYPAD_1 1 //是否读取键值开关 1不读取
extern u8 JOY_key; //保存角色1键值
extern u8 JOY_key2; //保存角色2键值
typedef struct{
u8 state; //状态
u8 index; //当前读取位
u32 value; //JoyPad 当前值
}JoyPadType;
/* function ------------------------------------------------------------------*/
void NES_JoyPadInit(void); //初始化模拟手柄
void NES_JoyPadReset(void); //读取键值,并存入 JOY_key
void NES_JoyPadDisable(void); //未用到
u8 NES_GetJoyPadVlaue(int JoyPadNum);//将JOY_key转化为模拟手柄脉冲,次函数供角色1使用
u8 NES_GetJoyPadVlaue2(int JoyPadNum);//将JOY_key转化为模拟手柄脉冲,次函数供角色2使用
#endif
分析上面的代码,先看引用的头文件
#include "KeyNum.h" //获取按键值头文件
#include "adcrock.h" //获取方向值头文件
这两个需要改成你们自己获取按键值得和方向的头文件
其他代码就不用改了,注意
void NES_JoyPadInit(void); //初始化模拟手柄
这个函数,会在nes_main用到,待会讲解
再看.c文件,.c文件完整代码后面贴出
直捣黄龙,我们直接看按键是如何控制的
void NES_JoyPadReset(void)
{
JoyPad[0].state = 1;
JoyPad[0].index = 0;
JoyPad[1].state = 1;
JoyPad[1].index = 0;
u8 ROCK_DIRCTION;
u8 KEY_value;
static u32 key_time = 0;
// if ((millis() - key_time) > 10)
// {
key_time = millis();
switch (key_get_num()) //获取按键数据
{
case 2:
KEY_value = 0X01; //按键A
break;
case 1:
KEY_value = 0x02; //按键B
break;
case 3:
KEY_value = 0x03; //按键A和B同时按
break;
case 7:
KEY_value = 0x04; //按键Select
break;
case 9:
KEY_value = 0x08; //按键Select
break;
default:
KEY_value = 0x00;
}
switch (print_directional()) //获取方向数据
{
case 1:
ROCK_DIRCTION = 0x10; //遥感上
break;
case 2:
ROCK_DIRCTION = 0x20; //遥感下
break;
case 3:
ROCK_DIRCTION = 0x40; //遥感左
break;
case 4:
ROCK_DIRCTION = 0x80; //遥感右
break;
default:
ROCK_DIRCTION = 0x00; //按键Select
}
// JOY_key=0xFF-((右 <<7)|(左 <<6)|(下 <<5)|(上 <<4)|Start<<3)|Select<<2)|(B <<1)|A );
JOY_key = ROCK_DIRCTION | KEY_value;
// JOYPAD_LAT=1;// 锁存一下
// JOYPAD_LAT=0;
// }
// else
// JOY_key = 0;
}
对于这段代码,很简单,key_get_num():即获取按键数据,并将按键数据转化为A,B,Start,Select,同理print_directional();即获取方向数据,并将按键数据转化为上,下,左,右
很显然key_get_num()、print_directional():这两个函数是需要你们自己写滴,直接复制是不会编译通过的
具体JOY_key保存信息结构如下:
//读取手柄按键值.
//FC手柄数据输出格式:
//每给一个脉冲,输出一位数据,输出顺序:
//A->B->SELECT->START->UP->DOWN->LEFT->RIGHT.
//总共8位,对于有C按钮的手柄,按下C其实就等于A+B同时按下.
//按下是0,松开是1.
//[0]:右 0--->7
//[1]:左
//[2]:下
//[3]:上
//[4]:Start
//[5]:Select
//[6]:B
//[7]:A
再看引用键值得函数
u8 NES_GetJoyPadVlaue(int JoyPadNum) // 得到手柄脉冲
{
u8 retval = 0;
if (JoyPadNum == 0)
{
retval = (JOY_key >> JoyPad[0].index) & 0X01;
if (JoyPad[0].index == 20)
retval = 1; //20位表示控制器在位.
// printf("\r\n 按键: %d",retval); //我写的代码 测试用
JoyPad[0].index++;
}
return retval;
}
这里需要注意的是:
当JoyPad[0].index == 20时,为控制第一个手柄
当JoyPad[0].index == 19时,为控制第二个手柄
然后打开nes_main.c文件
找到如下代码
printf("\r\n 开始申请内存\n");
res = nes_mem_creat(); //申请内存
if (res == 0) //申请成功了.则运行游戏
{
printf("\r\n 开始申请成功\n");
printf("\r\n 初始化6502\n");
LCD_tft_init(); //初始化显示设备
PPU_Init(((u8 *)&rom_file[offset + 0x10] +
(neshreader->romnum * 0x4000)),
(neshreader->romfeature & 0x01)
); //PPU_初始化
printf("\r\n 初始化按键\n");
printf("\r\n 初始化joypad\n");
printf("\r\n 无限循环执行游戏\n");
printf("\r\n 按下退出游戏键\n");
}
else printf("\r\n 开始申请失败\n");
nes_mem_delete();//释放内存
return res;
}
改为
printf("\r\n 开始申请内存\n");
res = nes_mem_creat(); //申请内存
if (res == 0) //申请成功了.则运行游戏
{
printf("\r\n 开始申请成功\n");
printf("\r\n 初始化6502\n");
LCD_tft_init(); //初始化显示设备
PPU_Init(((u8 *)&rom_file[offset + 0x10] +
(neshreader->romnum * 0x4000)),
(neshreader->romfeature & 0x01)
); //PPU_初始化
key_init(); //初始化获取按键值设备
adc_init(); //初始化获取方向值设备
NES_JoyPadInit(); //初始化模拟手柄
printf("\r\n 无限循环执行游戏\n");
printf("\r\n 按下退出游戏键\n");
}
else printf("\r\n 开始申请失败\n");
nes_mem_delete();//释放内存
return res;
}
同时在头文件添加
#include "joypad.h"
编译通过即可
下面为完整的.c代码
#include "joypad.h"
u8 JOY_key = 0xFF;
u8 JOY_key2 = 0xFF;
JoyPadType JoyPad[2];
u8 NES_GetJoyPadVlaue(int JoyPadNum) // 得到手柄脉冲
{
u8 retval = 0;
if (JoyPadNum == 0)
{
retval = (JOY_key >> JoyPad[0].index) & 0X01;
if (JoyPad[0].index == 20)
retval = 1; //20位表示控制器在位.
// printf("\r\n 按键: %d",retval); //我写的代码 测试用
JoyPad[0].index++;
}
return retval;
}
u8 NES_GetJoyPadVlaue2(int JoyPadNum) // 得到手柄脉冲
{
u8 retval = 0;
if (JoyPadNum == 0)
{
retval = (JOY_key >> JoyPad[1].index) & 0X01;
if (JoyPad[1].index == 19)
retval = 1; //20位表示控制器在位.
// printf("\r\n 按键: %d",retval); //我写的代码 测试用
JoyPad[1].index++;
}
return retval;
}
//读取手柄按键值.
//FC手柄数据输出格式:
//每给一个脉冲,输出一位数据,输出顺序:
//A->B->SELECT->START->UP->DOWN->LEFT->RIGHT.
//总共8位,对于有C按钮的手柄,按下C其实就等于A+B同时按下.
//按下是0,松开是1.
//[0]:右 0--->7
//[1]:左
//[2]:下
//[3]:上
//[4]:Start
//[5]:Select
//[6]:B
//[7]:A
void NES_JoyPadReset(void)
{
JoyPad[0].state = 1;
JoyPad[0].index = 0;
u8 ROCK_DIRCTION;
u8 KEY_value;
static u32 key_time = 0;
if ((millis() - key_time) > 10)
{
key_time=millis();
switch (key_get_num())
{
case 2:
KEY_value = 0X01; //按键A
break;
case 1:
KEY_value = 0x02; //按键B
break;
case 3:
KEY_value = 0x03; //按键A和B同时按
break;
case 7:
KEY_value = 0x04; //按键Select
break;
case 9:
KEY_value = 0x08; //按键Select
break;
default:
KEY_value = 0x00;
}
switch (print_directional())
{
case 1:
ROCK_DIRCTION = 0x10; //遥感上
break;
case 2:
ROCK_DIRCTION = 0x20; //遥感下
break;
case 3:
ROCK_DIRCTION = 0x40; //遥感左
break;
case 4:
ROCK_DIRCTION = 0x80; //遥感右
break;
default:
ROCK_DIRCTION = 0x00; //按键Select
}
// JOY_key=0xFF-((右 <<7)|(左 <<6)|(下 <<5)|(上 <<4)|Start<<3)|Select<<2)|(B <<1)|A );
// JOY_key=0xFF-((KEY5<<7)|(KEY3<<6)|(0X01<<5)|(0X01<<4)|(KEY1<<3)|(KEY2<<2)|(0X01<<1)|KEY4);
JOY_key = ROCK_DIRCTION | KEY_value;
// JOYPAD_LAT=1;// 锁存一下
// JOYPAD_LAT=0;
}
else
JOY_key = 0;
JoyPad[1].state = 1;
JoyPad[1].index = 0;
}
void NES_JoyPadInit(void)
{
JoyPad[0].state = 0; //状态为0,表示禁止
JoyPad[0].index = 0;
JoyPad[0].value = 1 << 20;
JoyPad[1].state = 0;
JoyPad[1].index = 0;
JoyPad[1].value = 1 << 19;
}
void NES_JoyPadDisable(void)
{
}
标签:case,JoyPad,u8,外置,break,key,按键,移植 来源: https://blog.csdn.net/yuweize520/article/details/122172708