From 387ada7e6f60e04b4bf7f342fbcd33244625e18b Mon Sep 17 00:00:00 2001 From: ranchuan Date: Thu, 10 Jul 2025 11:30:57 +0800 Subject: [PATCH] =?UTF-8?q?=E6=95=B4=E7=90=86=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Project/Src/Drive/Include/lcd_rgb.h | 431 +++--- Project/Src/Drive/Source/lcd_rgb.c | 2082 ++++++++++++--------------- Project/Src/NES/nes_main.c | 915 ++++++------ Project/Src/NES/nes_main.h | 115 +- Project/Src/NES/nes_mapper.c | 546 ++++--- Project/Src/NES/nes_mapper.h | 193 ++- Project/Src/NES/nes_ppu.c | 1508 +++++++++---------- Project/Src/NES/nes_ppu.h | 211 ++- 8 files changed, 2821 insertions(+), 3180 deletions(-) diff --git a/Project/Src/Drive/Include/lcd_rgb.h b/Project/Src/Drive/Include/lcd_rgb.h index c8c4105..780d7dc 100644 --- a/Project/Src/Drive/Include/lcd_rgb.h +++ b/Project/Src/Drive/Include/lcd_rgb.h @@ -1,330 +1,279 @@ #ifndef __LCD_H -#define __LCD_H +#define __LCD_H #include "stm32f4xx.h" +#define LCD_CLK 9 // 定义LCD驱动时钟,这里为了方便计算数值应在10-70之间,单位为M -#define LCD_CLK 9 //定义LCD驱动时钟,这里为了方便计算数值应在10-70之间,单位为M +#define HBP 40 +#define VBP 8 +#define HSW 1 +#define VSW 1 +#define HFP 5 +#define VFP 8 -#define HBP 40 -#define VBP 8 -#define HSW 1 -#define VSW 1 -#define HFP 5 -#define VFP 8 +#define LCD_Width 480 // LCD的像素长度 +#define LCD_Height 272 // LCD的像素宽度 +#define LCD_Pixels (LCD_Width * LCD_Height) // 分辨率 +#define LCD_MemoryAdd 0xD0000000 // 显存的起始地址 -#define LCD_Width 480 //LCD的像素长度 -#define LCD_Height 272 //LCD的像素宽度 -#define LCD_Pixels (LCD_Width*LCD_Height) //分辨率 -#define LCD_MemoryAdd 0xD0000000 //显存的起始地址 - -// 第二层的显存的偏移地址 +// 第二层的显存的偏移地址 // 这里预留了emWin使用32位色格式时,三缓冲所需的空间 // 计算方法,以32位颜色格式为例,每个像素点占4字节,使用emWin三缓冲所需空间为:480*272*4*3 // -#define LCD_MemoryAdd_OFFSET ((uint32_t)LCD_Width*LCD_Height*4*3) +#define LCD_MemoryAdd_OFFSET ((uint32_t)LCD_Width * LCD_Height * 4 * 3) - -/*---------------------- 函数声明 -------------------------*/ -void LCD_Init(void); -void LCD_Backlight (u8 power); +/*---------------------- 函数声明 -------------------------*/ +void LCD_Init(void); +void LCD_Backlight(u8 power); /*-----------------------引脚定义--------------------------*/ -//IO口时钟 -#define LCD_GPIO_CLK RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD \ - | RCC_AHB1Periph_GPIOJ | RCC_AHB1Periph_GPIOK | RCC_AHB1Periph_GPIOI +// IO口时钟 +#define LCD_GPIO_CLK \ + RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | \ + RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOJ | RCC_AHB1Periph_GPIOK | \ + RCC_AHB1Periph_GPIOI -//红色数据线 -#define LTDC_R0_PORT GPIOI -#define LTDC_R0_PIN GPIO_Pin_15 -#define LTDC_R0_PINSOURCE GPIO_PinSource15 +// 红色数据线 +#define LTDC_R0_PORT GPIOI +#define LTDC_R0_PIN GPIO_Pin_15 +#define LTDC_R0_PINSOURCE GPIO_PinSource15 -#define LTDC_R1_PORT GPIOJ -#define LTDC_R1_PIN GPIO_Pin_0 -#define LTDC_R1_PINSOURCE GPIO_PinSource0 +#define LTDC_R1_PORT GPIOJ +#define LTDC_R1_PIN GPIO_Pin_0 +#define LTDC_R1_PINSOURCE GPIO_PinSource0 -#define LTDC_R2_PORT GPIOJ -#define LTDC_R2_PIN GPIO_Pin_1 -#define LTDC_R2_PINSOURCE GPIO_PinSource1 +#define LTDC_R2_PORT GPIOJ +#define LTDC_R2_PIN GPIO_Pin_1 +#define LTDC_R2_PINSOURCE GPIO_PinSource1 -#define LTDC_R3_PORT GPIOJ -#define LTDC_R3_PIN GPIO_Pin_2 -#define LTDC_R3_PINSOURCE GPIO_PinSource2 +#define LTDC_R3_PORT GPIOJ +#define LTDC_R3_PIN GPIO_Pin_2 +#define LTDC_R3_PINSOURCE GPIO_PinSource2 -#define LTDC_R4_PORT GPIOJ -#define LTDC_R4_PIN GPIO_Pin_3 -#define LTDC_R4_PINSOURCE GPIO_PinSource3 +#define LTDC_R4_PORT GPIOJ +#define LTDC_R4_PIN GPIO_Pin_3 +#define LTDC_R4_PINSOURCE GPIO_PinSource3 -#define LTDC_R5_PORT GPIOJ -#define LTDC_R5_PIN GPIO_Pin_4 -#define LTDC_R5_PINSOURCE GPIO_PinSource4 +#define LTDC_R5_PORT GPIOJ +#define LTDC_R5_PIN GPIO_Pin_4 +#define LTDC_R5_PINSOURCE GPIO_PinSource4 -#define LTDC_R6_PORT GPIOJ -#define LTDC_R6_PIN GPIO_Pin_5 -#define LTDC_R6_PINSOURCE GPIO_PinSource5 +#define LTDC_R6_PORT GPIOJ +#define LTDC_R6_PIN GPIO_Pin_5 +#define LTDC_R6_PINSOURCE GPIO_PinSource5 -#define LTDC_R7_PORT GPIOJ -#define LTDC_R7_PIN GPIO_Pin_6 -#define LTDC_R7_PINSOURCE GPIO_PinSource6 +#define LTDC_R7_PORT GPIOJ +#define LTDC_R7_PIN GPIO_Pin_6 +#define LTDC_R7_PINSOURCE GPIO_PinSource6 -//绿色数据线 -#define LTDC_G0_PORT GPIOJ -#define LTDC_G0_PIN GPIO_Pin_7 -#define LTDC_G0_PINSOURCE GPIO_PinSource7 +// 绿色数据线 +#define LTDC_G0_PORT GPIOJ +#define LTDC_G0_PIN GPIO_Pin_7 +#define LTDC_G0_PINSOURCE GPIO_PinSource7 -#define LTDC_G1_PORT GPIOJ -#define LTDC_G1_PIN GPIO_Pin_8 -#define LTDC_G1_PINSOURCE GPIO_PinSource8 +#define LTDC_G1_PORT GPIOJ +#define LTDC_G1_PIN GPIO_Pin_8 +#define LTDC_G1_PINSOURCE GPIO_PinSource8 -#define LTDC_G2_PORT GPIOJ -#define LTDC_G2_PIN GPIO_Pin_9 -#define LTDC_G2_PINSOURCE GPIO_PinSource9 +#define LTDC_G2_PORT GPIOJ +#define LTDC_G2_PIN GPIO_Pin_9 +#define LTDC_G2_PINSOURCE GPIO_PinSource9 -#define LTDC_G3_PORT GPIOJ -#define LTDC_G3_PIN GPIO_Pin_10 -#define LTDC_G3_PINSOURCE GPIO_PinSource10 +#define LTDC_G3_PORT GPIOJ +#define LTDC_G3_PIN GPIO_Pin_10 +#define LTDC_G3_PINSOURCE GPIO_PinSource10 -#define LTDC_G4_PORT GPIOJ -#define LTDC_G4_PIN GPIO_Pin_11 -#define LTDC_G4_PINSOURCE GPIO_PinSource11 +#define LTDC_G4_PORT GPIOJ +#define LTDC_G4_PIN GPIO_Pin_11 +#define LTDC_G4_PINSOURCE GPIO_PinSource11 -#define LTDC_G5_PORT GPIOK -#define LTDC_G5_PIN GPIO_Pin_0 -#define LTDC_G5_PINSOURCE GPIO_PinSource0 +#define LTDC_G5_PORT GPIOK +#define LTDC_G5_PIN GPIO_Pin_0 +#define LTDC_G5_PINSOURCE GPIO_PinSource0 -#define LTDC_G6_PORT GPIOK -#define LTDC_G6_PIN GPIO_Pin_1 -#define LTDC_G6_PINSOURCE GPIO_PinSource1 +#define LTDC_G6_PORT GPIOK +#define LTDC_G6_PIN GPIO_Pin_1 +#define LTDC_G6_PINSOURCE GPIO_PinSource1 -#define LTDC_G7_PORT GPIOK -#define LTDC_G7_PIN GPIO_Pin_2 -#define LTDC_G7_PINSOURCE GPIO_PinSource2 +#define LTDC_G7_PORT GPIOK +#define LTDC_G7_PIN GPIO_Pin_2 +#define LTDC_G7_PINSOURCE GPIO_PinSource2 -//蓝色数据线 -#define LTDC_B0_PORT GPIOJ -#define LTDC_B0_PIN GPIO_Pin_12 -#define LTDC_B0_PINSOURCE GPIO_PinSource12 +// 蓝色数据线 +#define LTDC_B0_PORT GPIOJ +#define LTDC_B0_PIN GPIO_Pin_12 +#define LTDC_B0_PINSOURCE GPIO_PinSource12 -#define LTDC_B1_PORT GPIOJ -#define LTDC_B1_PIN GPIO_Pin_13 -#define LTDC_B1_PINSOURCE GPIO_PinSource13 +#define LTDC_B1_PORT GPIOJ +#define LTDC_B1_PIN GPIO_Pin_13 +#define LTDC_B1_PINSOURCE GPIO_PinSource13 -#define LTDC_B2_PORT GPIOJ -#define LTDC_B2_PIN GPIO_Pin_14 -#define LTDC_B2_PINSOURCE GPIO_PinSource14 +#define LTDC_B2_PORT GPIOJ +#define LTDC_B2_PIN GPIO_Pin_14 +#define LTDC_B2_PINSOURCE GPIO_PinSource14 -#define LTDC_B3_PORT GPIOJ -#define LTDC_B3_PIN GPIO_Pin_15 -#define LTDC_B3_PINSOURCE GPIO_PinSource15 +#define LTDC_B3_PORT GPIOJ +#define LTDC_B3_PIN GPIO_Pin_15 +#define LTDC_B3_PINSOURCE GPIO_PinSource15 -#define LTDC_B4_PORT GPIOK -#define LTDC_B4_PIN GPIO_Pin_3 -#define LTDC_B4_PINSOURCE GPIO_PinSource3 +#define LTDC_B4_PORT GPIOK +#define LTDC_B4_PIN GPIO_Pin_3 +#define LTDC_B4_PINSOURCE GPIO_PinSource3 -#define LTDC_B5_PORT GPIOK -#define LTDC_B5_PIN GPIO_Pin_4 -#define LTDC_B5_PINSOURCE GPIO_PinSource4 +#define LTDC_B5_PORT GPIOK +#define LTDC_B5_PIN GPIO_Pin_4 +#define LTDC_B5_PINSOURCE GPIO_PinSource4 -#define LTDC_B6_PORT GPIOK -#define LTDC_B6_PIN GPIO_Pin_5 -#define LTDC_B6_PINSOURCE GPIO_PinSource5 +#define LTDC_B6_PORT GPIOK +#define LTDC_B6_PIN GPIO_Pin_5 +#define LTDC_B6_PINSOURCE GPIO_PinSource5 -#define LTDC_B7_PORT GPIOK -#define LTDC_B7_PIN GPIO_Pin_6 -#define LTDC_B7_PINSOURCE GPIO_PinSource6 +#define LTDC_B7_PORT GPIOK +#define LTDC_B7_PIN GPIO_Pin_6 +#define LTDC_B7_PINSOURCE GPIO_PinSource6 -//控制信号线 -#define LTDC_CLK_PORT GPIOI //LCD时钟引脚 -#define LTDC_CLK_PIN GPIO_Pin_14 -#define LTDC_CLK_PINSOURCE GPIO_PinSource14 - -#define LTDC_HSYNC_PORT GPIOI //行同步 -#define LTDC_HSYNC_PIN GPIO_Pin_12 -#define LTDC_HSYNC_PINSOURCE GPIO_PinSource12 - -#define LTDC_VSYNC_PORT GPIOI //帧同步 -#define LTDC_VSYNC_PIN GPIO_Pin_13 -#define LTDC_VSYNC_PINSOURCE GPIO_PinSource13 - -#define LTDC_DE_PORT GPIOK //数据使能 -#define LTDC_DE_PIN GPIO_Pin_7 -#define LTDC_DE_PINSOURCE GPIO_PinSource7 - -#define LTDC_Black_PORT GPIOD //背光 -#define LTDC_Black_PIN GPIO_Pin_13 - - - -#define COLOR565TO888(color) ((((color)&0xf800)<<8)|((color)&0x07e0)<<5|(((color)&0x001f)<<3)) -#define COLOR888TO565(color) ((((color)>>8)&0xf800)|(((color)>>5)&0x07e0)|(((color)>>3)&0x001f)) -//把RGB转化为565格式 -#define RGB(r,g,b) ((((r)>>3)<<11)|(((g)>>2)<<5)|((b)>>3)) -//RGB转灰度 -#define RGB2GRAY(rgb16) (((((rgb16)&0xf800)>>8)+(((rgb16)&0x07e0)>>3)+(((rgb16)&0x001f)<<3))/3) -//灰度转RGB -#define GRAY2RGB(gray) ((((gray)>>3)<<11)|(((gray)>>2)<<5)|((gray)>>3)) - -//#define U8 unsigned char -//#define U16 unsigned short -//#define U32 unsigned - - -//extern u32* LCD_ADDR; -//extern u32* LCD_ADDR1; - - -//typedef struct -//{ -// u32 BackColor; //背景颜色 -// u32 Color; //前景颜色 -// u32 ScreenDis; //屏幕显示方向,0,1 -// u32 DrawMode; //绘制模式,0,绘制前景色时绘制背景色,1,绘制前景色时不绘制背景色 -// u16 *DrawAddr; //绘制显存地址 -// u32 LcdAddr; //当前指定的显存地址,在中断中执行切换 -// u32 LcdSwitchEn; //1,当前可以切换到LcdAddr指定的显存地址,0,不允许切换 -// int LayerBuffEnter; //进入缓冲区的次数 -// int WindowSrcX; //绘制窗口起始坐标 -// int WindowSrcY; // -// int WindowDstX; -// int WindowDstY; -//} LCD_Struct; - - - - - -typedef struct -{ - int xs; - int ys; - int xe; - int ye; -}LCD_WindowStruct; - - - -typedef struct -{ - int x_size; - int y_size; - int color; - int bkColor; - int effective; //1,绘制窗口有效 - LCD_WindowStruct win; - LCD_WindowStruct realwin; - u16 *draw; - u16 *show; - void(*fresh)(void); - int LcdSwitchEn; - int LayerBuffEnter; -}LCD_Struct; +// 控制信号线 +#define LTDC_CLK_PORT GPIOI // LCD时钟引脚 +#define LTDC_CLK_PIN GPIO_Pin_14 +#define LTDC_CLK_PINSOURCE GPIO_PinSource14 +#define LTDC_HSYNC_PORT GPIOI // 行同步 +#define LTDC_HSYNC_PIN GPIO_Pin_12 +#define LTDC_HSYNC_PINSOURCE GPIO_PinSource12 +#define LTDC_VSYNC_PORT GPIOI // 帧同步 +#define LTDC_VSYNC_PIN GPIO_Pin_13 +#define LTDC_VSYNC_PINSOURCE GPIO_PinSource13 +#define LTDC_DE_PORT GPIOK // 数据使能 +#define LTDC_DE_PIN GPIO_Pin_7 +#define LTDC_DE_PINSOURCE GPIO_PinSource7 + +#define LTDC_Black_PORT GPIOD // 背光 +#define LTDC_Black_PIN GPIO_Pin_13 +typedef struct { + int xs; + int ys; + int xe; + int ye; +} LCD_WindowStruct; +typedef struct { + int x_size; + int y_size; + int color; + int bkColor; + int effective; // 1,绘制窗口有效 + LCD_WindowStruct win; + LCD_WindowStruct realwin; + u16 *draw; + u16 *show; + void (*fresh)(void); + int LcdSwitchEn; + int LayerBuffEnter; +} LCD_Struct; // 函数:LCD层设置初始化 -// void LCD_LayerInit(void); +// 获取图像显示地址 +u32 *LCD_GetShowAddr(void); -//获取图像显示地址 -u32 *LCD_GetShowAddr (void); +// 获取图像绘制地址 +u32 *LCD_GetDrawAddr(void); -//获取图像绘制地址 -u32 *LCD_GetDrawAddr (void); +u32 LCD_SetLayer(u32 AddrIndex); +u32 LCD_SetDrawLayer(u32 Index); -u32 LCD_SetLayer (u32 AddrIndex); +u32 LCD_SetLcdColor(u32 color); -u32 LCD_SetDrawLayer (u32 Index); +u32 LCD_SetLcdBkColor(u32 color); -u32 LCD_SetLcdColor (u32 color); +u32 LCD_SetLcdColor16(u32 color); -u32 LCD_SetLcdBkColor (u32 color); +u32 LCD_SetLcdBkColor16(u32 color); -u32 LCD_SetLcdColor16 (u32 color); +u32 LCD_GetLcdColor(void); -u32 LCD_SetLcdBkColor16 (u32 color); +u32 LCD_GetLcdBkColor(void); -u32 LCD_GetLcdColor (void); +u32 LCD_GetLcdColor16(void); -u32 LCD_GetLcdBkColor (void); +u32 LCD_GetLcdBkColor16(void); -u32 LCD_GetLcdColor16 (void); +// 层复制 +void LCD_LayerCopy(int dst, int src); -u32 LCD_GetLcdBkColor16 (void); +// 开始在缓冲区绘制 +void LCD_LayerBufferOn(void); -//层复制 -void LCD_LayerCopy (int dst,int src); +// 显示缓冲层 +void LCD_LayerBuffShow(void); -//开始在缓冲区绘制 -void LCD_LayerBufferOn (void); +// 获取屏幕刷新状态,1,已刷新 +int LCD_GetLayerUpdataStat(void); -//显示缓冲层 -void LCD_LayerBuffShow (void); +// 进入缓冲区 +void LCD_EnterLayerBuff(void); -//获取屏幕刷新状态,1,已刷新 -int LCD_GetLayerUpdataStat (void); +// 切换层,不用复制显示,播放视频时用 +void LCD_SwitchLayerBuff(void); -//进入缓冲区 -void LCD_EnterLayerBuff (void); +// 退出缓冲区 +void LCD_ExitLayerBuff(void); -//切换层,不用复制显示,播放视频时用 -void LCD_SwitchLayerBuff (void); +// 设置活动窗口 +void LCD_SetWindow(int x_s, int y_s, int x_size, int y_size); -//退出缓冲区 -void LCD_ExitLayerBuff (void); +int LCD_GetWindowSizeX(void); - -//设置活动窗口 -void LCD_SetWindow (int x_s,int y_s,int x_size,int y_size); - -int LCD_GetWindowSizeX (void); - -int LCD_GetWindowSizeY (void); +int LCD_GetWindowSizeY(void); int LCD_GetLcdSizeX(void); -int LCD_GetLcdSizeY (void); +int LCD_GetLcdSizeY(void); -//设置绘制模式,1,不绘制背景,0,绘制背景 -void LCD_SetLcdDrawMode (int mode); +// 设置绘制模式,1,不绘制背景,0,绘制背景 +void LCD_SetLcdDrawMode(int mode); -void LCD_Clear (void); +void LCD_Clear(void); -//清除矩形内的显示 -void LCD_ClearRect (int x,int y,int x_size,int y_size); +// 清除矩形内的显示 +void LCD_ClearRect(int x, int y, int x_size, int y_size); -void LCD_DrawPoint (int x,int y,u32 mode); +void LCD_DrawPoint(int x, int y, u32 mode); -void LCD_DrawPointSafe (int x,int y,u32 mode); +void LCD_DrawPointSafe(int x, int y, u32 mode); -//以指定颜色画点,而不是前景色 -void LCD_DrawPointSafeColor (int x,int y,u16 color); +// 以指定颜色画点,而不是前景色 +void LCD_DrawPointSafeColor(int x, int y, u16 color); -//以指定色透明度画点0~32 -void LCD_DrawPointSafeColorAlpha (int x,int y,u16 color,u8 alpha); +// 以指定色透明度画点0~32 +void LCD_DrawPointSafeColorAlpha(int x, int y, u16 color, u8 alpha); -//填充矩形,已窗口坐标为原点 -void LCD_FillRectByColor (int x,int y,int x_size,int y_size); +// 填充矩形,已窗口坐标为原点 +void LCD_FillRectByColor(int x, int y, int x_size, int y_size); -//以透明度填充矩形,已窗口坐标为原点 -void LCD_FillRectByColorAlpha (int x,int y,int x_size,int y_size,u8 alpha); +// 以透明度填充矩形,已窗口坐标为原点 +void LCD_FillRectByColorAlpha(int x, int y, int x_size, int y_size, u8 alpha); -//void LCD_FillRect16 (u16 *buff,int xsize,int ysize); +// void LCD_FillRect16 (u16 *buff,int xsize,int ysize); -//void LCD_FillRectOff16 (u16 *buff,int x_s,int y_s,int xsize,int ysize); +// void LCD_FillRectOff16 (u16 *buff,int x_s,int y_s,int xsize,int ysize); -void LCD_FillRectOff16At (int s_x,int s_y,int s_xsize,int s_ysize,u16 *buff,int x_s,int y_s,int xsize,int ysize); +void LCD_FillRectOff16At(int s_x, int s_y, int s_xsize, int s_ysize, u16 *buff, + int x_s, int y_s, int xsize, int ysize); -//用有透明度的图片填充 -void LCD_FillRectOffAtAlpha (int s_x,int s_y,int s_xsize,int s_ysize,void *buff,int x_s,int y_s,int xsize,int ysize); +// 用有透明度的图片填充 +void LCD_FillRectOffAtAlpha(int s_x, int s_y, int s_xsize, int s_ysize, + void *buff, int x_s, int y_s, int xsize, int ysize); -void LCD_GetColors (u16 *buff,int x_s,int y_s,int x_size,int y_size); +void LCD_GetColors(u16 *buff, int x_s, int y_s, int x_size, int y_size); -#endif +#endif diff --git a/Project/Src/Drive/Source/lcd_rgb.c b/Project/Src/Drive/Source/lcd_rgb.c index b98061c..992231b 100644 --- a/Project/Src/Drive/Source/lcd_rgb.c +++ b/Project/Src/Drive/Source/lcd_rgb.c @@ -1,1223 +1,1059 @@ /*** - ***************************************************************************************** - * @file lcd.c - * @brief 使用STM32F29本身的控制器驱动液晶屏,一下代码移植于官方 STM32F429I_DISCOVERY - * 实验板的例程,并作出相应的修改 - ***************************************************************************************** - * - * - * - * - ****************************************************************************************** -***/ + ***************************************************************************************** + * @file lcd.c + * @brief 使用STM32F29本身的控制器驱动液晶屏,一下代码移植于官方 + *STM32F429I_DISCOVERY 实验板的例程,并作出相应的修改 + ***************************************************************************************** + * + * + * + * + ****************************************************************************************** + ***/ #include "lcd_rgb.h" #include "mymem.h" +#define COLOR565TO888(color) \ + ((((color) & 0xf800) << 8) | ((color) & 0x07e0) << 5 | \ + (((color) & 0x001f) << 3)) +#define COLOR888TO565(color) \ + ((((color) >> 8) & 0xf800) | (((color) >> 5) & 0x07e0) | \ + (((color) >> 3) & 0x001f)) +// 把RGB转化为565格式 +#define RGB(r, g, b) ((((r) >> 3) << 11) | (((g) >> 2) << 5) | ((b) >> 3)) +// RGB转灰度 +#define RGB2GRAY(rgb16) \ + (((((rgb16) & 0xf800) >> 8) + (((rgb16) & 0x07e0) >> 3) + \ + (((rgb16) & 0x001f) << 3)) / \ + 3) +// 灰度转RGB +#define GRAY2RGB(gray) \ + ((((gray) >> 3) << 11) | (((gray) >> 2) << 5) | ((gray) >> 3)) + // 函数:IO口初始化 -// -void LCD_GPIO_Config(void) -{ - GPIO_InitTypeDef GPIO_InitStruct; +void LCD_GPIO_Config(void) { + GPIO_InitTypeDef GPIO_InitStruct; - RCC_AHB1PeriphClockCmd( LCD_GPIO_CLK,ENABLE); - - GPIO_InitStruct.GPIO_Pin = LTDC_R0_PIN; - GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz; - GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; - GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; - GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; + RCC_AHB1PeriphClockCmd(LCD_GPIO_CLK, ENABLE); - // LCD 颜色 R 引脚配置 - GPIO_PinAFConfig(LTDC_R0_PORT, LTDC_R0_PINSOURCE, GPIO_AF_LTDC); - GPIO_PinAFConfig(LTDC_R1_PORT, LTDC_R1_PINSOURCE, GPIO_AF_LTDC); - GPIO_PinAFConfig(LTDC_R2_PORT, LTDC_R2_PINSOURCE, GPIO_AF_LTDC); - GPIO_PinAFConfig(LTDC_R3_PORT, LTDC_R3_PINSOURCE, GPIO_AF_LTDC); - GPIO_PinAFConfig(LTDC_R4_PORT, LTDC_R4_PINSOURCE, GPIO_AF_LTDC); - GPIO_PinAFConfig(LTDC_R5_PORT, LTDC_R5_PINSOURCE, GPIO_AF_LTDC); - GPIO_PinAFConfig(LTDC_R6_PORT, LTDC_R6_PINSOURCE, GPIO_AF_LTDC); - GPIO_PinAFConfig(LTDC_R7_PORT, LTDC_R7_PINSOURCE, GPIO_AF_LTDC); + GPIO_InitStruct.GPIO_Pin = LTDC_R0_PIN; + GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz; + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; + GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; + GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; - GPIO_InitStruct.GPIO_Pin = LTDC_R0_PIN; - GPIO_Init(LTDC_R0_PORT, &GPIO_InitStruct); + // LCD 颜色 R 引脚配置 + GPIO_PinAFConfig(LTDC_R0_PORT, LTDC_R0_PINSOURCE, GPIO_AF_LTDC); + GPIO_PinAFConfig(LTDC_R1_PORT, LTDC_R1_PINSOURCE, GPIO_AF_LTDC); + GPIO_PinAFConfig(LTDC_R2_PORT, LTDC_R2_PINSOURCE, GPIO_AF_LTDC); + GPIO_PinAFConfig(LTDC_R3_PORT, LTDC_R3_PINSOURCE, GPIO_AF_LTDC); + GPIO_PinAFConfig(LTDC_R4_PORT, LTDC_R4_PINSOURCE, GPIO_AF_LTDC); + GPIO_PinAFConfig(LTDC_R5_PORT, LTDC_R5_PINSOURCE, GPIO_AF_LTDC); + GPIO_PinAFConfig(LTDC_R6_PORT, LTDC_R6_PINSOURCE, GPIO_AF_LTDC); + GPIO_PinAFConfig(LTDC_R7_PORT, LTDC_R7_PINSOURCE, GPIO_AF_LTDC); - GPIO_InitStruct.GPIO_Pin = LTDC_R1_PIN; - GPIO_Init(LTDC_R1_PORT, &GPIO_InitStruct); + GPIO_InitStruct.GPIO_Pin = LTDC_R0_PIN; + GPIO_Init(LTDC_R0_PORT, &GPIO_InitStruct); - GPIO_InitStruct.GPIO_Pin = LTDC_R2_PIN; - GPIO_Init(LTDC_R2_PORT, &GPIO_InitStruct); + GPIO_InitStruct.GPIO_Pin = LTDC_R1_PIN; + GPIO_Init(LTDC_R1_PORT, &GPIO_InitStruct); - GPIO_InitStruct.GPIO_Pin = LTDC_R3_PIN; - GPIO_Init(LTDC_R3_PORT, &GPIO_InitStruct); + GPIO_InitStruct.GPIO_Pin = LTDC_R2_PIN; + GPIO_Init(LTDC_R2_PORT, &GPIO_InitStruct); - GPIO_InitStruct.GPIO_Pin = LTDC_R4_PIN; - GPIO_Init(LTDC_R4_PORT, &GPIO_InitStruct); + GPIO_InitStruct.GPIO_Pin = LTDC_R3_PIN; + GPIO_Init(LTDC_R3_PORT, &GPIO_InitStruct); - GPIO_InitStruct.GPIO_Pin = LTDC_R5_PIN; - GPIO_Init(LTDC_R5_PORT, &GPIO_InitStruct); + GPIO_InitStruct.GPIO_Pin = LTDC_R4_PIN; + GPIO_Init(LTDC_R4_PORT, &GPIO_InitStruct); - GPIO_InitStruct.GPIO_Pin = LTDC_R6_PIN; - GPIO_Init(LTDC_R6_PORT, &GPIO_InitStruct); + GPIO_InitStruct.GPIO_Pin = LTDC_R5_PIN; + GPIO_Init(LTDC_R5_PORT, &GPIO_InitStruct); - GPIO_InitStruct.GPIO_Pin = LTDC_R7_PIN; - GPIO_Init(LTDC_R7_PORT, &GPIO_InitStruct); + GPIO_InitStruct.GPIO_Pin = LTDC_R6_PIN; + GPIO_Init(LTDC_R6_PORT, &GPIO_InitStruct); - - // LCD 颜色 G 引脚配置 - - GPIO_PinAFConfig(LTDC_G0_PORT, LTDC_G0_PINSOURCE, GPIO_AF_LTDC); - GPIO_PinAFConfig(LTDC_G1_PORT, LTDC_G1_PINSOURCE, GPIO_AF_LTDC); - GPIO_PinAFConfig(LTDC_G2_PORT, LTDC_G2_PINSOURCE, GPIO_AF_LTDC); - GPIO_PinAFConfig(LTDC_G3_PORT, LTDC_G3_PINSOURCE, GPIO_AF_LTDC); - GPIO_PinAFConfig(LTDC_G4_PORT, LTDC_G4_PINSOURCE, GPIO_AF_LTDC); - GPIO_PinAFConfig(LTDC_G5_PORT, LTDC_G5_PINSOURCE, GPIO_AF_LTDC); - GPIO_PinAFConfig(LTDC_G6_PORT, LTDC_G6_PINSOURCE, GPIO_AF_LTDC); - GPIO_PinAFConfig(LTDC_G7_PORT, LTDC_G7_PINSOURCE, GPIO_AF_LTDC); - - GPIO_InitStruct.GPIO_Pin = LTDC_G0_PIN; - GPIO_Init(LTDC_G0_PORT, &GPIO_InitStruct); + GPIO_InitStruct.GPIO_Pin = LTDC_R7_PIN; + GPIO_Init(LTDC_R7_PORT, &GPIO_InitStruct); - GPIO_InitStruct.GPIO_Pin = LTDC_G1_PIN; - GPIO_Init(LTDC_G1_PORT, &GPIO_InitStruct); + // LCD 颜色 G 引脚配置 - GPIO_InitStruct.GPIO_Pin = LTDC_G2_PIN; - GPIO_Init(LTDC_G2_PORT, &GPIO_InitStruct); + GPIO_PinAFConfig(LTDC_G0_PORT, LTDC_G0_PINSOURCE, GPIO_AF_LTDC); + GPIO_PinAFConfig(LTDC_G1_PORT, LTDC_G1_PINSOURCE, GPIO_AF_LTDC); + GPIO_PinAFConfig(LTDC_G2_PORT, LTDC_G2_PINSOURCE, GPIO_AF_LTDC); + GPIO_PinAFConfig(LTDC_G3_PORT, LTDC_G3_PINSOURCE, GPIO_AF_LTDC); + GPIO_PinAFConfig(LTDC_G4_PORT, LTDC_G4_PINSOURCE, GPIO_AF_LTDC); + GPIO_PinAFConfig(LTDC_G5_PORT, LTDC_G5_PINSOURCE, GPIO_AF_LTDC); + GPIO_PinAFConfig(LTDC_G6_PORT, LTDC_G6_PINSOURCE, GPIO_AF_LTDC); + GPIO_PinAFConfig(LTDC_G7_PORT, LTDC_G7_PINSOURCE, GPIO_AF_LTDC); - GPIO_InitStruct.GPIO_Pin = LTDC_G3_PIN; - GPIO_Init(LTDC_G3_PORT, &GPIO_InitStruct); + GPIO_InitStruct.GPIO_Pin = LTDC_G0_PIN; + GPIO_Init(LTDC_G0_PORT, &GPIO_InitStruct); - GPIO_InitStruct.GPIO_Pin = LTDC_G4_PIN; - GPIO_Init(LTDC_G4_PORT, &GPIO_InitStruct); + GPIO_InitStruct.GPIO_Pin = LTDC_G1_PIN; + GPIO_Init(LTDC_G1_PORT, &GPIO_InitStruct); - GPIO_InitStruct.GPIO_Pin = LTDC_G5_PIN; - GPIO_Init(LTDC_G5_PORT, &GPIO_InitStruct); + GPIO_InitStruct.GPIO_Pin = LTDC_G2_PIN; + GPIO_Init(LTDC_G2_PORT, &GPIO_InitStruct); - GPIO_InitStruct.GPIO_Pin = LTDC_G6_PIN; - GPIO_Init(LTDC_G6_PORT, &GPIO_InitStruct); + GPIO_InitStruct.GPIO_Pin = LTDC_G3_PIN; + GPIO_Init(LTDC_G3_PORT, &GPIO_InitStruct); - GPIO_InitStruct.GPIO_Pin = LTDC_G7_PIN; - GPIO_Init(LTDC_G7_PORT, &GPIO_InitStruct); + GPIO_InitStruct.GPIO_Pin = LTDC_G4_PIN; + GPIO_Init(LTDC_G4_PORT, &GPIO_InitStruct); - - // LCD 颜色 B 引脚配置 - - GPIO_PinAFConfig(LTDC_B0_PORT, LTDC_B0_PINSOURCE, GPIO_AF_LTDC); - GPIO_PinAFConfig(LTDC_B1_PORT, LTDC_B1_PINSOURCE, GPIO_AF_LTDC); - GPIO_PinAFConfig(LTDC_B2_PORT, LTDC_B2_PINSOURCE, GPIO_AF_LTDC); - GPIO_PinAFConfig(LTDC_B3_PORT, LTDC_B3_PINSOURCE, GPIO_AF_LTDC); - GPIO_PinAFConfig(LTDC_B4_PORT, LTDC_B4_PINSOURCE, GPIO_AF_LTDC); - GPIO_PinAFConfig(LTDC_B5_PORT, LTDC_B5_PINSOURCE, GPIO_AF_LTDC); - GPIO_PinAFConfig(LTDC_B6_PORT, LTDC_B6_PINSOURCE, GPIO_AF_LTDC); - GPIO_PinAFConfig(LTDC_B7_PORT, LTDC_B7_PINSOURCE, GPIO_AF_LTDC); + GPIO_InitStruct.GPIO_Pin = LTDC_G5_PIN; + GPIO_Init(LTDC_G5_PORT, &GPIO_InitStruct); - GPIO_InitStruct.GPIO_Pin = LTDC_B0_PIN; - GPIO_Init(LTDC_B0_PORT, &GPIO_InitStruct); - - GPIO_InitStruct.GPIO_Pin = LTDC_B1_PIN; - GPIO_Init(LTDC_B1_PORT, &GPIO_InitStruct); - - GPIO_InitStruct.GPIO_Pin = LTDC_B2_PIN; - GPIO_Init(LTDC_B2_PORT, &GPIO_InitStruct); + GPIO_InitStruct.GPIO_Pin = LTDC_G6_PIN; + GPIO_Init(LTDC_G6_PORT, &GPIO_InitStruct); - GPIO_InitStruct.GPIO_Pin = LTDC_B3_PIN; - GPIO_Init(LTDC_B3_PORT, &GPIO_InitStruct); + GPIO_InitStruct.GPIO_Pin = LTDC_G7_PIN; + GPIO_Init(LTDC_G7_PORT, &GPIO_InitStruct); - GPIO_InitStruct.GPIO_Pin = LTDC_B4_PIN; - GPIO_Init(LTDC_B4_PORT, &GPIO_InitStruct); + // LCD 颜色 B 引脚配置 - GPIO_InitStruct.GPIO_Pin = LTDC_B5_PIN; - GPIO_Init(LTDC_B5_PORT, &GPIO_InitStruct); + GPIO_PinAFConfig(LTDC_B0_PORT, LTDC_B0_PINSOURCE, GPIO_AF_LTDC); + GPIO_PinAFConfig(LTDC_B1_PORT, LTDC_B1_PINSOURCE, GPIO_AF_LTDC); + GPIO_PinAFConfig(LTDC_B2_PORT, LTDC_B2_PINSOURCE, GPIO_AF_LTDC); + GPIO_PinAFConfig(LTDC_B3_PORT, LTDC_B3_PINSOURCE, GPIO_AF_LTDC); + GPIO_PinAFConfig(LTDC_B4_PORT, LTDC_B4_PINSOURCE, GPIO_AF_LTDC); + GPIO_PinAFConfig(LTDC_B5_PORT, LTDC_B5_PINSOURCE, GPIO_AF_LTDC); + GPIO_PinAFConfig(LTDC_B6_PORT, LTDC_B6_PINSOURCE, GPIO_AF_LTDC); + GPIO_PinAFConfig(LTDC_B7_PORT, LTDC_B7_PINSOURCE, GPIO_AF_LTDC); - GPIO_InitStruct.GPIO_Pin = LTDC_B6_PIN; - GPIO_Init(LTDC_B6_PORT, &GPIO_InitStruct); + GPIO_InitStruct.GPIO_Pin = LTDC_B0_PIN; + GPIO_Init(LTDC_B0_PORT, &GPIO_InitStruct); - GPIO_InitStruct.GPIO_Pin = LTDC_B7_PIN; - GPIO_Init(LTDC_B7_PORT, &GPIO_InitStruct); + GPIO_InitStruct.GPIO_Pin = LTDC_B1_PIN; + GPIO_Init(LTDC_B1_PORT, &GPIO_InitStruct); - - //控制线 - GPIO_PinAFConfig(LTDC_CLK_PORT, LTDC_CLK_PINSOURCE, GPIO_AF_LTDC); - GPIO_PinAFConfig(LTDC_HSYNC_PORT, LTDC_HSYNC_PINSOURCE,GPIO_AF_LTDC); - GPIO_PinAFConfig(LTDC_VSYNC_PORT, LTDC_VSYNC_PINSOURCE,GPIO_AF_LTDC); - GPIO_PinAFConfig(LTDC_DE_PORT, LTDC_DE_PINSOURCE, GPIO_AF_LTDC); - - GPIO_InitStruct.GPIO_Pin = LTDC_CLK_PIN; - GPIO_Init(LTDC_CLK_PORT, &GPIO_InitStruct); + GPIO_InitStruct.GPIO_Pin = LTDC_B2_PIN; + GPIO_Init(LTDC_B2_PORT, &GPIO_InitStruct); - GPIO_InitStruct.GPIO_Pin = LTDC_HSYNC_PIN; - GPIO_Init(LTDC_HSYNC_PORT, &GPIO_InitStruct); + GPIO_InitStruct.GPIO_Pin = LTDC_B3_PIN; + GPIO_Init(LTDC_B3_PORT, &GPIO_InitStruct); - GPIO_InitStruct.GPIO_Pin = LTDC_VSYNC_PIN; - GPIO_Init(LTDC_VSYNC_PORT, &GPIO_InitStruct); + GPIO_InitStruct.GPIO_Pin = LTDC_B4_PIN; + GPIO_Init(LTDC_B4_PORT, &GPIO_InitStruct); - GPIO_InitStruct.GPIO_Pin = LTDC_DE_PIN; - GPIO_Init(LTDC_DE_PORT, &GPIO_InitStruct); - - //背光 - GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; - GPIO_InitStruct.GPIO_Pin = LTDC_Black_PIN; - GPIO_Init(LTDC_Black_PORT, &GPIO_InitStruct); + GPIO_InitStruct.GPIO_Pin = LTDC_B5_PIN; + GPIO_Init(LTDC_B5_PORT, &GPIO_InitStruct); - GPIO_SetBits(LTDC_Black_PORT,LTDC_Black_PIN); + GPIO_InitStruct.GPIO_Pin = LTDC_B6_PIN; + GPIO_Init(LTDC_B6_PORT, &GPIO_InitStruct); + + GPIO_InitStruct.GPIO_Pin = LTDC_B7_PIN; + GPIO_Init(LTDC_B7_PORT, &GPIO_InitStruct); + + // 控制线 + GPIO_PinAFConfig(LTDC_CLK_PORT, LTDC_CLK_PINSOURCE, GPIO_AF_LTDC); + GPIO_PinAFConfig(LTDC_HSYNC_PORT, LTDC_HSYNC_PINSOURCE, GPIO_AF_LTDC); + GPIO_PinAFConfig(LTDC_VSYNC_PORT, LTDC_VSYNC_PINSOURCE, GPIO_AF_LTDC); + GPIO_PinAFConfig(LTDC_DE_PORT, LTDC_DE_PINSOURCE, GPIO_AF_LTDC); + + GPIO_InitStruct.GPIO_Pin = LTDC_CLK_PIN; + GPIO_Init(LTDC_CLK_PORT, &GPIO_InitStruct); + + GPIO_InitStruct.GPIO_Pin = LTDC_HSYNC_PIN; + GPIO_Init(LTDC_HSYNC_PORT, &GPIO_InitStruct); + + GPIO_InitStruct.GPIO_Pin = LTDC_VSYNC_PIN; + GPIO_Init(LTDC_VSYNC_PORT, &GPIO_InitStruct); + + GPIO_InitStruct.GPIO_Pin = LTDC_DE_PIN; + GPIO_Init(LTDC_DE_PORT, &GPIO_InitStruct); + + // 背光 + GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; + GPIO_InitStruct.GPIO_Pin = LTDC_Black_PIN; + GPIO_Init(LTDC_Black_PORT, &GPIO_InitStruct); + + GPIO_SetBits(LTDC_Black_PORT, LTDC_Black_PIN); } - - - -void LCD_Backlight (u8 power) -{ - if (power) - { - GPIO_SetBits(LTDC_Black_PORT,LTDC_Black_PIN); - } - else - { - GPIO_ResetBits(LTDC_Black_PORT,LTDC_Black_PIN); - } +void LCD_Backlight(u8 power) { + if (power) { + GPIO_SetBits(LTDC_Black_PORT, LTDC_Black_PIN); + } else { + GPIO_ResetBits(LTDC_Black_PORT, LTDC_Black_PIN); + } } +static u32 *LCD_ADDR = ((u32 *)(LCD_MemoryAdd + LCD_MemoryAdd_OFFSET * 0)); +static u32 *LCD_ADDR1 = ((u32 *)(LCD_MemoryAdd + LCD_MemoryAdd_OFFSET * 1)); +#define LCD_ADDR_BUFF0 \ + ((u32)(LCD_MemoryAdd + (uint32_t)LCD_Width * LCD_Height * 4 * 0)) +#define LCD_ADDR_BUFF1 \ + ((u32)(LCD_MemoryAdd + (uint32_t)LCD_Width * LCD_Height * 4 * 1)) +#define LCD_ADDR_BUFF2 \ + ((u32)(LCD_MemoryAdd + (uint32_t)LCD_Width * LCD_Height * 4 * 2)) - - -static u32* LCD_ADDR =((u32*)(LCD_MemoryAdd + LCD_MemoryAdd_OFFSET*0)); -static u32* LCD_ADDR1 =((u32*)(LCD_MemoryAdd + LCD_MemoryAdd_OFFSET*1)); -#define LCD_ADDR_BUFF0 ((u32)(LCD_MemoryAdd + (uint32_t)LCD_Width*LCD_Height*4*0)) -#define LCD_ADDR_BUFF1 ((u32)(LCD_MemoryAdd + (uint32_t)LCD_Width*LCD_Height*4*1)) -#define LCD_ADDR_BUFF2 ((u32)(LCD_MemoryAdd + (uint32_t)LCD_Width*LCD_Height*4*2)) - -const static u32 g_lcdAddrTable[3]= -{ - (u32)LCD_ADDR_BUFF0, - (u32)LCD_ADDR_BUFF1, - (u32)LCD_ADDR_BUFF2, +const static u32 g_lcdAddrTable[3] = { + (u32)LCD_ADDR_BUFF0, + (u32)LCD_ADDR_BUFF1, + (u32)LCD_ADDR_BUFF2, }; -static LCD_Struct g_lcd={0}; - - - - - - - +static LCD_Struct g_lcd = {0}; // 函数:初始化LCD控制器 // 说明:在emWin初始化里被调用 // -void LCD_Init(void) -{ - u16 LCD_PLLSAIN = 0; //用于倍频的PLLSAIN参数,可取范围为50~432 - u8 LCD_PLLSAIR = 3; //用于分频的PLLSAIR参数,可取范围为2~7 - u8 LCD_CLKDIV = 8; //LCD时钟分频参数,默认设置为8分频,数值上等于RCC_PLLSAIDivR_Div8 - - LTDC_InitTypeDef LTDC_InitStruct; - RCC_APB2PeriphClockCmd(RCC_APB2Periph_LTDC, ENABLE); - RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2D, ENABLE); +void LCD_Init(void) { + u16 LCD_PLLSAIN = 0; // 用于倍频的PLLSAIN参数,可取范围为50~432 + u8 LCD_PLLSAIR = 3; // 用于分频的PLLSAIR参数,可取范围为2~7 + u8 LCD_CLKDIV = + 8; // LCD时钟分频参数,默认设置为8分频,数值上等于RCC_PLLSAIDivR_Div8 - LCD_GPIO_Config(); //初始化LCD引脚 + LTDC_InitTypeDef LTDC_InitStruct; + RCC_APB2PeriphClockCmd(RCC_APB2Periph_LTDC, ENABLE); + RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2D, ENABLE); - LCD_PLLSAIN = LCD_CLK * LCD_PLLSAIR * LCD_CLKDIV; //根据需要使用的LCD时钟计算PLLSAIN参数,可取范围为50~432 - RCC_PLLSAIConfig(LCD_PLLSAIN,7,LCD_PLLSAIR); //时钟配置 - RCC_LTDCCLKDivConfig(RCC_PLLSAIDivR_Div8); //LCD时钟分频设置,要和LCD_CLKDIV对应 - RCC_PLLSAICmd(ENABLE); //使能PLLSAI时钟 - while(RCC_GetFlagStatus(RCC_FLAG_PLLSAIRDY) == RESET); //等待时钟配置完成 - - LTDC_InitStruct.LTDC_HSPolarity = LTDC_HSPolarity_AL; - LTDC_InitStruct.LTDC_VSPolarity = LTDC_VSPolarity_AL; - LTDC_InitStruct.LTDC_DEPolarity = LTDC_DEPolarity_AL; - LTDC_InitStruct.LTDC_PCPolarity = LTDC_PCPolarity_IPC; - - LTDC_InitStruct.LTDC_BackgroundRedValue = 0; - LTDC_InitStruct.LTDC_BackgroundGreenValue = 0; - LTDC_InitStruct.LTDC_BackgroundBlueValue = 0; + LCD_GPIO_Config(); // 初始化LCD引脚 - LTDC_InitStruct.LTDC_HorizontalSync =HSW; - LTDC_InitStruct.LTDC_VerticalSync = VSW; - LTDC_InitStruct.LTDC_AccumulatedHBP =HBP; - LTDC_InitStruct.LTDC_AccumulatedVBP = VBP; - LTDC_InitStruct.LTDC_AccumulatedActiveW = LCD_Width+HBP; - LTDC_InitStruct.LTDC_AccumulatedActiveH = LCD_Height+VBP; - LTDC_InitStruct.LTDC_TotalWidth =LCD_Width + HBP + HFP; - LTDC_InitStruct.LTDC_TotalHeigh =LCD_Height + VBP + VFP; - - LTDC_Init(<DC_InitStruct); //初始化LCD控制器 - LTDC_ITConfig (LTDC_IT_LI,ENABLE); - NVIC_SetPriority(LTDC_IRQn, 0); - NVIC_EnableIRQ(LTDC_IRQn); - LTDC_Cmd(ENABLE); //使能LCD控制器 - - LCD_LayerInit(); - - g_lcd.x_size = LCD_Width; - g_lcd.y_size = LCD_Height; - g_lcd.show = (u16 *)g_lcdAddrTable[0]; - g_lcd.draw = (u16 *)g_lcdAddrTable[1]; - LCD_SetWindow(0, 0, g_lcd.x_size, g_lcd.y_size); - g_lcd.bkColor = 0x0; - -} + LCD_PLLSAIN = + LCD_CLK * LCD_PLLSAIR * + LCD_CLKDIV; // 根据需要使用的LCD时钟计算PLLSAIN参数,可取范围为50~432 + RCC_PLLSAIConfig(LCD_PLLSAIN, 7, LCD_PLLSAIR); // 时钟配置 + RCC_LTDCCLKDivConfig( + RCC_PLLSAIDivR_Div8); // LCD时钟分频设置,要和LCD_CLKDIV对应 + RCC_PLLSAICmd(ENABLE); // 使能PLLSAI时钟 + while (RCC_GetFlagStatus(RCC_FLAG_PLLSAIRDY) == RESET) + ; // 等待时钟配置完成 + LTDC_InitStruct.LTDC_HSPolarity = LTDC_HSPolarity_AL; + LTDC_InitStruct.LTDC_VSPolarity = LTDC_VSPolarity_AL; + LTDC_InitStruct.LTDC_DEPolarity = LTDC_DEPolarity_AL; + LTDC_InitStruct.LTDC_PCPolarity = LTDC_PCPolarity_IPC; + LTDC_InitStruct.LTDC_BackgroundRedValue = 0; + LTDC_InitStruct.LTDC_BackgroundGreenValue = 0; + LTDC_InitStruct.LTDC_BackgroundBlueValue = 0; + LTDC_InitStruct.LTDC_HorizontalSync = HSW; + LTDC_InitStruct.LTDC_VerticalSync = VSW; + LTDC_InitStruct.LTDC_AccumulatedHBP = HBP; + LTDC_InitStruct.LTDC_AccumulatedVBP = VBP; + LTDC_InitStruct.LTDC_AccumulatedActiveW = LCD_Width + HBP; + LTDC_InitStruct.LTDC_AccumulatedActiveH = LCD_Height + VBP; + LTDC_InitStruct.LTDC_TotalWidth = LCD_Width + HBP + HFP; + LTDC_InitStruct.LTDC_TotalHeigh = LCD_Height + VBP + VFP; + LTDC_Init(<DC_InitStruct); // 初始化LCD控制器 + LTDC_ITConfig(LTDC_IT_LI, ENABLE); + NVIC_SetPriority(LTDC_IRQn, 0); + NVIC_EnableIRQ(LTDC_IRQn); + LTDC_Cmd(ENABLE); // 使能LCD控制器 + LCD_LayerInit(); + g_lcd.x_size = LCD_Width; + g_lcd.y_size = LCD_Height; + g_lcd.show = (u16 *)g_lcdAddrTable[0]; + g_lcd.draw = (u16 *)g_lcdAddrTable[1]; + LCD_SetWindow(0, 0, g_lcd.x_size, g_lcd.y_size); + g_lcd.bkColor = 0x0; +} // 函数:LCD层设置初始化 -// -void LCD_LayerInit(void) -{ - LTDC_Layer_InitTypeDef LTDC_Layer_InitStruct; +// +void LCD_LayerInit(void) { + LTDC_Layer_InitTypeDef LTDC_Layer_InitStruct; - LTDC_Layer_InitStruct.LTDC_HorizontalStart = HBP + 1; - LTDC_Layer_InitStruct.LTDC_HorizontalStop = (LCD_Width + HBP); - LTDC_Layer_InitStruct.LTDC_VerticalStart = VBP + 1; - LTDC_Layer_InitStruct.LTDC_VerticalStop = (LCD_Height + VBP); - //LTDC_Layer_InitStruct.LTDC_PixelFormat = LTDC_Pixelformat_ARGB8888; //像素格式设置 - LTDC_Layer_InitStruct.LTDC_PixelFormat = LTDC_Pixelformat_RGB565; //像素格式设置 - LTDC_Layer_InitStruct.LTDC_ConstantAlpha = 255; - LTDC_Layer_InitStruct.LTDC_DefaultColorBlue = 0; // 默认的颜色 - LTDC_Layer_InitStruct.LTDC_DefaultColorGreen = 0; - LTDC_Layer_InitStruct.LTDC_DefaultColorRed = 0; - LTDC_Layer_InitStruct.LTDC_DefaultColorAlpha = 0; - LTDC_Layer_InitStruct.LTDC_BlendingFactor_1 = LTDC_BlendingFactor1_CA; - LTDC_Layer_InitStruct.LTDC_BlendingFactor_2 = LTDC_BlendingFactor2_CA; - LTDC_Layer_InitStruct.LTDC_CFBLineNumber = LCD_Height; //显示区域的行数 - LTDC_Layer_InitStruct.LTDC_CFBStartAdress = LCD_MemoryAdd; //第一层的起始地址 - - //这里ARGB8888和RGB888使用相同的计算方式 - { -// LTDC_Layer_InitStruct.LTDC_CFBLineLength = ((LCD_Width * 4) + 3); //每行的像素占的总字节数 -// LTDC_Layer_InitStruct.LTDC_CFBPitch = (LCD_Width * 4); //行间距,某像素的起始处到下一行的起始处的增量 - LTDC_Layer_InitStruct.LTDC_CFBLineLength = ((LCD_Width * 2) + 3); //每行的像素占的总字节数 - LTDC_Layer_InitStruct.LTDC_CFBPitch = (LCD_Width * 2); //行间距,某像素的起始处到下一行的起始处的增量 - } - LTDC_LayerInit(LTDC_Layer1, <DC_Layer_InitStruct); //初始化层1 - LTDC_LayerCmd(LTDC_Layer1, ENABLE); //使能层1 + LTDC_Layer_InitStruct.LTDC_HorizontalStart = HBP + 1; + LTDC_Layer_InitStruct.LTDC_HorizontalStop = (LCD_Width + HBP); + LTDC_Layer_InitStruct.LTDC_VerticalStart = VBP + 1; + LTDC_Layer_InitStruct.LTDC_VerticalStop = (LCD_Height + VBP); + // LTDC_Layer_InitStruct.LTDC_PixelFormat = LTDC_Pixelformat_ARGB8888; + // //像素格式设置 + LTDC_Layer_InitStruct.LTDC_PixelFormat = + LTDC_Pixelformat_RGB565; // 像素格式设置 + LTDC_Layer_InitStruct.LTDC_ConstantAlpha = 255; + LTDC_Layer_InitStruct.LTDC_DefaultColorBlue = 0; // 默认的颜色 + LTDC_Layer_InitStruct.LTDC_DefaultColorGreen = 0; + LTDC_Layer_InitStruct.LTDC_DefaultColorRed = 0; + LTDC_Layer_InitStruct.LTDC_DefaultColorAlpha = 0; + LTDC_Layer_InitStruct.LTDC_BlendingFactor_1 = LTDC_BlendingFactor1_CA; + LTDC_Layer_InitStruct.LTDC_BlendingFactor_2 = LTDC_BlendingFactor2_CA; + LTDC_Layer_InitStruct.LTDC_CFBLineNumber = LCD_Height; // 显示区域的行数 + LTDC_Layer_InitStruct.LTDC_CFBStartAdress = LCD_MemoryAdd; // 第一层的起始地址 -#if ( LCD_NUM_LAYERS == 2 ) //当定义了双层时 + // 这里ARGB8888和RGB888使用相同的计算方式 + { + LTDC_Layer_InitStruct.LTDC_CFBLineLength = + ((LCD_Width * 2) + 3); // 每行的像素占的总字节数 + LTDC_Layer_InitStruct.LTDC_CFBPitch = + (LCD_Width * 2); // 行间距,某像素的起始处到下一行的起始处的增量 + } + LTDC_LayerInit(LTDC_Layer1, <DC_Layer_InitStruct); // 初始化层1 + LTDC_LayerCmd(LTDC_Layer1, ENABLE); // 使能层1 - LTDC_Layer_InitStruct.LTDC_PixelFormat = ColorMode_1; //像素格式设置 - LTDC_Layer_InitStruct.LTDC_BlendingFactor_1 = LTDC_BlendingFactor1_PAxCA; - LTDC_Layer_InitStruct.LTDC_BlendingFactor_2 = LTDC_BlendingFactor2_PAxCA; - LTDC_Layer_InitStruct.LTDC_CFBStartAdress = LCD_MemoryAdd + LCD_MemoryAdd_OFFSET; //层2的起始地址 +#if (LCD_NUM_LAYERS == 2) // 当定义了双层时 - if( ColorMode_1 == LCD_RGB565 || ColorMode_1 == LCD_ARGB1555 ) //判断颜色格式 - { - LTDC_Layer_InitStruct.LTDC_CFBLineLength = ((LCD_Width * 2) + 3); //每行的像素占的总字节数 - LTDC_Layer_InitStruct.LTDC_CFBPitch = (LCD_Width * 2); //行间距,某像素的起始处到下一行的起始处的增量 - } - else //这里ARGB8888和RGB888使用相同的计算方式 - { - LTDC_Layer_InitStruct.LTDC_CFBLineLength = ((LCD_Width * 4) + 3); //每行的像素占的总字节数 - LTDC_Layer_InitStruct.LTDC_CFBPitch = (LCD_Width * 4); //行间距,某像素的起始处到下一行的起始处的增量 - } - LTDC_LayerInit(LTDC_Layer2, <DC_Layer_InitStruct); //初始化层2 - LTDC_LayerCmd(LTDC_Layer2, ENABLE); //使能层2 + LTDC_Layer_InitStruct.LTDC_PixelFormat = ColorMode_1; // 像素格式设置 + LTDC_Layer_InitStruct.LTDC_BlendingFactor_1 = LTDC_BlendingFactor1_PAxCA; + LTDC_Layer_InitStruct.LTDC_BlendingFactor_2 = LTDC_BlendingFactor2_PAxCA; + LTDC_Layer_InitStruct.LTDC_CFBStartAdress = + LCD_MemoryAdd + LCD_MemoryAdd_OFFSET; // 层2的起始地址 + + if (ColorMode_1 == LCD_RGB565 || ColorMode_1 == LCD_ARGB1555) // 判断颜色格式 + { + LTDC_Layer_InitStruct.LTDC_CFBLineLength = + ((LCD_Width * 2) + 3); // 每行的像素占的总字节数 + LTDC_Layer_InitStruct.LTDC_CFBPitch = + (LCD_Width * 2); // 行间距,某像素的起始处到下一行的起始处的增量 + } else // 这里ARGB8888和RGB888使用相同的计算方式 + { + LTDC_Layer_InitStruct.LTDC_CFBLineLength = + ((LCD_Width * 4) + 3); // 每行的像素占的总字节数 + LTDC_Layer_InitStruct.LTDC_CFBPitch = + (LCD_Width * 4); // 行间距,某像素的起始处到下一行的起始处的增量 + } + LTDC_LayerInit(LTDC_Layer2, <DC_Layer_InitStruct); // 初始化层2 + LTDC_LayerCmd(LTDC_Layer2, ENABLE); // 使能层2 #endif - LTDC_ReloadConfig(LTDC_IMReload); //重新载入参数 - LTDC_DitherCmd(ENABLE); //使能颜色抖动,24位色必须打开,否则无法达到24位色的效果 + LTDC_ReloadConfig(LTDC_IMReload); // 重新载入参数 + LTDC_DitherCmd( + ENABLE); // 使能颜色抖动,24位色必须打开,否则无法达到24位色的效果 } - - - - - - - - - - - - - - - - - - - -void LTDC_ISR_Handler (void) -{ - LTDC_ClearFlag (LTDC_FLAG_LI); - if (g_lcd.LcdSwitchEn==1) - { - g_lcd.LcdSwitchEn=0; - LTDC_Layer1->CFBAR =(u32 )g_lcd.show; - LTDC->SRCR=1; - } -} - - - -static int LCD_UpDataWindow(void) -{ - LCD_WindowStruct *win = &g_lcd.win; - LCD_WindowStruct *draw = &g_lcd.realwin; - int real = 1; - if (win->xs >= 0 && win->xs < g_lcd.x_size) - draw->xs = win->xs; - else if (win->xs < 0) - draw->xs = 0; - else if (win->xs >= g_lcd.x_size) - real = 0;//在显示区域外 - - if (win->ys >= 0 && win->ys < g_lcd.y_size) - draw->ys = win->ys; - else if (win->ys < 0) - draw->ys = 0; - else if (win->ys >= g_lcd.y_size) - real = 0;//在显示区域外 - - if (win->xe >= 0 && win->xe < g_lcd.x_size) - draw->xe = win->xe; - else if (win->xe < 0) - real = 0;//在显示区域外 - else if (win->xe>=g_lcd.x_size) - draw->xe = g_lcd.x_size-1; - - if (win->ye >= 0 && win->ye < g_lcd.y_size) - draw->ye = win->ye; - else if (win->ye < 0) - real = 0;//在显示区域外 - else if (win->ye >= g_lcd.y_size) - draw->ye = g_lcd.y_size - 1; - - if ((win->xs > win->xe) || (win->ys > win->ye)) - real = 0; - g_lcd.effective = real; - return real; -} - - - -//设置活动窗口 -void LCD_SetWindow (int x_s,int y_s,int x_size,int y_size) -{ - g_lcd.win.xs = x_s; - g_lcd.win.ys = y_s; - g_lcd.win.xe = x_s + x_size - 1; - g_lcd.win.ye = y_s + y_size - 1; - LCD_UpDataWindow(); -} - - -//int LCD_GetWindowSizeX (void) -//{ -// return g_lcd_struct.WindowDstX-g_lcd_struct.WindowSrcX+1; -//} - -//int LCD_GetWindowSizeY (void) -//{ -// return g_lcd_struct.WindowDstY-g_lcd_struct.WindowSrcY+1; -//} - -int LCD_GetLcdSizeX(void) -{ - return LCD_Width; -} - -int LCD_GetLcdSizeY (void) -{ - return LCD_Height; -} - - - -//获取图像显示地址 -u32 *LCD_GetShowAddr (void) -{ - uint32_t *ret=(u32*)LTDC_Layer1->CFBAR; - ret=(u32*)g_lcd.show; - return ret; -} - -//获取图像绘制地址 -u32 *LCD_GetDrawAddr (void) -{ - uint32_t *ret=0; - ret=(u32*)g_lcd.draw; - return ret; -} - - - -//设置屏幕显示地址,这个地址直接输出到屏幕上,返回上一个输出到屏幕的地址 -u32 LCD_SetLayer (u32 AddrIndex) -{ - uint32_t ret=LTDC_Layer1->CFBAR; - if (AddrIndex<3) - { - g_lcd.show=(u16 * )g_lcdAddrTable[AddrIndex]; - LTDC_Layer1->CFBAR = g_lcdAddrTable[AddrIndex]; - LTDC->SRCR=1; - } - for (int i=0;i<3;i++) - { - if (ret==g_lcdAddrTable[i]) - { - ret=i; - break; - } - } - if (ret>=3) ret=0; - return ret; -} - -//设置绘图地址,所有绘制操作在这个地址执行 -u32 LCD_SetDrawLayer (u32 Index) -{ - u32 ret=(u32)g_lcd.draw; - if (Index<3) - { - g_lcd.draw=(u16*)g_lcdAddrTable[Index]; - } - for (int i=0;i<3;i++) - { - if (ret==g_lcdAddrTable[i]) - { - ret=i; - break; - } - } - if (ret>=3) ret=0; - return ret; -} - - -u32 LCD_SetLcdColor (u32 color) -{ - u32 ret=g_lcd.color; - //g_lcd_struct.Color=color; - g_lcd.color=COLOR888TO565(color); - return ret; -} - -u32 LCD_SetLcdBkColor (u32 color) -{ - u32 ret=g_lcd.bkColor; - //g_lcd_struct.BackColor=color; - ret=g_lcd.bkColor=COLOR888TO565(color); - return ret; -} - - -u32 LCD_SetLcdColor16 (u32 color) -{ - u32 ret=g_lcd.color; - g_lcd.color=(color); - return ret; -} - -u32 LCD_SetLcdBkColor16 (u32 color) -{ - u32 ret=ret=g_lcd.bkColor; - ret=g_lcd.bkColor=(color); - return ret; -} - - -u32 LCD_GetLcdColor (void) -{ - u32 ret=g_lcd.color; - return COLOR565TO888(ret); -} - -u32 LCD_GetLcdBkColor (void) -{ - u32 ret=g_lcd.bkColor; - return COLOR565TO888(ret); -} - - -u32 LCD_GetLcdColor16 (void) -{ - u32 ret=g_lcd.color; - return ret; -} - -u32 LCD_GetLcdBkColor16 (void) -{ - u32 ret=g_lcd.bkColor; - return ret; -} - - -//设置绘制模式,1,不绘制背景,0,绘制背景 -void LCD_SetLcdDrawMode (int mode) -{ - if (mode) - { - //g_lcd.DrawMode=1;//此时调用画点函数时不绘制背景色 - } - else - { - //g_lcd.DrawMode=0; - } -} - - - -static void LCD_DmaCopy(void * pSrc, void * pDst, uint32_t x_size,uint32_t y_size) -{ - DMA2D_DeInit(); - /* Set up mode */ - - DMA2D->CR = 0x00010000UL | (1 << 9); /* Control Register (Memory to memory with pixel format conversion and TCIE) */ - - /* Set up pointers */ - DMA2D->FGMAR = (uint32_t)pSrc; /* Foreground Memory Address Register (Source address) */ - DMA2D->OMAR = (uint32_t)pDst; /* Output Memory Address Register (Destination address) */ - - /* Set up offsets */ - DMA2D->FGOR = 0; /* Foreground Offset Register (Source line offset) */ - DMA2D->OOR = 0; /* Output Offset Register (Destination line offset) */ - - /* Set up pixel format */ - DMA2D->FGPFCCR = LTDC_Pixelformat_RGB565; /* Foreground PFC Control Register (Defines the input pixel format) */ - DMA2D->OPFCCR = LTDC_Pixelformat_RGB565; /* Output PFC Control Register (Defines the output pixel format) */ - - /* Set up size */ - DMA2D->NLR = (uint32_t)(x_size << 16) | y_size; /* Number of Line Register (Size configuration of area to be transfered) */ - - /* Execute operation */ - DMA2D->CR |= DMA2D_CR_START; - - while (DMA2D->CR & DMA2D_CR_START) - { +void LTDC_ISR_Handler(void) { + LTDC_ClearFlag(LTDC_FLAG_LI); + if (g_lcd.LcdSwitchEn == 1) { + g_lcd.LcdSwitchEn = 0; + LTDC_Layer1->CFBAR = (u32)g_lcd.show; + LTDC->SRCR = 1; } } +static int LCD_UpDataWindow(void) { + LCD_WindowStruct *win = &g_lcd.win; + LCD_WindowStruct *draw = &g_lcd.realwin; + int real = 1; + if (win->xs >= 0 && win->xs < g_lcd.x_size) + draw->xs = win->xs; + else if (win->xs < 0) + draw->xs = 0; + else if (win->xs >= g_lcd.x_size) + real = 0; // 在显示区域外 + if (win->ys >= 0 && win->ys < g_lcd.y_size) + draw->ys = win->ys; + else if (win->ys < 0) + draw->ys = 0; + else if (win->ys >= g_lcd.y_size) + real = 0; // 在显示区域外 -static void LCD_FillColor(void * pDst, int x,int y, int x_size,int y_size,u32 color) -{ - DMA2D_DeInit(); + if (win->xe >= 0 && win->xe < g_lcd.x_size) + draw->xe = win->xe; + else if (win->xe < 0) + real = 0; // 在显示区域外 + else if (win->xe >= g_lcd.x_size) + draw->xe = g_lcd.x_size - 1; - DMA2D->OPFCCR = DMA2D_RGB565; + if (win->ye >= 0 && win->ye < g_lcd.y_size) + draw->ye = win->ye; + else if (win->ye < 0) + real = 0; // 在显示区域外 + else if (win->ye >= g_lcd.y_size) + draw->ye = g_lcd.y_size - 1; + if ((win->xs > win->xe) || (win->ys > win->ye)) + real = 0; + g_lcd.effective = real; + return real; +} - DMA2D->CR = DMA2D_R2M; - DMA2D->OCOLR = color; - DMA2D->OMAR = (u32)pDst+(y*LCD_Width+x)*2; - DMA2D->OOR = LCD_Width-x_size; - DMA2D->NLR = (x_size<<16)|y_size; +// 设置活动窗口 +void LCD_SetWindow(int x_s, int y_s, int x_size, int y_size) { + g_lcd.win.xs = x_s; + g_lcd.win.ys = y_s; + g_lcd.win.xe = x_s + x_size - 1; + g_lcd.win.ye = y_s + y_size - 1; + LCD_UpDataWindow(); +} - - /* Execute operation */ - DMA2D->CR |= DMA2D_CR_START; - - while (DMA2D->CR & DMA2D_CR_START) - { +int LCD_GetLcdSizeX(void) { return LCD_Width; } + +int LCD_GetLcdSizeY(void) { return LCD_Height; } + +// 获取图像显示地址 +u32 *LCD_GetShowAddr(void) { + uint32_t *ret = (u32 *)LTDC_Layer1->CFBAR; + ret = (u32 *)g_lcd.show; + return ret; +} + +// 获取图像绘制地址 +u32 *LCD_GetDrawAddr(void) { + uint32_t *ret = 0; + ret = (u32 *)g_lcd.draw; + return ret; +} + +// 设置屏幕显示地址,这个地址直接输出到屏幕上,返回上一个输出到屏幕的地址 +u32 LCD_SetLayer(u32 AddrIndex) { + uint32_t ret = LTDC_Layer1->CFBAR; + if (AddrIndex < 3) { + g_lcd.show = (u16 *)g_lcdAddrTable[AddrIndex]; + LTDC_Layer1->CFBAR = g_lcdAddrTable[AddrIndex]; + LTDC->SRCR = 1; } -} - - -void LCD_FillImg(const u16 *pSurf,int x,int y,u16 w,u16 h,int width_bytes,const u8 *bits) -{ - - DMA2D_DeInit(); - - DMA2D->OPFCCR = DMA2D_RGB565; - - DMA2D->CR = DMA2D_M2M; - - DMA2D->OMAR = (u32)pSurf+(y*LCD_Width+x)*2; - DMA2D->OOR = LCD_Width-w; - - DMA2D->NLR = (w<<16)|h; - - DMA2D->FGPFCCR = CM_RGB565; - DMA2D->FGMAR = (u32)bits; - DMA2D->FGOR = (width_bytes>>1)-w; - - - /* Execute operation */ - DMA2D->CR |= DMA2D_CR_START; - - while (DMA2D->CR & DMA2D_CR_START) - { - } - -} - - - - - - - - -//层复制 -void LCD_LayerCopy (int dst,int src) -{ - u32 *p_dst=0; - u32 *p_src=0; - if ((dst<3)&&(src<3)) - { - p_dst=(u32 *)g_lcdAddrTable[dst]; - p_src=(u32 *)g_lcdAddrTable[src]; -// for (int i=0;i g_lcd.realwin.ye)) return; - if ((x + xsize - 1 < g_lcd.realwin.xs) || x > g_lcd.realwin.xe) return; - int mx = x; - if (mx < g_lcd.realwin.xs) mx = g_lcd.realwin.xs; - buff += mx - x; xsize -= mx - x; - //不超过指定范围 -// if (mx + xsize - 1 > xe) xsize=xe - mx + 1; - if (xsize>g_lcd.realwin.xe-mx+1) xsize=g_lcd.realwin.xe-mx+1; - for (int i = 0; i < xsize; i++) - g_lcd.draw[mx+y*g_lcd.x_size + i] = (buff[i]); -} - - -//把图像填充到屏幕的活动窗口中, -//参数xsize,图像的宽度 -//参数ysize,图像的高度 -static void LCD_FillRect16(int xs,int ys,int xe,int ye,u16 *buff, int xsize, int ysize) -{ - ys += g_lcd.win.ys; - ye += g_lcd.win.ys; - xs += g_lcd.win.xs; - xe += g_lcd.win.xs; - -// for (int y = ys; y<=ye; y++) -// { -// LCD_FillLine16( xs,y,xe,buff, xsize); -// buff += xsize; -// } - if(yeg_lcd.realwin.ye) return; - if(xeg_lcd.realwin.xe) return; - - if(ysxsize) lcd_xsize=xsize; - if(ysize>ye-ys+1) ysize=ye-ys+1; - if(lcd_xsize>0&&ysize>0) - LCD_FillImg(g_lcd.draw,xs,ys,lcd_xsize,ysize,xsize*2,(u8*)buff); - //DMA2D_DrawBitmap_RGB565(LCD_GetDrawAddr(),g_lcd_struct.WindowSrcX,g_lcd_struct.WindowSrcY,lcd_xsize,ysize,xsize*2,(u8*)buff); -} - -//把图像偏移之后填充到屏幕的活动窗口中, -//参数x_s,图像要显示的横向起始坐标 -//参数y_s,图像要显示的纵向起始坐标 -//参数xsize,图像的宽度 -//参数ysize,图像的高度 -static void LCD_FillRectOff16(int xs,int ys,int xe,int ye,u16 *buff, int x_s, int y_s, int xsize, int ysize) -{ - //图像偏移 - int offset = y_s*xsize + x_s; - //图像相对屏幕偏移 - //offset += xs + ys*xsize; - LCD_FillRect16(xs,ys,xe,ye,buff + offset, xsize, ysize - y_s); -} - - -void LCD_FillRectOff16At(int lcd_xs, int lcd_ys, int lcd_xsize, int lcd_ysize, u16 *buff, int xs, int ys, int xsize, int ysize) -{ - //绘图 - LCD_FillRectOff16(lcd_xs,lcd_ys,lcd_xs+lcd_xsize-1,lcd_ys+lcd_ysize-1,buff, xs, ys, xsize, ysize); -} - - - -static int LCD_FillImg_ARGB(const void *pSurf,int x,int y,u16 w,u16 h,int width_bytes,const u8 *bits,u32 color_format); - - -//把图像填充到屏幕的活动窗口中, -//参数xsize,图像的宽度 -//参数ysize,图像的高度 -static void LCD_FillRectAlpha(int xs,int ys,int xe,int ye,u32 *buff, int xsize, int ysize) -{ - ys += g_lcd.win.ys; - ye += g_lcd.win.ys; - xs += g_lcd.win.xs; - xe += g_lcd.win.xs; - - if(yeg_lcd.realwin.ye) return; - if(xeg_lcd.realwin.xe) return; - - if(ysxsize) lcd_xsize=xsize; - if(ysize>ye-ys+1) ysize=ye-ys+1; - if(lcd_xsize>0&&ysize>0) - LCD_FillImg_ARGB(g_lcd.draw,xs,ys,lcd_xsize,ysize,xsize*4,(u8*)buff,CM_ARGB8888); -} - - - -static void LCD_FillRectOffAlpha(int xs,int ys,int xe,int ye,u32 *buff, int x_s, int y_s, int xsize, int ysize) -{ - //图像偏移 - int offset = y_s*xsize + x_s; - //图像相对屏幕偏移 - //offset += xs + ys*xsize; - LCD_FillRectAlpha(xs,ys,xe,ye,buff + offset, xsize, ysize - y_s); -} - - -void LCD_FillRectOffAtAlpha(int lcd_xs, int lcd_ys, int lcd_xsize, int lcd_ysize, void *buff, int xs, int ys, int xsize, int ysize) -{ - //绘图 - LCD_FillRectOffAlpha(lcd_xs,lcd_ys,lcd_xs+lcd_xsize-1,lcd_ys+lcd_ysize-1,buff, xs, ys, xsize, ysize); -} - - - - - - - -//画点,不会进行安全性检查,调用时要保证要画的点不会超出屏幕 -//参数mode,1,画前景色,0,画背景色 -void LCD_DrawPoint (int x,int y,u32 mode) -{ - if (g_lcd.effective == 0) return; - x += g_lcd.win.xs; - y += g_lcd.win.ys; - if (xg_lcd.realwin.xe) return; - if (yg_lcd.realwin.ye) return; - if (mode) - g_lcd.draw[x + y*g_lcd.x_size] = g_lcd.color; -} - - -//安全画点,以屏幕窗口的坐标为原点,并且画点不会超出窗口范围 -void LCD_DrawPointSafe (int x,int y,u32 mode) -{ - if (g_lcd.effective == 0) return; - x += g_lcd.win.xs; - y += g_lcd.win.ys; - if (xg_lcd.realwin.xe) return; - if (yg_lcd.realwin.ye) return; - if (mode) - g_lcd.draw[x + y*g_lcd.x_size] = g_lcd.color; -} - - - -//安全画点,以屏幕窗口的坐标为原点,并且画点不会超出窗口范围 -//以指定颜色画点,而不是前景色 -void LCD_DrawPointSafeColor (int x,int y,u16 color) -{ - if (g_lcd.effective == 0) return; - x += g_lcd.win.xs; - y += g_lcd.win.ys; - if (xg_lcd.realwin.xe) return; - if (yg_lcd.realwin.ye) return; - g_lcd.draw[x + y*g_lcd.x_size] = (color); -} - - - -//快速ALPHA BLENDING算法. -//src:源颜色 -//dst:目标颜色 -//alpha:透明程度(0~32) -//返回值:混合后的颜色. -static u16 alpha_blend565(u16 src,u16 dst,u8 alpha) -{ - u32 src2; - u32 dst2; - //Convert to 32bit |-----GGGGGG-----RRRRR------BBBBB| - src2=((src<<16)|src)&0x07E0F81F; - dst2=((dst<<16)|dst)&0x07E0F81F; - //Perform blending R:G:B with alpha in range 0..32 - //Note that the reason that alpha may not exceed 32 is that there are only - //5bits of space between each R:G:B value, any higher value will overflow - //into the next component and deliver ugly result. - dst2=((((dst2-src2)*alpha)>>5)+src2)&0x07E0F81F; - return (dst2>>16)|dst2; -} - - -//以指定色透明度画点0~32 -void LCD_DrawPointSafeColorAlpha (int x,int y,u16 color,u8 alpha) -{ - if (g_lcd.effective == 0) return; - if (alpha==0) return; - x += g_lcd.win.xs; - y += g_lcd.win.ys; - if (xg_lcd.realwin.xe) return; - if (yg_lcd.realwin.ye) return; - - u32 color_old = g_lcd.draw[x + y*g_lcd.x_size]; - color_old = (color_old); - color = alpha_blend565(color_old, color, alpha); - g_lcd.draw[x + y*g_lcd.x_size] = (color); -} - - - - - -//填充矩形,已窗口坐标为原点 -void LCD_FillRectByColor (int x,int y,int x_size,int y_size) -{ -// for (int i=y;ig_lcd.realwin.xe) xe=g_lcd.realwin.xe; - if (ye>g_lcd.realwin.ye) ye=g_lcd.realwin.ye; - x_size=xe-x+1; - y_size=ye-y+1; - - if(x_size<0||y_size<0) return ; - - -// LCD_FillImg_ARGB(LCD_GetDrawAddr(),x,y,x_size,y_size, x_size*4,fb,CM_ARGB8888); - - LCD_FillColor(g_lcd.draw,x,y,x_size,y_size,g_lcd.color); -} - - - - -static int LCD_MemSet(const void *pSurf,u16 w,u16 h,u32 color) -{ - - DMA2D_DeInit(); - DMA2D->OPFCCR = DMA2D_ARGB8888; - - - DMA2D->CR = DMA2D_R2M; - //DMA2D->OPFCCR = DMA2D_RGB565; - DMA2D->OCOLR = color; - DMA2D->OMAR = (u32)pSurf; - DMA2D->OOR = 0; - DMA2D->NLR = (w<<16)|h; - - - /* Execute operation */ - DMA2D->CR |= DMA2D_CR_START; - - while (DMA2D->CR & DMA2D_CR_START) - { - } - - return 1; - -} - - - -static int LCD_FillImg_ARGB(const void *pSurf,int x,int y,u16 w,u16 h,int width_bytes,const u8 *bits,u32 color_format) -{ - - - DMA2D_DeInit(); - - DMA2D->OPFCCR = DMA2D_RGB565; - DMA2D->BGPFCCR =CM_RGB565; - - DMA2D->CR = DMA2D_M2M_BLEND; - DMA2D->OMAR = (u32)pSurf+(y*LCD_Width+x)*2; - DMA2D->OOR = LCD_Width-w; - - DMA2D->NLR = (w<<16)|h; - - DMA2D->BGMAR =DMA2D->OMAR; - DMA2D->BGOR =DMA2D->OOR; - - DMA2D->FGPFCCR = NO_MODIF_ALPHA_VALUE|color_format; - DMA2D->FGMAR = (u32)bits; - - switch(color_format) - { - case CM_ARGB4444: - DMA2D->FGOR = (width_bytes>>1)-w; - break; - case CM_ARGB8888: - DMA2D->FGOR = (width_bytes>>2)-w; - break; - default: - return 0; + for (int i = 0; i < 3; i++) { + if (ret == g_lcdAddrTable[i]) { + ret = i; + break; } + } + if (ret >= 3) + ret = 0; + return ret; +} - //// +// 设置绘图地址,所有绘制操作在这个地址执行 +u32 LCD_SetDrawLayer(u32 Index) { + u32 ret = (u32)g_lcd.draw; + if (Index < 3) { + g_lcd.draw = (u16 *)g_lcdAddrTable[Index]; + } + for (int i = 0; i < 3; i++) { + if (ret == g_lcdAddrTable[i]) { + ret = i; + break; + } + } + if (ret >= 3) + ret = 0; + return ret; +} + +u32 LCD_SetLcdColor(u32 color) { + u32 ret = g_lcd.color; + // g_lcd_struct.Color=color; + g_lcd.color = COLOR888TO565(color); + return ret; +} + +u32 LCD_SetLcdBkColor(u32 color) { + u32 ret = g_lcd.bkColor; + // g_lcd_struct.BackColor=color; + ret = g_lcd.bkColor = COLOR888TO565(color); + return ret; +} + +u32 LCD_SetLcdColor16(u32 color) { + u32 ret = g_lcd.color; + g_lcd.color = (color); + return ret; +} + +u32 LCD_SetLcdBkColor16(u32 color) { + u32 ret = ret = g_lcd.bkColor; + ret = g_lcd.bkColor = (color); + return ret; +} + +u32 LCD_GetLcdColor(void) { + u32 ret = g_lcd.color; + return COLOR565TO888(ret); +} + +u32 LCD_GetLcdBkColor(void) { + u32 ret = g_lcd.bkColor; + return COLOR565TO888(ret); +} + +u32 LCD_GetLcdColor16(void) { + u32 ret = g_lcd.color; + return ret; +} + +u32 LCD_GetLcdBkColor16(void) { + u32 ret = g_lcd.bkColor; + return ret; +} + +// 设置绘制模式,1,不绘制背景,0,绘制背景 +void LCD_SetLcdDrawMode(int mode) { + if (mode) { + // g_lcd.DrawMode=1;//此时调用画点函数时不绘制背景色 + } else { + // g_lcd.DrawMode=0; + } +} + +static void LCD_DmaCopy(void *pSrc, void *pDst, uint32_t x_size, + uint32_t y_size) { + DMA2D_DeInit(); + /* Set up mode */ + + DMA2D->CR = + 0x00010000UL | (1 << 9); /* Control Register (Memory to memory with pixel + format conversion and TCIE) */ + + /* Set up pointers */ + DMA2D->FGMAR = + (uint32_t)pSrc; /* Foreground Memory Address Register (Source address) */ + DMA2D->OMAR = + (uint32_t)pDst; /* Output Memory Address Register (Destination address) */ + + /* Set up offsets */ + DMA2D->FGOR = 0; /* Foreground Offset Register (Source line offset) */ + DMA2D->OOR = 0; /* Output Offset Register (Destination line offset) */ + + /* Set up pixel format */ + DMA2D->FGPFCCR = + LTDC_Pixelformat_RGB565; /* Foreground PFC Control Register (Defines the + input pixel format) */ + DMA2D->OPFCCR = + LTDC_Pixelformat_RGB565; /* Output PFC Control Register (Defines the + output pixel format) */ + + /* Set up size */ + DMA2D->NLR = (uint32_t)(x_size << 16) | + y_size; /* Number of Line Register (Size configuration of area to + be transfered) */ /* Execute operation */ - DMA2D->CR |= DMA2D_CR_START; - - while (DMA2D->CR & DMA2D_CR_START) - { + DMA2D->CR |= DMA2D_CR_START; + + while (DMA2D->CR & DMA2D_CR_START) { } - return 1; - } +static void LCD_FillColor(void *pDst, int x, int y, int x_size, int y_size, + u32 color) { + DMA2D_DeInit(); + DMA2D->OPFCCR = DMA2D_RGB565; + DMA2D->CR = DMA2D_R2M; + DMA2D->OCOLR = color; + DMA2D->OMAR = (u32)pDst + (y * LCD_Width + x) * 2; + DMA2D->OOR = LCD_Width - x_size; + DMA2D->NLR = (x_size << 16) | y_size; + /* Execute operation */ + DMA2D->CR |= DMA2D_CR_START; -//以透明度填充矩形,已窗口坐标为原点 -void LCD_FillRectByColorAlpha (int x,int y,int x_size,int y_size,u8 alpha) -{ -// for (int i=y;ig_lcd.realwin.xe) xe=g_lcd.realwin.xe; - if (ye>g_lcd.realwin.ye) ye=g_lcd.realwin.ye; - x_size=xe-x+1; - y_size=ye-y+1; - - if(x_size<0||y_size<0) return ; - - u8 *fb=mymalloc(x_size*y_size*4); - LCD_MemSet(fb,x_size,y_size,COLOR565TO888(g_lcd.color)|(alpha<<(24+3))); - - - LCD_FillImg_ARGB(LCD_GetDrawAddr(),x,y,x_size,y_size, x_size*4,fb,CM_ARGB8888); - - myfree(fb); -} - - - -//求矩形在屏幕中的显示区域 -static int LCD_RectIntersection(LCD_WindowStruct *out,int x,int y,int xsize,int ysize) -{ - //取得新矩形的左上角 - int x_s = g_lcd.realwin.xs; - int y_s = g_lcd.realwin.ys; - if (x_sx + xsize - 1) - x_e = x + xsize - 1; - if (y_e>y + ysize - 1) - y_e = y + ysize - 1; - out->xs = x_s; - out->ys = y_s; - out->xe = x_e; - out->ye = y_e; - - if ((y_e >= y_s) && (x_e >= x_s)) - { - return 1; - } - else - { - return 0; - } + while (DMA2D->CR & DMA2D_CR_START) { + } } +void LCD_FillImg(const u16 *pSurf, int x, int y, u16 w, u16 h, int width_bytes, + const u8 *bits) { + DMA2D_DeInit(); + DMA2D->OPFCCR = DMA2D_RGB565; + DMA2D->CR = DMA2D_M2M; + DMA2D->OMAR = (u32)pSurf + (y * LCD_Width + x) * 2; + DMA2D->OOR = LCD_Width - w; + DMA2D->NLR = (w << 16) | h; + DMA2D->FGPFCCR = CM_RGB565; + DMA2D->FGMAR = (u32)bits; + DMA2D->FGOR = (width_bytes >> 1) - w; -//清除矩形内的显示 -void LCD_ClearRect(int x, int y, int xsize, int ysize) -{ - if (g_lcd.effective == 0) return; - x += g_lcd.win.xs; - y += g_lcd.win.ys; - LCD_WindowStruct out = { 0 }; -// if (LCD_RectIntersection(&out, x, y, xsize, ysize)) -// { -// for (int my = out.ys; my <= out.ye; my++) -// { -// for (int mx = out.xs; mx <= out.xe; mx++) -// { -// g_lcd.draw[mx + my*g_lcd.x_size] = g_lcd.bkColor; -// } -// } -// } - if (LCD_RectIntersection(&out, x, y, xsize, ysize)) - { - LCD_FillColor(g_lcd.draw,out.xs,out.ys,out.xe-out.xs+1,out.ye-out.ys+1,g_lcd.bkColor); - } + /* Execute operation */ + DMA2D->CR |= DMA2D_CR_START; + + while (DMA2D->CR & DMA2D_CR_START) { + } } - - - - -//获取指定矩形空间的屏幕颜色,屏幕的绝对坐标 -void LCD_GetColors (u16 *buff,int x_s,int y_s,int x_size,int y_size) -{ - u16 *addr=g_lcd.draw; - if (x_s<0) x_s=0; - else if (x_s>LCD_Width-1) x_s=LCD_Width-1; - if (y_s<0) y_s=0; - else if (y_s>LCD_Height-1) y_s=LCD_Height-1; - if (x_size>LCD_Width-x_s) x_size= LCD_Width-x_s; - else if (x_size<0) x_size=0; - if (y_size>LCD_Height-y_s) y_size= LCD_Height-y_s; - else if (y_size<0) y_size=0; - for (int y=y_s;y g_lcd.realwin.ye)) + return; + if ((x + xsize - 1 < g_lcd.realwin.xs) || x > g_lcd.realwin.xe) + return; + int mx = x; + if (mx < g_lcd.realwin.xs) + mx = g_lcd.realwin.xs; + buff += mx - x; + xsize -= mx - x; + // 不超过指定范围 + // if (mx + xsize - 1 > xe) xsize=xe - mx + 1; + if (xsize > g_lcd.realwin.xe - mx + 1) + xsize = g_lcd.realwin.xe - mx + 1; + for (int i = 0; i < xsize; i++) + g_lcd.draw[mx + y * g_lcd.x_size + i] = (buff[i]); +} + +// 把图像填充到屏幕的活动窗口中, +// 参数xsize,图像的宽度 +// 参数ysize,图像的高度 +static void LCD_FillRect16(int xs, int ys, int xe, int ye, u16 *buff, int xsize, + int ysize) { + ys += g_lcd.win.ys; + ye += g_lcd.win.ys; + xs += g_lcd.win.xs; + xe += g_lcd.win.xs; + + // for (int y = ys; y<=ye; y++) + // { + // LCD_FillLine16( xs,y,xe,buff, xsize); + // buff += xsize; + // } + if (ye < g_lcd.realwin.ys || ys > g_lcd.realwin.ye) + return; + if (xe < g_lcd.realwin.xs || xs > g_lcd.realwin.xe) + return; + + if (ys < g_lcd.realwin.ys) { + buff += (g_lcd.realwin.ys - ys) * xsize; + ysize -= g_lcd.realwin.ys - ys; + if (ysize < 0) + return; + ys = g_lcd.realwin.ys; + } + if (xs < g_lcd.realwin.xs) { + buff += (g_lcd.realwin.xs - xs); + xsize -= g_lcd.realwin.xs - xs; + if (xsize < 0) + return; + xs = g_lcd.realwin.xs; + } + + int lcd_xsize = xe - xs + 1; + if (lcd_xsize > xsize) + lcd_xsize = xsize; + if (ysize > ye - ys + 1) + ysize = ye - ys + 1; + if (lcd_xsize > 0 && ysize > 0) + LCD_FillImg(g_lcd.draw, xs, ys, lcd_xsize, ysize, xsize * 2, (u8 *)buff); + // DMA2D_DrawBitmap_RGB565(LCD_GetDrawAddr(),g_lcd_struct.WindowSrcX,g_lcd_struct.WindowSrcY,lcd_xsize,ysize,xsize*2,(u8*)buff); +} + +// 把图像偏移之后填充到屏幕的活动窗口中, +// 参数x_s,图像要显示的横向起始坐标 +// 参数y_s,图像要显示的纵向起始坐标 +// 参数xsize,图像的宽度 +// 参数ysize,图像的高度 +static void LCD_FillRectOff16(int xs, int ys, int xe, int ye, u16 *buff, + int x_s, int y_s, int xsize, int ysize) { + // 图像偏移 + int offset = y_s * xsize + x_s; + // 图像相对屏幕偏移 + // offset += xs + ys*xsize; + LCD_FillRect16(xs, ys, xe, ye, buff + offset, xsize, ysize - y_s); +} + +void LCD_FillRectOff16At(int lcd_xs, int lcd_ys, int lcd_xsize, int lcd_ysize, + u16 *buff, int xs, int ys, int xsize, int ysize) { + // 绘图 + LCD_FillRectOff16(lcd_xs, lcd_ys, lcd_xs + lcd_xsize - 1, + lcd_ys + lcd_ysize - 1, buff, xs, ys, xsize, ysize); +} + +static int LCD_FillImg_ARGB(const void *pSurf, int x, int y, u16 w, u16 h, + int width_bytes, const u8 *bits, u32 color_format); + +// 把图像填充到屏幕的活动窗口中, +// 参数xsize,图像的宽度 +// 参数ysize,图像的高度 +static void LCD_FillRectAlpha(int xs, int ys, int xe, int ye, u32 *buff, + int xsize, int ysize) { + ys += g_lcd.win.ys; + ye += g_lcd.win.ys; + xs += g_lcd.win.xs; + xe += g_lcd.win.xs; + + if (ye < g_lcd.realwin.ys || ys > g_lcd.realwin.ye) + return; + if (xe < g_lcd.realwin.xs || xs > g_lcd.realwin.xe) + return; + + if (ys < g_lcd.realwin.ys) { + buff += (g_lcd.realwin.ys - ys) * xsize; + ysize -= g_lcd.realwin.ys - ys; + if (ysize < 0) + return; + ys = g_lcd.realwin.ys; + } + if (xs < g_lcd.realwin.xs) { + buff += (g_lcd.realwin.xs - xs); + xsize -= g_lcd.realwin.xs - xs; + if (xsize < 0) + return; + xs = g_lcd.realwin.xs; + } + + int lcd_xsize = xe - xs + 1; + if (lcd_xsize > xsize) + lcd_xsize = xsize; + if (ysize > ye - ys + 1) + ysize = ye - ys + 1; + if (lcd_xsize > 0 && ysize > 0) + LCD_FillImg_ARGB(g_lcd.draw, xs, ys, lcd_xsize, ysize, xsize * 4, + (u8 *)buff, CM_ARGB8888); +} + +static void LCD_FillRectOffAlpha(int xs, int ys, int xe, int ye, u32 *buff, + int x_s, int y_s, int xsize, int ysize) { + // 图像偏移 + int offset = y_s * xsize + x_s; + // 图像相对屏幕偏移 + // offset += xs + ys*xsize; + LCD_FillRectAlpha(xs, ys, xe, ye, buff + offset, xsize, ysize - y_s); +} + +void LCD_FillRectOffAtAlpha(int lcd_xs, int lcd_ys, int lcd_xsize, + int lcd_ysize, void *buff, int xs, int ys, + int xsize, int ysize) { + // 绘图 + LCD_FillRectOffAlpha(lcd_xs, lcd_ys, lcd_xs + lcd_xsize - 1, + lcd_ys + lcd_ysize - 1, buff, xs, ys, xsize, ysize); +} + +// 画点,不会进行安全性检查,调用时要保证要画的点不会超出屏幕 +// 参数mode,1,画前景色,0,画背景色 +void LCD_DrawPoint(int x, int y, u32 mode) { + if (g_lcd.effective == 0) + return; + x += g_lcd.win.xs; + y += g_lcd.win.ys; + if (x < g_lcd.realwin.xs || x > g_lcd.realwin.xe) + return; + if (y < g_lcd.realwin.ys || y > g_lcd.realwin.ye) + return; + if (mode) + g_lcd.draw[x + y * g_lcd.x_size] = g_lcd.color; +} + +// 安全画点,以屏幕窗口的坐标为原点,并且画点不会超出窗口范围 +void LCD_DrawPointSafe(int x, int y, u32 mode) { + if (g_lcd.effective == 0) + return; + x += g_lcd.win.xs; + y += g_lcd.win.ys; + if (x < g_lcd.realwin.xs || x > g_lcd.realwin.xe) + return; + if (y < g_lcd.realwin.ys || y > g_lcd.realwin.ye) + return; + if (mode) + g_lcd.draw[x + y * g_lcd.x_size] = g_lcd.color; +} + +// 安全画点,以屏幕窗口的坐标为原点,并且画点不会超出窗口范围 +// 以指定颜色画点,而不是前景色 +void LCD_DrawPointSafeColor(int x, int y, u16 color) { + if (g_lcd.effective == 0) + return; + x += g_lcd.win.xs; + y += g_lcd.win.ys; + if (x < g_lcd.realwin.xs || x > g_lcd.realwin.xe) + return; + if (y < g_lcd.realwin.ys || y > g_lcd.realwin.ye) + return; + g_lcd.draw[x + y * g_lcd.x_size] = (color); +} + +// 快速ALPHA BLENDING算法. +// src:源颜色 +// dst:目标颜色 +// alpha:透明程度(0~32) +// 返回值:混合后的颜色. +static u16 alpha_blend565(u16 src, u16 dst, u8 alpha) { + u32 src2; + u32 dst2; + // Convert to 32bit |-----GGGGGG-----RRRRR------BBBBB| + src2 = ((src << 16) | src) & 0x07E0F81F; + dst2 = ((dst << 16) | dst) & 0x07E0F81F; + // Perform blending R:G:B with alpha in range 0..32 + // Note that the reason that alpha may not exceed 32 is that there are only + // 5bits of space between each R:G:B value, any higher value will overflow + // into the next component and deliver ugly result. + dst2 = ((((dst2 - src2) * alpha) >> 5) + src2) & 0x07E0F81F; + return (dst2 >> 16) | dst2; +} + +// 以指定色透明度画点0~32 +void LCD_DrawPointSafeColorAlpha(int x, int y, u16 color, u8 alpha) { + if (g_lcd.effective == 0) + return; + if (alpha == 0) + return; + x += g_lcd.win.xs; + y += g_lcd.win.ys; + if (x < g_lcd.realwin.xs || x > g_lcd.realwin.xe) + return; + if (y < g_lcd.realwin.ys || y > g_lcd.realwin.ye) + return; + + u32 color_old = g_lcd.draw[x + y * g_lcd.x_size]; + color_old = (color_old); + color = alpha_blend565(color_old, color, alpha); + g_lcd.draw[x + y * g_lcd.x_size] = (color); +} + +// 填充矩形,已窗口坐标为原点 +void LCD_FillRectByColor(int x, int y, int x_size, int y_size) { + if (g_lcd.effective == 0) + return; + x += g_lcd.win.xs; + y += g_lcd.win.ys; + int xe = x + x_size - 1; + int ye = y + y_size - 1; + if (x < g_lcd.realwin.xs) + x = g_lcd.realwin.xs; + if (y < g_lcd.realwin.ys) + y = g_lcd.realwin.ys; + if (xe > g_lcd.realwin.xe) + xe = g_lcd.realwin.xe; + if (ye > g_lcd.realwin.ye) + ye = g_lcd.realwin.ye; + x_size = xe - x + 1; + y_size = ye - y + 1; + + if (x_size < 0 || y_size < 0) + return; + + LCD_FillColor(g_lcd.draw, x, y, x_size, y_size, g_lcd.color); +} + +static int LCD_MemSet(const void *pSurf, u16 w, u16 h, u32 color) { + + DMA2D_DeInit(); + DMA2D->OPFCCR = DMA2D_ARGB8888; + + DMA2D->CR = DMA2D_R2M; + // DMA2D->OPFCCR = DMA2D_RGB565; + DMA2D->OCOLR = color; + DMA2D->OMAR = (u32)pSurf; + DMA2D->OOR = 0; + DMA2D->NLR = (w << 16) | h; + + /* Execute operation */ + DMA2D->CR |= DMA2D_CR_START; + + while (DMA2D->CR & DMA2D_CR_START) { + } + + return 1; +} + +static int LCD_FillImg_ARGB(const void *pSurf, int x, int y, u16 w, u16 h, + int width_bytes, const u8 *bits, u32 color_format) { + + DMA2D_DeInit(); + + DMA2D->OPFCCR = DMA2D_RGB565; + DMA2D->BGPFCCR = CM_RGB565; + + DMA2D->CR = DMA2D_M2M_BLEND; + DMA2D->OMAR = (u32)pSurf + (y * LCD_Width + x) * 2; + DMA2D->OOR = LCD_Width - w; + + DMA2D->NLR = (w << 16) | h; + + DMA2D->BGMAR = DMA2D->OMAR; + DMA2D->BGOR = DMA2D->OOR; + + DMA2D->FGPFCCR = NO_MODIF_ALPHA_VALUE | color_format; + DMA2D->FGMAR = (u32)bits; + + switch (color_format) { + case CM_ARGB4444: + DMA2D->FGOR = (width_bytes >> 1) - w; + break; + case CM_ARGB8888: + DMA2D->FGOR = (width_bytes >> 2) - w; + break; + default: + return 0; + } + + DMA2D->CR |= DMA2D_CR_START; + + while (DMA2D->CR & DMA2D_CR_START) { + } + return 1; +} + +// 以透明度填充矩形,已窗口坐标为原点 +void LCD_FillRectByColorAlpha(int x, int y, int x_size, int y_size, u8 alpha) { + if (g_lcd.effective == 0) + return; + x += g_lcd.win.xs; + y += g_lcd.win.ys; + int xe = x + x_size - 1; + int ye = y + y_size - 1; + if (x < g_lcd.realwin.xs) + x = g_lcd.realwin.xs; + if (y < g_lcd.realwin.ys) + y = g_lcd.realwin.ys; + if (xe > g_lcd.realwin.xe) + xe = g_lcd.realwin.xe; + if (ye > g_lcd.realwin.ye) + ye = g_lcd.realwin.ye; + x_size = xe - x + 1; + y_size = ye - y + 1; + + if (x_size < 0 || y_size < 0) + return; + + u8 *fb = mymalloc(x_size * y_size * 4); + LCD_MemSet(fb, x_size, y_size, + COLOR565TO888(g_lcd.color) | (alpha << (24 + 3))); + + LCD_FillImg_ARGB(LCD_GetDrawAddr(), x, y, x_size, y_size, x_size * 4, fb, + CM_ARGB8888); + myfree(fb); +} + +// 求矩形在屏幕中的显示区域 +static int LCD_RectIntersection(LCD_WindowStruct *out, int x, int y, int xsize, + int ysize) { + // 取得新矩形的左上角 + int x_s = g_lcd.realwin.xs; + int y_s = g_lcd.realwin.ys; + if (x_s < x) + x_s = x; + if (y_s < y) + y_s = y; + + // 取得新矩形的右下角 + int x_e = g_lcd.realwin.xe; + int y_e = g_lcd.realwin.ye; + if (x_e > x + xsize - 1) + x_e = x + xsize - 1; + if (y_e > y + ysize - 1) + y_e = y + ysize - 1; + out->xs = x_s; + out->ys = y_s; + out->xe = x_e; + out->ye = y_e; + + if ((y_e >= y_s) && (x_e >= x_s)) { + return 1; + } else { + return 0; + } +} + +// 清除矩形内的显示 +void LCD_ClearRect(int x, int y, int xsize, int ysize) { + if (g_lcd.effective == 0) + return; + x += g_lcd.win.xs; + y += g_lcd.win.ys; + LCD_WindowStruct out = {0}; + if (LCD_RectIntersection(&out, x, y, xsize, ysize)) { + LCD_FillColor(g_lcd.draw, out.xs, out.ys, out.xe - out.xs + 1, + out.ye - out.ys + 1, g_lcd.bkColor); + } +} + +// 获取指定矩形空间的屏幕颜色,屏幕的绝对坐标 +void LCD_GetColors(u16 *buff, int x_s, int y_s, int x_size, int y_size) { + u16 *addr = g_lcd.draw; + if (x_s < 0) + x_s = 0; + else if (x_s > LCD_Width - 1) + x_s = LCD_Width - 1; + if (y_s < 0) + y_s = 0; + else if (y_s > LCD_Height - 1) + y_s = LCD_Height - 1; + if (x_size > LCD_Width - x_s) + x_size = LCD_Width - x_s; + else if (x_size < 0) + x_size = 0; + if (y_size > LCD_Height - y_s) + y_size = LCD_Height - y_s; + else if (y_size < 0) + y_size = 0; + for (int y = y_s; y < y_size + y_s; y++) { + for (int x = x_s; x < x_size + x_s; x++) { + u32 temp = addr[(y * LCD_Width + x)]; + //*buff=COLOR888TO565(temp); + *buff = temp; + buff++; + } + } +} diff --git a/Project/Src/NES/nes_main.c b/Project/Src/NES/nes_main.c index dbdf4ad..3b5907e 100644 --- a/Project/Src/NES/nes_main.c +++ b/Project/Src/NES/nes_main.c @@ -1,534 +1,447 @@ -#include "main.h" -#include "stm32f4xx.h" -#include "nes_main.h" -#include "nes_ppu.h" -#include "nes_mapper.h" -#include "nes_apu.h" -#include "mymem.h" +////////////////////////////////////////////////////////////////////////////////// +// 本程序移植自网友ye781205的NES模拟器工程 +// ALIENTEK STM32F407开发板 +// NES主函数 代码 +// 正点原子@ALIENTEK +// 技术论坛:www.openedv.com +// 创建日期:2014/7/1 +// 版本:V1.0 +////////////////////////////////////////////////////////////////////////////////// + +#include "nes_main.h" #include "dac.h" +#include "main.h" +#include "mymem.h" +#include "nes_apu.h" +#include "nes_mapper.h" +#include "nes_ppu.h" +#include "stm32f4xx.h" #include "ff.h" #include "string.h" -////////////////////////////////////////////////////////////////////////////////// -//本程序移植自网友ye781205的NES模拟器工程 -//ALIENTEK STM32F407开发板 -//NES主函数 代码 -//正点原子@ALIENTEK -//技术论坛:www.openedv.com -//创建日期:2014/7/1 -//版本:V1.0 -////////////////////////////////////////////////////////////////////////////////// - -u8 nes_frame_cnt; //nes帧计数器 -int MapperNo; //map编号 -int NES_scanline; //nes扫描线 +uint8_t nes_frame_cnt; // nes帧计数器 +int MapperNo; // map编号 +int NES_scanline; // nes扫描线 int VROM_1K_SIZE; int VROM_8K_SIZE; -u8 PADdata; //手柄1键值 [7:0]右7 左6 下5 上4 Start3 Select2 B1 A0 -u8 PADdata1; //手柄2键值 [7:0]右7 左6 下5 上4 Start3 Select2 B1 A0 -u8 *NES_RAM; //保持1024字节对齐 -u8 *NES_SRAM; -NES_header *RomHeader; //rom文件头 -MAPPER *NES_Mapper; -MapperCommRes *MAPx; +uint8_t PADdata; // 手柄1键值 [7:0]右7 左6 下5 上4 Start3 Select2 B1 A0 +uint8_t PADdata1; // 手柄2键值 [7:0]右7 左6 下5 上4 Start3 Select2 B1 A0 +uint8_t *NES_RAM; // 保持1024字节对齐 +uint8_t *NES_SRAM; +NES_header *RomHeader; // rom文件头 +MAPPER *NES_Mapper; +MapperCommRes *MAPx; +uint8_t *spr_ram; // 精灵RAM,256字节 +ppu_data *ppu; // ppu指针 +uint8_t *VROM_banks; +uint8_t *VROM_tiles; -u8* spr_ram; //精灵RAM,256字节 -ppu_data* ppu; //ppu指针 -u8* VROM_banks; -u8* VROM_tiles; +apu_t *apu; // apu指针 +uint16_t *wave_buffers; +uint16_t *i2sbuf1; // 音频缓冲帧,占用内存数 367*4 字节@22050Hz +uint16_t *i2sbuf2; // 音频缓冲帧,占用内存数 367*4 字节@22050Hz -apu_t *apu; //apu指针 -u16 *wave_buffers; -u16 *i2sbuf1; //音频缓冲帧,占用内存数 367*4 字节@22050Hz -u16 *i2sbuf2; //音频缓冲帧,占用内存数 367*4 字节@22050Hz - -u8* romfile; //nes文件指针,指向整个nes文件的起始地址. +uint8_t *romfile; // nes文件指针,指向整个nes文件的起始地址. ////////////////////////////////////////////////////////////////////////////////////// -//记录nes是否需要跳出 -static u8 g_nes_break=0; +// 记录nes是否需要跳出 +static uint8_t g_nes_break = 0; - - - -//加载ROM -//返回值:0,成功 -// 1,内存错误 -// 3,map错误 -u8 nes_load_rom(void) -{ - u8* p; - u8 i; - u8 res=0; - p=(u8*)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; //有512字节的trainer: - if(RomHeader->num_8k_vrom_banks>0) //存在VROM,进行预解码 - { - VROM_banks=p+16+(RomHeader->num_16k_rom_banks*0x4000); -#if NES_RAM_SPEED==1 //1:内存占用小 0:速度快 - VROM_tiles=VROM_banks; -#else - VROM_tiles=mymalloc(RomHeader->num_8k_vrom_banks*8*1024);//这里可能申请多达1MB内存!!! - if(VROM_tiles==0)VROM_tiles=VROM_banks;//内存不够用的情况下,尝试VROM_titles与VROM_banks共用内存 - 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;//忽略高四位,如果头看起来很糟糕 - //printf("use map:%d\r\n",MapperNo); - for(i=0;i<255;i++) // 查找支持的Mapper号 - { - 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; //返回执行结果 -} -//变量NES_RAM申请内存时的辅助指针 +// 加载ROM +// 返回值:0,成功 +// 1,内存错误 +// 3,map错误 +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; // 有512字节的trainer: + if (RomHeader->num_8k_vrom_banks > 0) // 存在VROM,进行预解码 + { + VROM_banks = p + 16 + (RomHeader->num_16k_rom_banks * 0x4000); +#if NES_RAM_SPEED == 1 // 1:内存占用小 0:速度快 + VROM_tiles = VROM_banks; +#else + VROM_tiles = mymalloc(RomHeader->num_8k_vrom_banks * 8 * + 1024); // 这里可能申请多达1MB内存!!! + if (VROM_tiles == 0) + VROM_tiles = + VROM_banks; // 内存不够用的情况下,尝试VROM_titles与VROM_banks共用内存 + 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; // 忽略高四位,如果头看起来很糟糕 + // printf("use map:%d\r\n",MapperNo); + for (i = 0; i < 255; i++) // 查找支持的Mapper号 + { + 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; // 返回执行结果 +} +// 变量NES_RAM申请内存时的辅助指针 void *nes_ram_alignment; -//释放内存 -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)//如果分别为VROM_banks和VROM_tiles申请了内存,则释放 - { - myfree(VROM_banks); - myfree(VROM_tiles); - } - switch (MapperNo)//释放map内存 - { - case 1: //释放内存 - 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; //释放内存 - 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; -} -//为NES运行申请内存 -//romsize:nes文件大小 -//返回值:0,申请成功 -// 1,申请失败 -u8 nes_sram_malloc(u32 romsize) -{ - u16 i=0; - - //NES_RAM需要0x800大小的内存,这里多申请0x400的内存,用于1024字节对齐 - nes_ram_alignment=mymalloc(0x800+0x400); - NES_RAM=(void*)(((u32)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); //申请游戏rom空间,等于nes文件大小 - 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); //清零 - memset(RomHeader,0,sizeof(NES_header)); //清零 - memset(NES_Mapper,0,sizeof(MAPPER)); //清零 - memset(spr_ram,0,0X100); //清零 - memset(ppu,0,sizeof(ppu_data)); //清零 - memset(apu,0,sizeof(apu_t)); //清零 - memset(wave_buffers,0,APU_PCMBUF_SIZE*2);//清零 - memset(i2sbuf1,0,APU_PCMBUF_SIZE*4+10); //清零 - memset(i2sbuf2,0,APU_PCMBUF_SIZE*4+10); //清零 - memset(romfile,0,romsize); //清零 - return 0; -} - - - - - - - - - - - - - - -int nes_xoff=0; //显示在x轴方向的偏移量(实际显示宽度=256-2*nes_xoff) -int nes_yoff=0; - - - -//开始nes游戏 -//pname:nes游戏路径 -//返回值: -//0,正常退出 -//1,内存错误 -//2,文件错误 -//3,不支持的map -u8 nes_load(u8* pname,void *lcd_addr,int x,int y) -{ - nes_xoff=x; - nes_yoff=y; - FIL *file; - FILINFO *file_info; - UINT br; - u8 res=0; -// app_wm8978_volset(wm8978set.mvol); -// WM8978_ADDA_Cfg(1,0); //开启DAC -// WM8978_Input_Cfg(0,0,0);//关闭输入通道 -// WM8978_Output_Cfg(1,0); //开启DAC输出 - g_nes_break=0; - file=mymalloc(sizeof(FIL)); - file_info= mymalloc(sizeof(FILINFO)); - if(file==0)return 1; //内存申请失败. - - res=f_stat((char*)pname,file_info); - if(res!=FR_OK) //打开文件失败 - { - myfree(file); - myfree(file_info); - return 2; - } - res=nes_sram_malloc(file_info->fsize); //申请内存 - if(res==0) - { - f_open(file,(char*)pname,FA_READ); - f_read(file,romfile,file_info->fsize,&br); //读取nes文件 - res=nes_load_rom(); //加载ROM - if(res==0) - { - Mapper_Init(); //map初始化 - cpu6502_init(); //初始化6502,并复位 - PPU_reset(lcd_addr); //ppu复位 - apu_init(); //apu初始化 - nes_sound_open(0,APU_SAMPLE_RATE); //初始化播放设备 - nes_emulate_frame(); //进入NES模拟器主循环 - nes_sound_close(); //关闭声音输出 - } - } - f_close(file); - myfree(file);//释放内存 - myfree(file_info); - nes_sram_free(); //释放内存 - return res; -} - - - - - - - -//运行已经加载在内存中的游戏 -u8 nes_start(u8* file,int fileSize,void *lcd_addr,int x,int y) -{ - nes_xoff=x; - nes_yoff=y; - u8 res=0; - g_nes_break=0; - res=nes_sram_malloc(fileSize); //申请内存 - - if(res==0) - { - mymemcpy (romfile,file,fileSize);//复制一份在运行空间 - res=nes_load_rom(); //加载ROM - if(res==0) - { - Mapper_Init(); //map初始化 - cpu6502_init(); //初始化6502,并复位 - PPU_reset(lcd_addr); //ppu复位 - apu_init(); //apu初始化 - nes_sound_open(0,APU_SAMPLE_RATE); //初始化播放设备 - nes_emulate_frame(); //进入NES模拟器主循环 - nes_sound_close(); //关闭声音输出 - } - } - nes_sram_free(); //释放内存 - return res; -} - - - - - - - - - - - -//设置游戏显示窗口 -void nes_set_window(void) -{ +// 释放内存 +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) // 如果分别为VROM_banks和VROM_tiles申请了内存,则释放 + { + myfree(VROM_banks); + myfree(VROM_tiles); + } + switch (MapperNo) // 释放map内存 + { + case 1: // 释放内存 + 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; // 释放内存 + 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; } -//读取游戏手柄数据 -void nes_get_gamepadval(void) -{ +// 为NES运行申请内存 +// romsize:nes文件大小 +// 返回值:0,申请成功 +// 1,申请失败 +uint8_t nes_sram_malloc(uint32_t romsize) { + uint16_t i = 0; + + // NES_RAM需要0x800大小的内存,这里多申请0x400的内存,用于1024字节对齐 + 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); // 申请游戏rom空间,等于nes文件大小 + 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); // 清零 + memset(RomHeader, 0, sizeof(NES_header)); // 清零 + memset(NES_Mapper, 0, sizeof(MAPPER)); // 清零 + memset(spr_ram, 0, 0X100); // 清零 + memset(ppu, 0, sizeof(ppu_data)); // 清零 + memset(apu, 0, sizeof(apu_t)); // 清零 + memset(wave_buffers, 0, APU_PCMBUF_SIZE * 2); // 清零 + memset(i2sbuf1, 0, APU_PCMBUF_SIZE * 4 + 10); // 清零 + memset(i2sbuf2, 0, APU_PCMBUF_SIZE * 4 + 10); // 清零 + memset(romfile, 0, romsize); // 清零 + return 0; +} + +int nes_xoff = 0; // 显示在x轴方向的偏移量(实际显示宽度=256-2*nes_xoff) +int nes_yoff = 0; + +// 开始nes游戏 +// pname:nes游戏路径 +// 返回值: +// 0,正常退出 +// 1,内存错误 +// 2,文件错误 +// 3,不支持的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; // 内存申请失败. + + res = f_stat((char *)pname, file_info); + if (res != FR_OK) // 打开文件失败 + { + myfree(file); + myfree(file_info); + return 2; + } + res = nes_sram_malloc(file_info->fsize); // 申请内存 + if (res == 0) { + f_open(file, (char *)pname, FA_READ); + f_read(file, romfile, file_info->fsize, &br); // 读取nes文件 + res = nes_load_rom(); // 加载ROM + if (res == 0) { + Mapper_Init(); // map初始化 + cpu6502_init(); // 初始化6502,并复位 + PPU_reset(lcd_addr); // ppu复位 + apu_init(); // apu初始化 + nes_sound_open(0, APU_SAMPLE_RATE); // 初始化播放设备 + nes_emulate_frame(); // 进入NES模拟器主循环 + nes_sound_close(); // 关闭声音输出 + } + } + f_close(file); + myfree(file); // 释放内存 + myfree(file_info); + nes_sram_free(); // 释放内存 + return res; +} + +// 运行已经加载在内存中的游戏 +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); // 申请内存 + + if (res == 0) { + mymemcpy(romfile, file, fileSize); // 复制一份在运行空间 + res = nes_load_rom(); // 加载ROM + if (res == 0) { + Mapper_Init(); // map初始化 + cpu6502_init(); // 初始化6502,并复位 + PPU_reset(lcd_addr); // ppu复位 + apu_init(); // apu初始化 + nes_sound_open(0, APU_SAMPLE_RATE); // 初始化播放设备 + nes_emulate_frame(); // 进入NES模拟器主循环 + nes_sound_close(); // 关闭声音输出 + } + } + nes_sram_free(); // 释放内存 + return res; +} + +// 设置游戏显示窗口 +void nes_set_window(void) {} + +// 读取游戏手柄数据 +void nes_get_gamepadval(void) { #include "usart.h" - PADdata=USART3_GetKey(); - PADdata1=0; -} -//nes模拟器主循环 -void nes_emulate_frame(void) -{ - u8 nes_frame; - //TIM3_Int_Init(10000-1,8400-1);//启动TIM3 ,1s中断一次 - nes_set_window();//设置窗口 - while(1) - { - // LINES 0-239 - PPU_start_frame(); - //LCD_SwitchLayerBuff();//切换帧 - for(NES_scanline = 0; NES_scanline< 240; NES_scanline++) - { - run6502(113*256); - NES_Mapper->HSync(NES_scanline); - //扫描一行 - if(nes_frame==0)scanline_draw(NES_scanline); - else do_scanline_and_dont_draw(NES_scanline); - } - //LCD_ExitLayerBuff (); - - NES_scanline=240; - run6502(113*256);//运行1线 - NES_Mapper->HSync(NES_scanline); - start_vblank(); - if(NMI_enabled()) - { - cpunmi=1; - run6502(7*256);//运行中断 - } - 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帧查询一次USB - apu_soundoutput();//输出游戏声音 - nes_frame_cnt++; - nes_frame++; - if(nes_frame>NES_SKIP_FRAME)nes_frame=0;//跳帧 - u8 nesBreak (void); - if (nesBreak()) break; - if (Touch_GetState()->x[1]!=0) break; - } - //TIM3->CR1&=~(1<<0);//关闭定时器3 + PADdata = USART3_GetKey(); + PADdata1 = 0; } +// nes模拟器主循环 +void nes_emulate_frame(void) { + uint8_t nes_frame; + // TIM3_Int_Init(10000-1,8400-1);//启动TIM3 ,1s中断一次 + nes_set_window(); // 设置窗口 + while (1) { + // LINES 0-239 + PPU_start_frame(); + // LCD_SwitchLayerBuff();//切换帧 + for (NES_scanline = 0; NES_scanline < 240; NES_scanline++) { + run6502(113 * 256); + NES_Mapper->HSync(NES_scanline); + // 扫描一行 + if (nes_frame == 0) + scanline_draw(NES_scanline); + else + do_scanline_and_dont_draw(NES_scanline); + } + // LCD_ExitLayerBuff (); - - -u8 nesBreak (void) -{ - u8 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; + NES_scanline = 240; + run6502(113 * 256); // 运行1线 + NES_Mapper->HSync(NES_scanline); + start_vblank(); + if (NMI_enabled()) { + cpunmi = 1; + run6502(7 * 256); // 运行中断 + } + 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帧查询一次USB + apu_soundoutput(); // 输出游戏声音 + nes_frame_cnt++; + nes_frame++; + if (nes_frame > NES_SKIP_FRAME) + nes_frame = 0; // 跳帧 + uint8_t nesBreak(void); + if (nesBreak()) + break; + if (Touch_GetState()->x[1] != 0) + break; + } + // TIM3->CR1&=~(1<<0);//关闭定时器3 } - - - - - - -//在6502.s里面被调用 -void debug_6502(u16 reg0,u8 reg1) -{ - //printf("6502 error:%x,%d\r\n",reg0,reg1); +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; } +// 在6502.s里面被调用 +void debug_6502(uint16_t reg0, uint8_t reg1) { + // printf("6502 error:%x,%d\r\n",reg0,reg1); +} +////////////////////////////////////////////////////////////////////////////////// +// nes,音频输出支持部分 -////////////////////////////////////////////////////////////////////////////////// -//nes,音频输出支持部分 - - - -static vu8 g_buff_Invalid=0; //数据无效时要重新填充数据 -static vu8 g_buff_useing; //当前DMA在使用哪个缓冲区 +static vu8 g_buff_Invalid = 0; // 数据无效时要重新填充数据 +static vu8 g_buff_useing; // 当前DMA在使用哪个缓冲区 static DAC_UserStruct g_dac; - - -static void dma_tx_callback(DAC_UserStruct *dac) -{ - u16 i; - g_buff_useing=dac->buff_useing; - g_buff_Invalid=1; -} - - - - - -//NES打开音频输出 -int nes_sound_open(int samples_per_sync,int sample_rate) -{ - - //初始化DAC - g_dac.buff1=(u32 *)i2sbuf1; - g_dac.buff2=(u32 *)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; +static void dma_tx_callback(DAC_UserStruct *dac) { + uint16_t i; + g_buff_useing = dac->buff_useing; + g_buff_Invalid = 1; } -//NES关闭音频输出 -void nes_sound_close(void) -{ - DAC_NormalDeInit (&g_dac); -} -//NES音频输出到I2S缓存 -void nes_apu_fill_buffer(int samples,u16* wavebuf) -{ - - if (DAC_GetDacHander()!=&g_dac) return; - u16 i; - u16 *p; - while(g_buff_Invalid==0)//等待传输完成 - { - rt_thread_delay(5);// - }; - if(g_buff_useing==0) - { - p=(u16*)i2sbuf2; - }else - { - p=(u16*)i2sbuf1; - } - { - for(i=0;i>4); - p[2*i+1]=p[2*i]; - } - } - //填充了数据之后设置为有效 - g_buff_Invalid=0; -} - - - - - - - - - - - - - - - +// NES打开音频输出 +int nes_sound_open(int samples_per_sync, int sample_rate) { + // 初始化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; +} +// NES关闭音频输出 +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) // 等待传输完成 + { + 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]; + } + } + // 填充了数据之后设置为有效 + g_buff_Invalid = 0; +} diff --git a/Project/Src/NES/nes_main.h b/Project/Src/NES/nes_main.h index 409e334..88a4fdd 100644 --- a/Project/Src/NES/nes_main.h +++ b/Project/Src/NES/nes_main.h @@ -1,85 +1,68 @@ +////////////////////////////////////////////////////////////////////////////////// +// 本程序移植自网友ye781205的NES模拟器工程 +// ALIENTEK STM32F407开发板 +// NES主函数 代码 +// 正点原子@ALIENTEK +// 技术论坛:www.openedv.com +// 创建日期:2014/7/1 +// 版本:V1.0 +////////////////////////////////////////////////////////////////////////////////// + #ifndef __NES_MAIN_H #define __NES_MAIN_H -////////////////////////////////////////////////////////////////////////////////// -//本程序移植自网友ye781205的NES模拟器工程 -//ALIENTEK STM32F407开发板 -//NES主函数 代码 -//正点原子@ALIENTEK -//技术论坛:www.openedv.com -//创建日期:2014/7/1 -//版本:V1.0 -////////////////////////////////////////////////////////////////////////////////// - -#define NES_SKIP_FRAME 2 //定义模拟器跳帧数,默认跳2帧 - - -#define INLINE static inline -#define int8 char -#define int16 short -#define int32 int -#define uint8 unsigned char -#define uint16 unsigned short -#define uint32 unsigned int -#define boolean uint8 +#include "stdint.h" +#define NES_SKIP_FRAME 2 // 定义模拟器跳帧数,默认跳2帧 +#define INLINE static inline +#define boolean uint8_t -//nes信息头结构体 -typedef struct -{ - unsigned char id[3]; // 'NES' - unsigned char ctrl_z; // control-z - unsigned char num_16k_rom_banks; - unsigned char num_8k_vrom_banks; - unsigned char flags_1; - unsigned char flags_2; - unsigned char reserved[8]; -}NES_header; +// nes信息头结构体 +typedef struct { + unsigned char id[3]; // 'NES' + unsigned char ctrl_z; // control-z + unsigned char num_16k_rom_banks; + unsigned char num_8k_vrom_banks; + unsigned char flags_1; + unsigned char flags_2; + unsigned char reserved[8]; +} NES_header; -extern u8 nes_frame_cnt; //nes帧计数器 -extern int MapperNo; //map编号 -extern int NES_scanline; //扫描线 -extern NES_header *RomHeader; //rom文件头 +extern uint8_t nes_frame_cnt; // nes帧计数器 +extern int MapperNo; // map编号 +extern int NES_scanline; // 扫描线 +extern NES_header *RomHeader; // rom文件头 extern int VROM_1K_SIZE; -extern int VROM_8K_SIZE; -extern u8 cpunmi; //cpu中断标志 在 6502.s里面 -extern u8 cpuirq; -extern u8 PADdata; //手柄1键值 -extern u8 PADdata1; //手柄1键值 -extern u8 lianan_biao; //连按标志 -#define CPU_NMI cpunmi=1; -#define CPU_IRQ cpuirq=1; -#define NES_RAM_SPEED 0 //1:内存占用小 0:速度快 +extern int VROM_8K_SIZE; +extern uint8_t cpunmi; // cpu中断标志 在 6502.s里面 +extern uint8_t cpuirq; +extern uint8_t PADdata; // 手柄1键值 +extern uint8_t PADdata1; // 手柄1键值 +extern uint8_t lianan_biao; // 连按标志 +#define CPU_NMI cpunmi = 1; +#define CPU_IRQ cpuirq = 1; +#define NES_RAM_SPEED 0 // 1:内存占用小 0:速度快 +// 使用文件名来打开游戏 +uint8_t nes_load(uint8_t *pname, void *lcd_addr, int x, int y); -//使用文件名来打开游戏 -u8 nes_load(u8* pname,void *lcd_addr,int x,int y); +// 运行已经加载在内存中的游戏 +uint8_t nes_start(uint8_t *file, int fileSize, void *lcd_addr, int x, int y); -//运行已经加载在内存中的游戏 -u8 nes_start(u8* file,int fileSize,void *lcd_addr,int x,int y); - - - -void cpu6502_init(void); //在 cart.s -void run6502(u32); //在 6502.s -u8 nes_load_rom(void); +void cpu6502_init(void); // 在 cart.s +void run6502(uint32_t); // 在 6502.s +uint8_t nes_load_rom(void); void nes_sram_free(void); -u8 nes_sram_malloc(u32 romsize); +uint8_t nes_sram_malloc(uint32_t romsize); void nes_set_window(void); void nes_get_gamepadval(void); void nes_emulate_frame(void); -void debug_6502(u16 reg0,u8 reg1); +void debug_6502(uint16_t reg0, uint8_t reg1); void nes_i2s_dma_tx_callback(void); -int nes_sound_open(int samples_per_sync,int sample_rate); +int nes_sound_open(int samples_per_sync, int sample_rate); void nes_sound_close(void); -void nes_apu_fill_buffer(int samples,u16* wavebuf); +void nes_apu_fill_buffer(int samples, uint16_t *wavebuf); + #endif - - - - - - - diff --git a/Project/Src/NES/nes_mapper.c b/Project/Src/NES/nes_mapper.c index 8cf5097..1cafd88 100644 --- a/Project/Src/NES/nes_mapper.c +++ b/Project/Src/NES/nes_mapper.c @@ -1,18 +1,42 @@ -#include "stm32f4xx.h" -#include "nes_main.h" -#include "nes_ppu.h" -#include "nes_mapper.h" -////////////////////////////////////////////////////////////////////////////////// -//本程序移植自网友ye781205的NES模拟器工程 -//ALIENTEK STM32F407开发板 -//NES MAP 驱动代码 -//正点原子@ALIENTEK -//技术论坛:www.openedv.com -//创建日期:2014/7/1 -//版本:V1.0 -////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////// +// 本程序移植自网友ye781205的NES模拟器工程 +// ALIENTEK STM32F407开发板 +// NES MAP 驱动代码 +// 正点原子@ALIENTEK +// 技术论坛:www.openedv.com +// 创建日期:2014/7/1 +// 版本:V1.0 +////////////////////////////////////////////////////////////////////////////////// -//根据自己需要添加其他map文件用. +#include "nes_mapper.h" +#include "nes_main.h" +#include "nes_ppu.h" + + +#ifndef u8 +#define u8 uint8_t +#endif +#ifndef u16 +#define u16 uint16_t +#endif +#ifndef u32 +#define u32 uint32_t +#endif +#ifndef uint8 +#define uint8 uint8_t +#endif +#ifndef uint16 +#define uint16 uint16_t +#endif +#ifndef uint32 +#define uint32 uint32_t +#endif +#ifndef int32 +#define int32 int32_t +#endif + + +// 根据自己需要添加其他map文件用. #include "mapper/000.cpp" #include "mapper/001.cpp" #include "mapper/002.cpp" @@ -24,7 +48,7 @@ #include "mapper/011.cpp" #include "mapper/013.cpp" #include "mapper/015.cpp" -#include "mapper/016.cpp" +#include "mapper/016.cpp" #include "mapper/017.cpp" #include "mapper/018.cpp" #include "mapper/019.cpp" @@ -35,17 +59,17 @@ #include "mapper/025.cpp" #include "mapper/032.cpp" #include "mapper/033.cpp" -#include "mapper/034.cpp" -#include "mapper/064.cpp" -#include "mapper/065.cpp" -#include "mapper/066.cpp" -#include "mapper/067.cpp" -#include "mapper/069.cpp" -#include "mapper/070.cpp" -#include "mapper/071.cpp" -#include "mapper/072.cpp" -#include "mapper/073.cpp" -#include "mapper/075.cpp" +#include "mapper/034.cpp" +#include "mapper/064.cpp" +#include "mapper/065.cpp" +#include "mapper/066.cpp" +#include "mapper/067.cpp" +#include "mapper/069.cpp" +#include "mapper/070.cpp" +#include "mapper/071.cpp" +#include "mapper/072.cpp" +#include "mapper/073.cpp" +#include "mapper/075.cpp" #include "mapper/076.cpp" #include "mapper/078.cpp" #include "mapper/079.cpp" @@ -53,137 +77,222 @@ #include "mapper/087.cpp" #include "mapper/088.cpp" #include "mapper/099.cpp" -#include "mapper/113.cpp" +#include "mapper/113.cpp" #include "mapper/189.cpp" #include "mapper/225.cpp" #include "mapper/227.cpp" -#include "mapper/240.cpp" -#include "mapper/245.cpp" +#include "mapper/240.cpp" +#include "mapper/245.cpp" -//支持的Mapper号,自己添加 -const int MapTab[] = -{ - 0,1,2,3,4,6,7,8,11,13,15,16,17,18,19,21,22,23,24,25,32,33,34, - 64,65,66,67,69,70,71,72,73,75,76,78,79,85,87,88,99,113, - 189,225,227,240,245, - -1,//最后一个,-1,表示不支持的map号 +// 支持的Mapper号,自己添加 +const int MapTab[] = { + 0, 1, 2, 3, 4, 6, 7, 8, 11, 13, 15, 16, 17, 18, 19, 21, + 22, 23, 24, 25, 32, 33, 34, 64, 65, 66, 67, 69, 70, 71, 72, 73, + 75, 76, 78, 79, 85, 87, 88, 99, 113, 189, 225, 227, 240, 245, + -1, // 最后一个,-1,表示不支持的map号 }; -#define MASK_BANK(bank,mask) (bank) = ((bank) & (mask)) -#define VALIDATE_VROM_BANK(bank) \ - MASK_BANK(bank,VROM_mask); \ - if((bank) >= VROM_1K_SIZE) return; - - -uint32 VROM_mask; +#define MASK_BANK(bank, mask) (bank) = ((bank) & (mask)) +#define VALIDATE_VROM_BANK(bank) \ + MASK_BANK(bank, VROM_mask); \ + if ((bank) >= VROM_1K_SIZE) \ + return; -void Mapper_Reset(void){} -uint8 Mapper_ReadLow(uint16 addr){ return 0;} -void Mapper_WriteLow(uint16 addr,uint8 data){} -void Mapper_Write( uint16 addr , uint8 data){} -void Mapper_Read( uint8 data,uint16 addr ){} -void Mapper_HSync( int scanline ){} -void Mapper_VSync(void) {} - - void Mapper_Init(void) +uint32_t VROM_mask; + +void Mapper_Reset(void) {} +uint8_t Mapper_ReadLow(uint16_t addr) { return 0; } +void Mapper_WriteLow(uint16_t addr, uint8_t data) {} +void Mapper_Write(uint16_t addr, uint8_t data) {} +void Mapper_Read(uint8_t data, uint16_t addr) {} +void Mapper_HSync(int scanline) {} +void Mapper_VSync(void) {} + +void Mapper_Init(void) { + uint32_t probe; + NES_Mapper->Reset = Mapper_Reset; + NES_Mapper->Write = Mapper_Write; + NES_Mapper->Read = Mapper_Read; + NES_Mapper->WriteLow = Mapper_WriteLow; + NES_Mapper->ReadLow = Mapper_ReadLow; + NES_Mapper->HSync = Mapper_HSync; + NES_Mapper->VSync = Mapper_VSync; + VROM_mask = 0xFFFF; + for (probe = 0x8000; probe; probe >>= 1) { + if ((VROM_1K_SIZE - 1) & probe) + break; + VROM_mask >>= 1; + } + + switch (MapperNo) { + case 0: + MAP0_Init(); + break; + case 1: + MAP1_Init(); + break; + case 2: + MAP2_Init(); + break; + case 3: + MAP3_Init(); + break; + case 4: + MAP4_Init(); + break; + case 6: + MAP6_Init(); + break; + case 7: + MAP7_Init(); + break; + case 8: + MAP8_Init(); + break; + case 11: + MAP11_Init(); + break; + case 13: + MAP13_Init(); + break; + case 15: + MAP15_Init(); + break; + case 16: + MAP16_Init(); + break; + case 17: + MAP17_Init(); + break; + case 18: + MAP18_Init(); + break; + case 19: + MAP19_Init(); + break; + case 21: + MAP21_Init(); + break; + case 22: + MAP22_Init(); + break; + case 23: + MAP23_Init(); + break; + case 24: + MAP24_Init(); + break; + case 25: + MAP25_Init(); + break; + case 32: + MAP32_Init(); + break; + case 33: + MAP33_Init(); + break; + case 34: + MAP34_Init(); + break; + case 64: + MAP64_Init(); + break; + case 65: + MAP65_Init(); + break; + case 66: + MAP66_Init(); + break; + case 67: + MAP67_Init(); + break; + case 69: + MAP69_Init(); + break; + case 70: + MAP70_Init(); + break; + case 71: + MAP71_Init(); + break; + case 72: + MAP72_Init(); + break; + case 73: + MAP73_Init(); + break; + case 75: + MAP75_Init(); + break; + case 76: + MAP76_Init(); + break; + case 78: + MAP78_Init(); + break; + case 79: + MAP79_Init(); + break; + case 85: + MAP85_Init(); + break; + case 87: + MAP87_Init(); + break; + case 88: + MAP88_Init(); + break; + case 99: + MAP99_Init(); + break; + case 113: + MAP113_Init(); + break; + case 189: + MAP189_Init(); + break; + case 225: + MAP225_Init(); + break; + case 227: + MAP227_Init(); + break; + case 240: + MAP240_Init(); + break; + case 245: + MAP245_Init(); + break; + default: + break; + } + NES_Mapper->Reset(); +} +void asm_Mapper_Write(uint8_t byData, uint16_t wAddr) { + NES_Mapper->Write(wAddr, byData); +} +void asm_Mapper_ReadLow(uint16_t wAddr) // 添加的 { - uint32 probe; - NES_Mapper->Reset = Mapper_Reset; - NES_Mapper->Write = Mapper_Write; - NES_Mapper->Read = Mapper_Read; - NES_Mapper->WriteLow = Mapper_WriteLow; - NES_Mapper->ReadLow = Mapper_ReadLow; - NES_Mapper->HSync = Mapper_HSync; - NES_Mapper->VSync = Mapper_VSync; - VROM_mask = 0xFFFF; - for(probe = 0x8000; probe; probe >>= 1) - { - if((VROM_1K_SIZE-1) & probe) break; - VROM_mask >>= 1; - } - - switch (MapperNo) - { - case 0 :MAP0_Init();break; - case 1 :MAP1_Init();break; - case 2 :MAP2_Init();break; - case 3 :MAP3_Init();break; - case 4 :MAP4_Init();break; - case 6 :MAP6_Init();break; - case 7 :MAP7_Init();break; - case 8 :MAP8_Init();break; - case 11:MAP11_Init();break; - case 13:MAP13_Init();break; - case 15:MAP15_Init();break; - case 16:MAP16_Init();break; - case 17:MAP17_Init();break; - case 18:MAP18_Init();break; - case 19:MAP19_Init();break; - case 21:MAP21_Init();break; - case 22:MAP22_Init();break; - case 23:MAP23_Init();break; - case 24:MAP24_Init();break; - case 25:MAP25_Init();break; - case 32:MAP32_Init();break; - case 33:MAP33_Init();break; - case 34:MAP34_Init();break; - case 64:MAP64_Init();break; - case 65:MAP65_Init();break; - case 66:MAP66_Init();break; - case 67:MAP67_Init();break; - case 69:MAP69_Init();break; - case 70:MAP70_Init();break; - case 71:MAP71_Init();break; - case 72:MAP72_Init();break; - case 73:MAP73_Init();break; - case 75:MAP75_Init();break; - case 76:MAP76_Init();break; - case 78:MAP78_Init();break; - case 79:MAP79_Init();break; - case 85:MAP85_Init();break; - case 87:MAP87_Init();break; - case 88:MAP88_Init();break; - case 99:MAP99_Init();break; - case 113:MAP113_Init();break; - case 189:MAP189_Init();break; - case 225:MAP225_Init();break; - case 227:MAP227_Init();break; - case 240:MAP240_Init();break; - case 245:MAP245_Init();break; - default:break; - } - NES_Mapper->Reset(); -} -void asm_Mapper_Write(uint8 byData,uint16 wAddr) -{ - NES_Mapper->Write(wAddr,byData); -} -void asm_Mapper_ReadLow( uint16 wAddr) //添加的 -{ - NES_Mapper->ReadLow( wAddr); -} -void asm_Mapper_WriteLow( uint8 byData ,uint16 wAddr) -{ - NES_Mapper->WriteLow(wAddr, byData ); + NES_Mapper->ReadLow(wAddr); +} +void asm_Mapper_WriteLow(uint8_t byData, uint16_t wAddr) { + NES_Mapper->WriteLow(wAddr, byData); } -void set_CPU_bank3(signed char page ) {map67_(page) ;} -void set_CPU_bank4(signed char page ) {map89_(page) ;} -void set_CPU_bank5(signed char page ) {mapAB_(page) ;} -void set_CPU_bank6(signed char page ) {mapCD_(page) ;} -void set_CPU_bank7(signed char page ) {mapEF_(page) ;} -void set_CPU_banks(int bank0_num,int bank1_num,int bank2_num, int bank3_num) -{ - map89_(bank0_num); - mapAB_(bank1_num); - mapCD_(bank2_num); - mapEF_(bank3_num); +void set_CPU_bank3(signed char page) { map67_(page); } +void set_CPU_bank4(signed char page) { map89_(page); } +void set_CPU_bank5(signed char page) { mapAB_(page); } +void set_CPU_bank6(signed char page) { mapCD_(page); } +void set_CPU_bank7(signed char page) { mapEF_(page); } +void set_CPU_banks(int bank0_num, int bank1_num, int bank2_num, int bank3_num) { + map89_(bank0_num); + mapAB_(bank1_num); + mapCD_(bank2_num); + mapEF_(bank3_num); } -void set_PPU_banks(uint32 bank0_num, uint32 bank1_num, - uint32 bank2_num, uint32 bank3_num, - uint32 bank4_num, uint32 bank5_num, - uint32 bank6_num, uint32 bank7_num) -{ +void set_PPU_banks(uint32_t bank0_num, uint32_t bank1_num, uint32_t bank2_num, + uint32_t bank3_num, uint32_t bank4_num, uint32_t bank5_num, + uint32_t bank6_num, uint32_t bank7_num) { VALIDATE_VROM_BANK(bank0_num); VALIDATE_VROM_BANK(bank1_num); VALIDATE_VROM_BANK(bank2_num); @@ -201,113 +310,82 @@ void set_PPU_banks(uint32 bank0_num, uint32 bank1_num, ppu->PPU_VRAM_banks[5] = VROM_banks + (bank5_num << 10); ppu->PPU_VRAM_banks[6] = VROM_banks + (bank6_num << 10); ppu->PPU_VRAM_banks[7] = VROM_banks + (bank7_num << 10); - - set_tile_banks( VROM_tiles + bank0_num * 0x400 , - VROM_tiles + bank1_num * 0x400 , - VROM_tiles + bank2_num * 0x400 , - VROM_tiles + bank3_num * 0x400 , - VROM_tiles + bank4_num * 0x400 , - VROM_tiles + bank5_num * 0x400 , - VROM_tiles + bank6_num * 0x400 , - VROM_tiles + bank7_num * 0x400 ); + + set_tile_banks(VROM_tiles + bank0_num * 0x400, VROM_tiles + bank1_num * 0x400, + VROM_tiles + bank2_num * 0x400, VROM_tiles + bank3_num * 0x400, + VROM_tiles + bank4_num * 0x400, VROM_tiles + bank5_num * 0x400, + VROM_tiles + bank6_num * 0x400, + VROM_tiles + bank7_num * 0x400); } -void set_PPU_bank0(uint32 bank_num) -{ - VALIDATE_VROM_BANK(bank_num); - ppu->PPU_VRAM_banks[0] = VROM_banks + (bank_num << 10); // * 0x400 - set_tile_bank(0, VROM_tiles + bank_num * 0x400); +void set_PPU_bank0(uint32_t bank_num) { + VALIDATE_VROM_BANK(bank_num); + ppu->PPU_VRAM_banks[0] = VROM_banks + (bank_num << 10); // * 0x400 + set_tile_bank(0, VROM_tiles + bank_num * 0x400); } -void set_PPU_bank1(uint32 bank_num) -{ - VALIDATE_VROM_BANK(bank_num); - ppu->PPU_VRAM_banks[1] = VROM_banks + (bank_num << 10); // * 0x400 - set_tile_bank(1, VROM_tiles + bank_num * 0x400 ); +void set_PPU_bank1(uint32_t bank_num) { + VALIDATE_VROM_BANK(bank_num); + ppu->PPU_VRAM_banks[1] = VROM_banks + (bank_num << 10); // * 0x400 + set_tile_bank(1, VROM_tiles + bank_num * 0x400); } -void set_PPU_bank2(uint32 bank_num) -{ - VALIDATE_VROM_BANK(bank_num); - ppu->PPU_VRAM_banks[2] = VROM_banks + (bank_num << 10); // * 0x400 - set_tile_bank(2, VROM_tiles + bank_num * 0x400 ); +void set_PPU_bank2(uint32_t bank_num) { + VALIDATE_VROM_BANK(bank_num); + ppu->PPU_VRAM_banks[2] = VROM_banks + (bank_num << 10); // * 0x400 + set_tile_bank(2, VROM_tiles + bank_num * 0x400); } -void set_PPU_bank3(uint32 bank_num) -{ - VALIDATE_VROM_BANK(bank_num); - ppu->PPU_VRAM_banks[3] = VROM_banks + (bank_num << 10); // * 0x400 - set_tile_bank(3, VROM_tiles + bank_num * 0x400 ); +void set_PPU_bank3(uint32_t bank_num) { + VALIDATE_VROM_BANK(bank_num); + ppu->PPU_VRAM_banks[3] = VROM_banks + (bank_num << 10); // * 0x400 + set_tile_bank(3, VROM_tiles + bank_num * 0x400); } -void set_PPU_bank4(uint32 bank_num) -{ - VALIDATE_VROM_BANK(bank_num); - ppu->PPU_VRAM_banks[4] = VROM_banks + (bank_num << 10); // * 0x400 - set_tile_bank(4, VROM_tiles + bank_num * 0x400 ); -} -void set_PPU_bank5(uint32 bank_num) -{ - VALIDATE_VROM_BANK(bank_num); - ppu->PPU_VRAM_banks[5] = VROM_banks + (bank_num << 10); // * 0x400 - set_tile_bank(5, VROM_tiles + bank_num * 0x400 ); +void set_PPU_bank4(uint32_t bank_num) { + VALIDATE_VROM_BANK(bank_num); + ppu->PPU_VRAM_banks[4] = VROM_banks + (bank_num << 10); // * 0x400 + set_tile_bank(4, VROM_tiles + bank_num * 0x400); +} +void set_PPU_bank5(uint32_t bank_num) { + VALIDATE_VROM_BANK(bank_num); + ppu->PPU_VRAM_banks[5] = VROM_banks + (bank_num << 10); // * 0x400 + set_tile_bank(5, VROM_tiles + bank_num * 0x400); } -void set_PPU_bank6(uint32 bank_num) -{ - VALIDATE_VROM_BANK(bank_num); - ppu->PPU_VRAM_banks[6] = VROM_banks + (bank_num << 10); // * 0x400 - set_tile_bank(6, VROM_tiles + bank_num * 0x400 ); +void set_PPU_bank6(uint32_t bank_num) { + VALIDATE_VROM_BANK(bank_num); + ppu->PPU_VRAM_banks[6] = VROM_banks + (bank_num << 10); // * 0x400 + set_tile_bank(6, VROM_tiles + bank_num * 0x400); } -void set_PPU_bank7(uint32 bank_num) -{ - VALIDATE_VROM_BANK(bank_num); - ppu->PPU_VRAM_banks[7] = VROM_banks + (bank_num << 10); // * 0x400 - set_tile_bank(7, VROM_tiles + bank_num * 0x400); +void set_PPU_bank7(uint32_t bank_num) { + VALIDATE_VROM_BANK(bank_num); + ppu->PPU_VRAM_banks[7] = VROM_banks + (bank_num << 10); // * 0x400 + set_tile_bank(7, VROM_tiles + bank_num * 0x400); } // for mapper 19,68,90 -void set_PPU_bank8(uint32 bank_num) -{ - VALIDATE_VROM_BANK(bank_num); - ppu->PPU_VRAM_banks[8] = VROM_banks + (bank_num << 10); +void set_PPU_bank8(uint32_t bank_num) { + VALIDATE_VROM_BANK(bank_num); + ppu->PPU_VRAM_banks[8] = VROM_banks + (bank_num << 10); } -void set_PPU_bank9(uint32 bank_num) -{ - VALIDATE_VROM_BANK(bank_num); - ppu->PPU_VRAM_banks[9] = VROM_banks + (bank_num << 10); +void set_PPU_bank9(uint32_t bank_num) { + VALIDATE_VROM_BANK(bank_num); + ppu->PPU_VRAM_banks[9] = VROM_banks + (bank_num << 10); } -void set_PPU_bank10(uint32 bank_num) -{ - VALIDATE_VROM_BANK(bank_num); - ppu->PPU_VRAM_banks[10] = VROM_banks + (bank_num << 10); +void set_PPU_bank10(uint32_t bank_num) { + VALIDATE_VROM_BANK(bank_num); + ppu->PPU_VRAM_banks[10] = VROM_banks + (bank_num << 10); } -void set_PPU_bank11(uint32 bank_num) -{ - VALIDATE_VROM_BANK(bank_num); - ppu->PPU_VRAM_banks[11] = VROM_banks + (bank_num << 10); +void set_PPU_bank11(uint32_t bank_num) { + VALIDATE_VROM_BANK(bank_num); + ppu->PPU_VRAM_banks[11] = VROM_banks + (bank_num << 10); } // for mapper 1,4,5,6,13,19,80,85,96,119 -void set_VRAM_bank(uint8 bank, uint32 bank_num) -{ - if(bank < 8) - { - ppu->PPU_VRAM_banks[bank] = PPU_patterntables + ((bank_num & 0x0f) << 10); - } - else if(bank < 12) - { - set_name_table(bank, bank_num); - } +void set_VRAM_bank(uint8_t bank, uint32_t bank_num) { + if (bank < 8) { + ppu->PPU_VRAM_banks[bank] = PPU_patterntables + ((bank_num & 0x0f) << 10); + } else if (bank < 12) { + set_name_table(bank, bank_num); + } } - - - - - - - - - - - - diff --git a/Project/Src/NES/nes_mapper.h b/Project/Src/NES/nes_mapper.h index 9aae795..9479460 100644 --- a/Project/Src/NES/nes_mapper.h +++ b/Project/Src/NES/nes_mapper.h @@ -1,122 +1,109 @@ -#ifndef __NES_MAPPER_H -#define __NES_MAPPER_H -////////////////////////////////////////////////////////////////////////////////// -//本程序移植自网友ye781205的NES模拟器工程 -//ALIENTEK STM32F407开发板 -//NES MAP 驱动代码 -//正点原子@ALIENTEK -//技术论坛:www.openedv.com -//创建日期:2014/7/1 -//版本:V1.0 ////////////////////////////////////////////////////////////////////////////////// -#ifndef uint16 -#define uint16 u16 -#define uint8 u8 -#define uint32 u32 -#endif +// 本程序移植自网友ye781205的NES模拟器工程 +// ALIENTEK STM32F407开发板 +// NES MAP 驱动代码 +// 正点原子@ALIENTEK +// 技术论坛:www.openedv.com +// 创建日期:2014/7/1 +// 版本:V1.0 +////////////////////////////////////////////////////////////////////////////////// -#define num_8k_ROM_banks VROM_8K_SIZE -#define num_1k_VROM_banks VROM_1K_SIZE -////////////////////////////////////////////////////////////////////////////////// -typedef struct -{ - void (*Reset)(); - void (*Write)( uint16 addr,uint8 data); - void (*Read)( uint8 data,uint16 addr); - uint8 (*ReadLow)( uint16 addr); - void (*WriteLow)(uint16 addr,uint8 data); - void (*HSync)( int scanline); - void (*VSync)(void); +#ifndef __NES_MAPPER_H +#define __NES_MAPPER_H + +#include "stdint.h" + +#define num_8k_ROM_banks VROM_8K_SIZE +#define num_1k_VROM_banks VROM_1K_SIZE + +typedef struct { + void (*Reset)(); + void (*Write)(uint16_t addr, uint8_t data); + void (*Read)(uint8_t data, uint16_t addr); + uint8_t (*ReadLow)(uint16_t addr); + void (*WriteLow)(uint16_t addr, uint8_t data); + void (*HSync)(int scanline); + void (*VSync)(void); } MAPPER; -/////////////////////////////////////////////////////////////// -typedef enum -{ - MMC1_SMALL, - MMC1_512K, - MMC1_1024K -}MMC1_Size_t; - -typedef struct -{ - uint32 write_count; - uint8 bits; - uint8 regs[4]; - uint32 last_write_addr; - - MMC1_Size_t MMC1_Size; - uint32 MMC1_256K_base; - uint32 MMC1_swap; - // these are the 4 ROM banks currently selected - uint32 MMC1_bank1; - uint32 MMC1_bank2; - uint32 MMC1_bank3; - uint32 MMC1_bank4; +typedef enum { MMC1_SMALL, MMC1_512K, MMC1_1024K } MMC1_Size_t; - uint32 MMC1_HI1; - uint32 MMC1_HI2; -}Mapper1Res; +typedef struct { + uint32_t write_count; + uint8_t bits; + uint8_t regs[4]; + uint32_t last_write_addr; -//通用map变量结构体 -typedef struct -{ - uint8 patch; - uint8 regs[11]; + MMC1_Size_t MMC1_Size; + uint32_t MMC1_256K_base; + uint32_t MMC1_swap; - uint32 prg0,prg1; - uint32 chr01,chr23,chr4,chr5,chr6,chr7; - - uint8 irq_enabled; // IRQs enabled - uint32 irq_counter; // IRQ scanline counter, decreasing - uint32 irq_latch; // IRQ scanline counter latch -}MapperCommRes; - -extern uint32 ROM_mask; -extern uint32 VROM_mask; -extern const int MapTab[]; + // these are the 4 ROM banks currently selected + uint32_t MMC1_bank1; + uint32_t MMC1_bank2; + uint32_t MMC1_bank3; + uint32_t MMC1_bank4; + + uint32_t MMC1_HI1; + uint32_t MMC1_HI2; +} Mapper1Res; + +// 通用map变量结构体 +typedef struct { + uint8_t patch; + uint8_t regs[11]; + + uint32_t prg0, prg1; + uint32_t chr01, chr23, chr4, chr5, chr6, chr7; + + uint8_t irq_enabled; // IRQs enabled + uint32_t irq_counter; // IRQ scanline counter, decreasing + uint32_t irq_latch; // IRQ scanline counter latch +} MapperCommRes; + +extern uint32_t ROM_mask; +extern uint32_t VROM_mask; +extern const int MapTab[]; extern MAPPER *NES_Mapper; -extern uint32 VROM_mask; +extern uint32_t VROM_mask; extern Mapper1Res *MAP1; -extern MapperCommRes *MAPx; - +extern MapperCommRes *MAPx; -////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////// void Mapper_Init(void); -void asm_Mapper_Write(uint8 byData,uint16 wAddr); -void asm_Mapper_ReadLow( uint16 wAddr); -void asm_Mapper_WriteLow( uint8 byData ,uint16 wAddr); +void asm_Mapper_Write(uint8_t byData, uint16_t wAddr); +void asm_Mapper_ReadLow(uint16_t wAddr); +void asm_Mapper_WriteLow(uint8_t byData, uint16_t wAddr); -void map67_(signed char page); //6502.s -void map89_(signed char page); +void map67_(signed char page); // 6502.s +void map89_(signed char page); void mapAB_(signed char page); void mapCD_(signed char page); -void mapEF_(signed char page);//有符号字符 +void mapEF_(signed char page); // 有符号字符 -void set_CPU_bank3(signed char page ); -void set_CPU_bank4(signed char page ); -void set_CPU_bank5(signed char page ); -void set_CPU_bank6(signed char page ); -void set_CPU_bank7(signed char page ); -void set_CPU_banks(int bank0_num,int bank1_num,int bank2_num, int bank3_num); - -void set_PPU_banks( uint32 bank0_num, uint32 bank1_num, - uint32 bank2_num, uint32 bank3_num, - uint32 bank4_num, uint32 bank5_num, - uint32 bank6_num, uint32 bank7_num); -void set_PPU_bank0(uint32 bank_num); -void set_PPU_bank1(uint32 bank_num); -void set_PPU_bank2(uint32 bank_num); -void set_PPU_bank3(uint32 bank_num); -void set_PPU_bank4(uint32 bank_num); -void set_PPU_bank5(uint32 bank_num); -void set_PPU_bank6(uint32 bank_num); -void set_PPU_bank7(uint32 bank_num); -void set_PPU_bank8(uint32 bank_num); -void set_PPU_bank9(uint32 bank_num); -void set_PPU_bank10(uint32 bank_num); -void set_PPU_bank11(uint32 bank_num); -void set_VRAM_bank(uint8 bank, uint32 bank_num); +void set_CPU_bank3(signed char page); +void set_CPU_bank4(signed char page); +void set_CPU_bank5(signed char page); +void set_CPU_bank6(signed char page); +void set_CPU_bank7(signed char page); +void set_CPU_banks(int bank0_num, int bank1_num, int bank2_num, int bank3_num); +void set_PPU_banks(uint32_t bank0_num, uint32_t bank1_num, uint32_t bank2_num, + uint32_t bank3_num, uint32_t bank4_num, uint32_t bank5_num, + uint32_t bank6_num, uint32_t bank7_num); +void set_PPU_bank0(uint32_t bank_num); +void set_PPU_bank1(uint32_t bank_num); +void set_PPU_bank2(uint32_t bank_num); +void set_PPU_bank3(uint32_t bank_num); +void set_PPU_bank4(uint32_t bank_num); +void set_PPU_bank5(uint32_t bank_num); +void set_PPU_bank6(uint32_t bank_num); +void set_PPU_bank7(uint32_t bank_num); +void set_PPU_bank8(uint32_t bank_num); +void set_PPU_bank9(uint32_t bank_num); +void set_PPU_bank10(uint32_t bank_num); +void set_PPU_bank11(uint32_t bank_num); +void set_VRAM_bank(uint8_t bank, uint32_t bank_num); #endif diff --git a/Project/Src/NES/nes_ppu.c b/Project/Src/NES/nes_ppu.c index 4ada495..54bf31c 100644 --- a/Project/Src/NES/nes_ppu.c +++ b/Project/Src/NES/nes_ppu.c @@ -1,287 +1,265 @@ -#include "stm32f4xx.h" -#include "mymem.h" +////////////////////////////////////////////////////////////////////////////////// +// 本程序移植自网友ye781205的NES模拟器工程 +// ALIENTEK STM32F407开发板 +// NES PPU 驱动代码 +// 正点原子@ALIENTEK +// 技术论坛:www.openedv.com +// 创建日期:2014/7/1 +// 版本:V1.0 +////////////////////////////////////////////////////////////////////////////////// + #include "nes_ppu.h" +#include "mymem.h" +#include "stm32f4xx.h" #include "string.h" -//#include "gui.h" -//#include "GUIDRV_Lin.h" + #include "lcd_rgb.h" +uint8_t *PPU_patterntables; // 8192 VROM开始地址 图案表 - -////////////////////////////////////////////////////////////////////////////////// -//本程序移植自网友ye781205的NES模拟器工程 -//ALIENTEK STM32F407开发板 -//NES PPU 驱动代码 -//正点原子@ALIENTEK -//技术论坛:www.openedv.com -//创建日期:2014/7/1 -//版本:V1.0 -////////////////////////////////////////////////////////////////////////////////// - -uint8* PPU_patterntables; //8192 VROM开始地址 图案表 - -void set_tile_banks(uint8 *bank0, uint8 *bank1, uint8 *bank2, uint8 *bank3, - uint8 *bank4, uint8 *bank5, uint8 *bank6, uint8 *bank7) -{ - ppu->PPU_tile_banks[0] = bank0; - ppu->PPU_tile_banks[1] = bank1; - ppu->PPU_tile_banks[2] = bank2; - ppu->PPU_tile_banks[3] = bank3; - ppu->PPU_tile_banks[4] = bank4; - ppu->PPU_tile_banks[5] = bank5; - ppu->PPU_tile_banks[6] = bank6; - ppu->PPU_tile_banks[7] = bank7; +void set_tile_banks(uint8_t *bank0, uint8_t *bank1, uint8_t *bank2, uint8_t *bank3, + uint8_t *bank4, uint8_t *bank5, uint8_t *bank6, uint8_t *bank7) { + ppu->PPU_tile_banks[0] = bank0; + ppu->PPU_tile_banks[1] = bank1; + ppu->PPU_tile_banks[2] = bank2; + ppu->PPU_tile_banks[3] = bank3; + ppu->PPU_tile_banks[4] = bank4; + ppu->PPU_tile_banks[5] = bank5; + ppu->PPU_tile_banks[6] = bank6; + ppu->PPU_tile_banks[7] = bank7; } //******************************************************************* - void set_tile_bank(int i, uint8 *bank) - { - ppu->PPU_tile_banks[i] = bank; - } - - void set_name_table(uint8 bank, int bank_num) - { - ppu->PPU_VRAM_banks[bank] = ppu->PPU_nametables + ((bank_num & 0x03) << 10); - } - // 0x2000 - uint32 NMI_enabled(void) { return ppu->LowRegs[0] & 0x80; } - uint32 sprites_8x16() { return ppu->LowRegs[0] & 0x20; } +void set_tile_bank(int i, uint8_t *bank) { ppu->PPU_tile_banks[i] = bank; } - // 0x2001 - uint32 spr_enabled(void) { return ppu->LowRegs[1] & 0x10; } - uint32 bg_enabled(void) { return ppu->LowRegs[1] & 0x08; } - uint32 spr_clip_left8() { return !(ppu->LowRegs[1] & 0x04); } - uint32 bg_clip_left8() { return !(ppu->LowRegs[1] & 0x02); } - uint32 rgb_pal() { return ppu->LowRegs[1] & 0xE0;} -// uint8 rgb_bak; +void set_name_table(uint8_t bank, int bank_num) { + ppu->PPU_VRAM_banks[bank] = ppu->PPU_nametables + ((bank_num & 0x03) << 10); +} +// 0x2000 +uint32_t NMI_enabled(void) { return ppu->LowRegs[0] & 0x80; } +uint32_t sprites_8x16() { return ppu->LowRegs[0] & 0x20; } - // 0x2002 - uint32 sprite0_hit() { return ppu->LowRegs[2] & 0x40; } - uint32 more_than_8_sprites_on_cur_line() { return ppu->LowRegs[2] & 0x20; } - uint32 VRAM_accessible() { return ppu->LowRegs[2] & 0x10; } +// 0x2001 +uint32_t spr_enabled(void) { return ppu->LowRegs[1] & 0x10; } +uint32_t bg_enabled(void) { return ppu->LowRegs[1] & 0x08; } +uint32_t spr_clip_left8() { return !(ppu->LowRegs[1] & 0x04); } +uint32_t bg_clip_left8() { return !(ppu->LowRegs[1] & 0x02); } +uint32_t rgb_pal() { return ppu->LowRegs[1] & 0xE0; } +// uint8_t rgb_bak; - // by rinao -// uint8* get_patt() { return PPU_patterntables; } -// uint8* get_namt() { return ppu->PPU_nametables; } -// uint8 get_pattype(uint8 bank) { return PPU_patterntype[bank]; } -// void set_pattype(uint8 bank, uint8 data) { PPU_patterntype[bank] = data; } - - //***************************************************************** +// 0x2002 +uint32_t sprite0_hit() { return ppu->LowRegs[2] & 0x40; } +uint32_t more_than_8_sprites_on_cur_line() { return ppu->LowRegs[2] & 0x20; } +uint32_t VRAM_accessible() { return ppu->LowRegs[2] & 0x10; } -// ROM_banks = (uint8*)malloc(header.num_16k_rom_banks * (16*1024)); -// VROM_banks = (uint8*)malloc(header.num_8k_vrom_banks * (8*1024)); -// VROM_tiles = (uint8 *)malloc(RomHeader->num_8k_vrom_banks * 8 * 1024 / 16 * BYTES_PER_COMPILED_TILE); -// compile(header.num_8k_vrom_banks * 8 * 1024 / 16, VROM_banks, VROM_tiles); - -// uint8* get_ROM_banks() { return ROM_banks; } -// uint8* get_VROM_banks() { return VROM_banks; } -// uint8* get_VROM_tiles() { return VROM_tiles; } - -// #define MASK_BANK(bank,mask) (bank) = ((bank) & (mask)) +// by rinao +// uint8_t* get_patt() { return PPU_patterntables; } +// uint8_t* get_namt() { return ppu->PPU_nametables; } +// uint8_t get_pattype(uint8_t bank) { return PPU_patterntype[bank]; } +// void set_pattype(uint8_t bank, uint8_t data) { PPU_patterntype[bank] = data; } + +//***************************************************************** + +// ROM_banks = (uint8_t*)malloc(header.num_16k_rom_banks * (16*1024)); +// VROM_banks = (uint8_t*)malloc(header.num_8k_vrom_banks * (8*1024)); +// VROM_tiles = (uint8_t *)malloc(RomHeader->num_8k_vrom_banks * 8 * 1024 / 16 * +// BYTES_PER_COMPILED_TILE); compile(header.num_8k_vrom_banks * 8 * 1024 / 16, +// VROM_banks, VROM_tiles); + +// uint8_t* get_ROM_banks() { return ROM_banks; } +// uint8_t* get_VROM_banks() { return VROM_banks; } +// uint8_t* get_VROM_tiles() { return VROM_tiles; } + +// #define MASK_BANK(bank,mask) (bank) = ((bank) & (mask)) // #define VALIDATE_VROM_BANK(bank) \ // MASK_BANK(bank,VROM_mask); \ -// if((bank) >= (RomHeader->num_8k_vrom_banks * 8)) return; +// if((bank) >= (RomHeader->num_8k_vrom_banks * 8)) return; //**************************************************************************************************** -#define EXTRACT_4_PIXELS() \ - col = 0; \ - if(pattern_lo & pattern_mask) col |= (0x01 << 6); \ - if(pattern_hi & pattern_mask) col |= (0x02 << 6); \ - pattern_mask >>= 1; \ - if(pattern_lo & pattern_mask) col |= (0x01 << 4); \ - if(pattern_hi & pattern_mask) col |= (0x02 << 4); \ - pattern_mask >>= 1; \ - if(pattern_lo & pattern_mask) col |= (0x01 << 2); \ - if(pattern_hi & pattern_mask) col |= (0x02 << 2); \ - pattern_mask >>= 1; \ - if(pattern_lo & pattern_mask) col |= (0x01 << 0); \ - if(pattern_hi & pattern_mask) col |= (0x02 << 0); \ - *p++= col; +#define EXTRACT_4_PIXELS() \ + col = 0; \ + if (pattern_lo & pattern_mask) \ + col |= (0x01 << 6); \ + if (pattern_hi & pattern_mask) \ + col |= (0x02 << 6); \ + pattern_mask >>= 1; \ + if (pattern_lo & pattern_mask) \ + col |= (0x01 << 4); \ + if (pattern_hi & pattern_mask) \ + col |= (0x02 << 4); \ + pattern_mask >>= 1; \ + if (pattern_lo & pattern_mask) \ + col |= (0x01 << 2); \ + if (pattern_hi & pattern_mask) \ + col |= (0x02 << 2); \ + pattern_mask >>= 1; \ + if (pattern_lo & pattern_mask) \ + col |= (0x01 << 0); \ + if (pattern_hi & pattern_mask) \ + col |= (0x02 << 0); \ + *p++ = col; -void compile1(int count, uint8 *src, uint8 *dest) -{ - uint8 *p = dest; - uint8 col; - uint8 pattern_lo; - uint8 pattern_hi; - int i,line,pattern_mask; - for (i = 0; i < count; i++) { - for (line = 0; line < 8; line++) { - pattern_lo = *src; - pattern_hi = *(src + 8); +void compile1(int count, uint8_t *src, uint8_t *dest) { + uint8_t *p = dest; + uint8_t col; + uint8_t pattern_lo; + uint8_t pattern_hi; + int i, line, pattern_mask; + for (i = 0; i < count; i++) { + for (line = 0; line < 8; line++) { + pattern_lo = *src; + pattern_hi = *(src + 8); - pattern_mask = 0x80; - EXTRACT_4_PIXELS(); - pattern_mask >>= 1; - EXTRACT_4_PIXELS(); - src++; - } - src += 8; + pattern_mask = 0x80; + EXTRACT_4_PIXELS(); + pattern_mask >>= 1; + EXTRACT_4_PIXELS(); + src++; } + src += 8; + } } -void compile(int count, uint8 *src, uint8 *dest) -{ - u8 destemp[16]; - u8 *p = destemp; - u8 col; - u8 pattern_lo; - u8 pattern_hi; - int i,line,pattern_mask; - u8 j; - for (i = 0; i < count; i++) - { - for (line = 0; line < 8; line++) - { - pattern_lo = *src; - pattern_hi = *(src + 8); - pattern_mask = 0x80; - EXTRACT_4_PIXELS(); - pattern_mask >>= 1; - EXTRACT_4_PIXELS(); - src++; - } - p=destemp;//重新指向数组首地址 - for(j=0;j<16;j++)*dest++=destemp[j]; - src += 8; +void compile(int count, uint8_t *src, uint8_t *dest) { + u8 destemp[16]; + u8 *p = destemp; + u8 col; + u8 pattern_lo; + u8 pattern_hi; + int i, line, pattern_mask; + u8 j; + for (i = 0; i < count; i++) { + for (line = 0; line < 8; line++) { + pattern_lo = *src; + pattern_hi = *(src + 8); + pattern_mask = 0x80; + EXTRACT_4_PIXELS(); + pattern_mask >>= 1; + EXTRACT_4_PIXELS(); + src++; } + p = destemp; // 重新指向数组首地址 + for (j = 0; j < 16; j++) + *dest++ = destemp[j]; + src += 8; + } } -#define UPDATE_PIXEL() \ - if(data & pattern_mask) *p |= bit; \ +#define UPDATE_PIXEL() \ + if (data & pattern_mask) \ + *p |= bit; \ p++; +#define VRAM(addr) ppu->PPU_VRAM_banks[(addr) >> 10][(addr) & 0x3FF] -#define VRAM(addr) \ - ppu->PPU_VRAM_banks[(addr) >> 10][(addr) & 0x3FF] - -#define TILE(addr) \ +#define TILE(addr) \ (ppu->PPU_tile_banks[(addr) >> 10] + ((addr) & 0x3FF) / 16 * 16) -#define TILE_OFFSET(line) \ - ((line) * 2) +#define TILE_OFFSET(line) ((line) * 2) /* scanline start (if background or sprites are enabled): - v:0000010000011111=t:0000010000011111 + v:0000010000011111=t:0000010000011111 */ -#define LOOPY_SCANLINE_START(v,t) \ - { \ - v = (v & 0xFBE0) | (t & 0x041F); \ +#define LOOPY_SCANLINE_START(v, t) \ + { v = (v & 0xFBE0) | (t & 0x041F); } + +#define LOOPY_NEXT_LINE(v) \ + { \ + if ((v & 0x7000) == 0x7000) /* is subtile y offset == 7? */ \ + { \ + v &= 0x8FFF; /* subtile y offset = 0 */ \ + if ((v & 0x03E0) == 0x03A0) /* name_tab line == 29? */ \ + { \ + v ^= 0x0800; /* switch nametables (bit 11) */ \ + v &= 0xFC1F; /* name_tab line = 0 */ \ + } else { \ + if ((v & 0x03E0) == 0x03E0) /* line == 31? */ \ + { \ + v &= 0xFC1F; /* name_tab line = 0 */ \ + } else { \ + v += 0x0020; \ + } \ + } \ + } else { \ + v += 0x1000; /* next subtile y offset */ \ + } \ } - -#define LOOPY_NEXT_LINE(v) \ - { \ - if((v & 0x7000) == 0x7000) /* is subtile y offset == 7? */ \ - { \ - v &= 0x8FFF; /* subtile y offset = 0 */ \ - if((v & 0x03E0) == 0x03A0) /* name_tab line == 29? */ \ - { \ - v ^= 0x0800; /* switch nametables (bit 11) */ \ - v &= 0xFC1F; /* name_tab line = 0 */ \ - } \ - else \ - { \ - if((v & 0x03E0) == 0x03E0) /* line == 31? */ \ - { \ - v &= 0xFC1F; /* name_tab line = 0 */ \ - } \ - else \ - { \ - v += 0x0020; \ - } \ - } \ - } \ - else \ - { \ - v += 0x1000; /* next subtile y offset */ \ - } \ +#define LOOPY_NEXT_TILE(v) \ + { \ + if ((v & 0x001F) == 0x001F) { \ + v ^= 0x0400; /* switch nametables (bit 10) */ \ + v &= 0xFFE0; /* tile x = 0 */ \ + } else { \ + v++; /* next tile */ \ + } \ } - -#define LOOPY_NEXT_TILE(v) \ - { \ - if((v & 0x001F) == 0x001F) \ - { \ - v ^= 0x0400; /* switch nametables (bit 10) */ \ - v &= 0xFFE0; /* tile x = 0 */ \ - } \ - else \ - { \ - v++; /* next tile */ \ - } \ +#define LOOPY_NEXT_PIXEL(v, x) \ + { \ + if (x == 0x07) { \ + LOOPY_NEXT_TILE(v); \ + x = 0x00; \ + } else { \ + x++; \ + } \ + } +void PPU_Latch_FDFE(uint32_t addr) {} +#define CHECK_MMC2(addr) \ + if (((addr) & 0x0FC0) == 0x0FC0) { \ + if ((((addr) & 0x0FF0) == 0x0FD0) || (((addr) & 0x0FF0) == 0x0FE0)) { \ + PPU_Latch_FDFE(addr); \ + } \ } -#define LOOPY_NEXT_PIXEL(v,x) \ - { \ - if(x == 0x07) \ - { \ - LOOPY_NEXT_TILE(v); \ - x = 0x00; \ - } \ - else \ - { \ - x++; \ - } \ - } -void PPU_Latch_FDFE(uint32 addr) {} -#define CHECK_MMC2(addr) \ - if(((addr) & 0x0FC0) == 0x0FC0) \ - { \ - if((((addr) & 0x0FF0) == 0x0FD0) || (((addr) & 0x0FF0) == 0x0FE0)) \ - { \ - PPU_Latch_FDFE(addr); \ - } \ - } - -//、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、初始化 -static u16 *LCD_ADDR=0; -void PPU_reset(void *lcd_addr) -{ - LCD_ADDR=lcd_addr; - if (LCD_ADDR==0) return; -// static u8 first=0; -// if (first==0) -// { -// first=1; -// for (int i=0;i<64;i++) -// { -// NES_Palette[i]=COLOR565TO888(NES_Palette[i]); -// } -// } - //清屏 -// for (int i=0;i<480*272;i++) -// { -// LCD_ADDR[i]=0; -// } +// 、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、初始化 +static u16 *LCD_ADDR = 0; +void PPU_reset(void *lcd_addr) { + LCD_ADDR = lcd_addr; + if (LCD_ADDR == 0) + return; + // static u8 first=0; + // if (first==0) + // { + // first=1; + // for (int i=0;i<64;i++) + // { + // NES_Palette[i]=COLOR565TO888(NES_Palette[i]); + // } + // } + // 清屏 + // for (int i=0;i<480*272;i++) + // { + // LCD_ADDR[i]=0; + // } // set up PPU memory space table - PPU_patterntables=VROM_banks;//不确定正确 - - ppu->PPU_VRAM_banks[0x00] = PPU_patterntables + (0*0x400); - ppu->PPU_VRAM_banks[0x01] = PPU_patterntables + (1*0x400); - ppu->PPU_VRAM_banks[0x02] = PPU_patterntables + (2*0x400); - ppu->PPU_VRAM_banks[0x03] = PPU_patterntables + (3*0x400); - - ppu->PPU_VRAM_banks[0x04] = PPU_patterntables + (4*0x400); - ppu->PPU_VRAM_banks[0x05] = PPU_patterntables + (5*0x400); - ppu->PPU_VRAM_banks[0x06] = PPU_patterntables + (6*0x400); - ppu->PPU_VRAM_banks[0x07] = PPU_patterntables + (7*0x400); + PPU_patterntables = VROM_banks; // 不确定正确 + + ppu->PPU_VRAM_banks[0x00] = PPU_patterntables + (0 * 0x400); + ppu->PPU_VRAM_banks[0x01] = PPU_patterntables + (1 * 0x400); + ppu->PPU_VRAM_banks[0x02] = PPU_patterntables + (2 * 0x400); + ppu->PPU_VRAM_banks[0x03] = PPU_patterntables + (3 * 0x400); + + ppu->PPU_VRAM_banks[0x04] = PPU_patterntables + (4 * 0x400); + ppu->PPU_VRAM_banks[0x05] = PPU_patterntables + (5 * 0x400); + ppu->PPU_VRAM_banks[0x06] = PPU_patterntables + (6 * 0x400); + ppu->PPU_VRAM_banks[0x07] = PPU_patterntables + (7 * 0x400); // point nametables at internal name table 0 ppu->PPU_VRAM_banks[0x08] = ppu->PPU_nametables; ppu->PPU_VRAM_banks[0x09] = ppu->PPU_nametables; ppu->PPU_VRAM_banks[0x0A] = ppu->PPU_nametables; ppu->PPU_VRAM_banks[0x0B] = ppu->PPU_nametables; - - ppu->PPU_tile_tables=VROM_tiles;//不确定正确 - //BYTES_PER_COMPILED_TILE=16 - ppu->PPU_tile_banks[0x00] = ppu->PPU_tile_tables + (0*0x400); - ppu->PPU_tile_banks[0x01] = ppu->PPU_tile_tables + (1*0x400); - ppu->PPU_tile_banks[0x02] = ppu->PPU_tile_tables + (2*0x400); - ppu->PPU_tile_banks[0x03] = ppu->PPU_tile_tables + (3*0x400); - ppu->PPU_tile_banks[0x04] = ppu->PPU_tile_tables + (4*0x400); - ppu->PPU_tile_banks[0x05] = ppu->PPU_tile_tables + (5*0x400); - ppu->PPU_tile_banks[0x06] = ppu->PPU_tile_tables + (6*0x400); - ppu->PPU_tile_banks[0x07] = ppu->PPU_tile_tables + (7*0x400); + + ppu->PPU_tile_tables = VROM_tiles; // 不确定正确 + // BYTES_PER_COMPILED_TILE=16 + ppu->PPU_tile_banks[0x00] = ppu->PPU_tile_tables + (0 * 0x400); + ppu->PPU_tile_banks[0x01] = ppu->PPU_tile_tables + (1 * 0x400); + ppu->PPU_tile_banks[0x02] = ppu->PPU_tile_tables + (2 * 0x400); + ppu->PPU_tile_banks[0x03] = ppu->PPU_tile_tables + (3 * 0x400); + ppu->PPU_tile_banks[0x04] = ppu->PPU_tile_tables + (4 * 0x400); + ppu->PPU_tile_banks[0x05] = ppu->PPU_tile_tables + (5 * 0x400); + ppu->PPU_tile_banks[0x06] = ppu->PPU_tile_tables + (6 * 0x400); + ppu->PPU_tile_banks[0x07] = ppu->PPU_tile_tables + (7 * 0x400); ppu->read_2007_buffer = 0x00; ppu->in_vblank = 0; @@ -295,165 +273,142 @@ void PPU_reset(void *lcd_addr) ppu->spr_ram_rw_ptr = 0; ppu->read_2007_buffer = 0; ppu->current_frame_line = 0; - - if(RomHeader->flags_1 &0x01)set_mirroring(0,1,0,1);//垂直镜像 // PPU_set_mirroring(); 设置镜像 - else set_mirroring(0,0,1,1);//水平镜像 + if (RomHeader->flags_1 & 0x01) + set_mirroring(0, 1, 0, 1); // 垂直镜像 // PPU_set_mirroring(); + // 设置镜像 + else + set_mirroring(0, 0, 1, 1); // 水平镜像 } //*********************************************************************************************** -void set_mirroring(uint32 nt0, uint32 nt1, uint32 nt2, uint32 nt3)//设置垂直水平镜像 +void set_mirroring(uint32_t nt0, uint32_t nt1, uint32_t nt2, + uint32_t nt3) // 设置垂直水平镜像 { ppu->PPU_VRAM_banks[0x08] = ppu->PPU_nametables + (nt0 << 10); // * 0x0400 ppu->PPU_VRAM_banks[0x09] = ppu->PPU_nametables + (nt1 << 10); ppu->PPU_VRAM_banks[0x0A] = ppu->PPU_nametables + (nt2 << 10); ppu->PPU_VRAM_banks[0x0B] = ppu->PPU_nametables + (nt3 << 10); -// name_table_switched = TRUE; + // name_table_switched = TRUE; } -void PPU_start_frame(void) -{ +void PPU_start_frame(void) { ppu->current_frame_line = 0; - if(spr_enabled() || bg_enabled()) - { + if (spr_enabled() || bg_enabled()) { ppu->loopy_v = ppu->loopy_t; } } -uint8 getBGColor() { return ppu->bg_pal[0]; } +uint8_t getBGColor() { return ppu->bg_pal[0]; } -void do_scanline_and_draw(uint8* buf) -{ - uint16 i; - if(!bg_enabled()) - { +void do_scanline_and_draw(uint8_t *buf) { + uint16_t i; + if (!bg_enabled()) { // set to background color设置背景颜色 -// memset(buf, bg_pal[0], NES_BACKBUF_WIDTH);//NES_BACKBUF_WIDTH=256+(2*8) - for(i=0;i<(256+16);i++) - { - buf[i]=ppu->bg_pal[0]; - } - + // memset(buf, bg_pal[0], + // NES_BACKBUF_WIDTH);//NES_BACKBUF_WIDTH=256+(2*8) + for (i = 0; i < (256 + 16); i++) { + buf[i] = ppu->bg_pal[0]; + } } - if(spr_enabled() || bg_enabled()) - { + if (spr_enabled() || bg_enabled()) { LOOPY_SCANLINE_START(ppu->loopy_v, ppu->loopy_t); - if(bg_enabled()) - { + if (bg_enabled()) { // draw background画背景 render_bg(buf); - } - else - { + } else { // clear out solid buffer清除固体缓冲区 - memset(ppu->solid_buf, 0x00, sizeof(ppu->solid_buf)); + memset(ppu->solid_buf, 0x00, sizeof(ppu->solid_buf)); } - if(spr_enabled()) - { + if (spr_enabled()) { // draw sprites绘制精灵 render_spr(buf); } LOOPY_NEXT_LINE(ppu->loopy_v); } - ppu->current_frame_line++; + ppu->current_frame_line++; } -extern u8 nes_xoff; //显示在x轴方向的偏移量(实际显示宽度=256-2*nes_xoff) +extern u8 nes_xoff; // 显示在x轴方向的偏移量(实际显示宽度=256-2*nes_xoff) extern u8 nes_yoff; -void scanline_draw(int LineNo) -{ - uint16 i; - u16 sx,ex; - do_scanline_and_draw(ppu->dummy_buffer); - sx=0+8; - ex=256+8-0; - { - for(i=sx;idummy_buffer[i]]; - LCD_ADDR[((NES_scanline+nes_yoff)*480+(i-8+nes_xoff))]=NES_Palette[ppu->dummy_buffer[i]]; - } - } +void scanline_draw(int LineNo) { + uint16_t i; + u16 sx, ex; + do_scanline_and_draw(ppu->dummy_buffer); + sx = 0 + 8; + ex = 256 + 8 - 0; + { + for (i = sx; i < ex; i++) { + // LCD_ADDR[(480*272-1)-((NES_scanline+nes_yoff)*480+(i-8+nes_xoff))]=NES_Palette[ppu->dummy_buffer[i]]; + LCD_ADDR[((NES_scanline + nes_yoff) * 480 + (i - 8 + nes_xoff))] = + NES_Palette[ppu->dummy_buffer[i]]; + } + } } -void do_scanline_and_dont_draw(int LineNo) -{ -// uint16 i; - // mmc2 / punchout -- we must simulate the ppu for every line -// if(parent_NES->ROM->get_mapper_num() == 9) -// { -// do_scanline_and_draw(ppu->dummy_buffer); -// } -// else - { - // if sprite 0 flag not set and sprite 0 on current line - if((!sprite0_hit()) && - (ppu->current_frame_line >= ((uint32)(spr_ram[0]+1))) && - (ppu->current_frame_line < ((uint32)(spr_ram[0]+1+(sprites_8x16()?16:8)))) - ) - { - // render line to dummy buffer - do_scanline_and_draw(ppu->dummy_buffer); - - } - else - { - if(spr_enabled() || bg_enabled()) - { - LOOPY_SCANLINE_START(ppu->loopy_v, ppu->loopy_t); - LOOPY_NEXT_LINE(ppu->loopy_v); - } - ppu->current_frame_line++; - } - } +void do_scanline_and_dont_draw(int LineNo) { + // uint16_t i; + // mmc2 / punchout -- we must simulate the ppu for every line + // if(parent_NES->ROM->get_mapper_num() == 9) + // { + // do_scanline_and_draw(ppu->dummy_buffer); + // } + // else + { + // if sprite 0 flag not set and sprite 0 on current line + if ((!sprite0_hit()) && + (ppu->current_frame_line >= ((uint32_t)(spr_ram[0] + 1))) && + (ppu->current_frame_line < + ((uint32_t)(spr_ram[0] + 1 + (sprites_8x16() ? 16 : 8))))) { + // render line to dummy buffer + do_scanline_and_draw(ppu->dummy_buffer); -} -void start_vblank() -{ + } else { + if (spr_enabled() || bg_enabled()) { + LOOPY_SCANLINE_START(ppu->loopy_v, ppu->loopy_t); + LOOPY_NEXT_LINE(ppu->loopy_v); + } + ppu->current_frame_line++; + } + } +} +void start_vblank() { ppu->in_vblank = 1; // set vblank register flag ppu->LowRegs[2] |= 0x80; } -void end_vblank() -{ +void end_vblank() { ppu->in_vblank = 0; // reset vblank register flag and sprite0 hit flag1 ppu->LowRegs[2] &= 0x3F; } - // these functions read from/write to VRAM using loopy_v -uint8 read_2007() -{ - uint16 addr; - uint8 temp; +uint8_t read_2007() { + uint16_t addr; + uint8_t temp; addr = ppu->loopy_v; ppu->loopy_v += ppu->ppu_addr_inc; addr &= 0x3FFF; - if(addr >= 0x3000) - { + if (addr >= 0x3000) { // is it a palette entry? - if(addr >= 0x3F00) - { + if (addr >= 0x3F00) { // palette // handle palette mirroring - if(0x0000 == (addr & 0x0010)) - { + if (0x0000 == (addr & 0x0010)) { // background palette return ppu->bg_pal[addr & 0x000F]; - } - else - { + } else { // sprite palette return ppu->spr_pal[addr & 0x000F]; } @@ -469,34 +424,27 @@ uint8 read_2007() return temp; } -void write_2007(uint8 data) -{ - uint16 addr; +void write_2007(uint8_t data) { + uint16_t addr; addr = ppu->loopy_v; ppu->loopy_v += ppu->ppu_addr_inc; addr &= 0x3FFF; - if(addr >= 0x3000) - { + if (addr >= 0x3000) { // is it a palette entry? - if(addr >= 0x3F00) - { + if (addr >= 0x3F00) { // palette data &= 0x3F; - if(0x0000 == (addr & 0x000F)) // is it THE 0 entry?0的条目吗 + if (0x0000 == (addr & 0x000F)) // is it THE 0 entry?0的条目吗 { ppu->bg_pal[0] = ppu->spr_pal[0] = data; - } - else if(0x0000 == (addr & 0x0010)) - { + } else if (0x0000 == (addr & 0x0010)) { // background palette ppu->bg_pal[addr & 0x000F] = data; - } - else - { + } else { // sprite palette ppu->spr_pal[addr & 0x000F] = data; } @@ -510,338 +458,319 @@ void write_2007(uint8 data) VRAM(addr) = data; if (addr < 0x2000) { -#if NES_RAM_SPEED==1 //1:内存占用小 0:速度快 - - *(TILE(addr) + (addr & 0xf )) = data;//************************ -#else - update_tile(addr, data); -#endif +#if NES_RAM_SPEED == 1 // 1:内存占用小 0:速度快 + + *(TILE(addr) + (addr & 0xf)) = data; //************************ +#else + update_tile(addr, data); +#endif } } -#define UPDATE_4_PIXELS() \ - col = 0; \ - if(data & pattern_mask) col |= (bit << 6); \ - pattern_mask >>= 1; \ - if(data & pattern_mask) col |= (bit << 4); \ - pattern_mask >>= 1; \ - if(data & pattern_mask) col |= (bit << 2); \ - pattern_mask >>= 1; \ - if(data & pattern_mask) col |= (bit << 0); \ - *p++ |= col; +#define UPDATE_4_PIXELS() \ + col = 0; \ + if (data & pattern_mask) \ + col |= (bit << 6); \ + pattern_mask >>= 1; \ + if (data & pattern_mask) \ + col |= (bit << 4); \ + pattern_mask >>= 1; \ + if (data & pattern_mask) \ + col |= (bit << 2); \ + pattern_mask >>= 1; \ + if (data & pattern_mask) \ + col |= (bit << 0); \ + *p++ |= col; -void update_tile(int byte_offset, uint8 data) -{ - //int tileNum = byte_offset >> 4; - int line = byte_offset & 0xf; +void update_tile(int byte_offset, uint8_t data) { + // int tileNum = byte_offset >> 4; + int line = byte_offset & 0xf; - uint8 *p = TILE(byte_offset) + TILE_OFFSET(line & 0x7); - uint8 bit; - uint8 pattern_mask; - int col; + uint8_t *p = TILE(byte_offset) + TILE_OFFSET(line & 0x7); + uint8_t bit; + uint8_t pattern_mask; + int col; - if (line < 8) { - // low pattern - bit = 0x01; + if (line < 8) { + // low pattern + bit = 0x01; - *(uint16 *)p &= 0xaaaa; + *(uint16_t *)p &= 0xaaaa; - } else { - // high pattern - bit = 0x02; - *(uint16 *)p &= 0x5555; - } + } else { + // high pattern + bit = 0x02; + *(uint16_t *)p &= 0x5555; + } - pattern_mask = 0x80; - - - UPDATE_4_PIXELS(); - pattern_mask >>= 1; - UPDATE_4_PIXELS(); + pattern_mask = 0x80; + UPDATE_4_PIXELS(); + pattern_mask >>= 1; + UPDATE_4_PIXELS(); } -uint8 PPU_ReadFromPort(uint16 addr) -{ - uint8 temp; - - - //switch(addr) - switch(addr & 0x7) - { - //case 0x2002: - case 0x2: - // clear toggle - ppu->toggle_2005_2006 = 0; +uint8_t PPU_ReadFromPort(uint16_t addr) { + uint8_t temp; - temp = ppu->LowRegs[2]; + // switch(addr) + switch (addr & 0x7) { + // case 0x2002: + case 0x2: + // clear toggle + ppu->toggle_2005_2006 = 0; - // clear v-blank flag - ppu->LowRegs[2] &= 0x7F; + temp = ppu->LowRegs[2]; - return temp; - -// break; + // clear v-blank flag + ppu->LowRegs[2] &= 0x7F; - //case 0x2007: - case 0x7: - return read_2007(); -// break; + return temp; + // break; + + // case 0x2007: + case 0x7: + return read_2007(); + // break; } return ppu->LowRegs[addr & 0x0007]; } -void PPU_WriteToPort(uint8 data,uint16 addr ) -{ - -// uint32 t; - ppu->LowRegs[addr & 0x0007] = data; +void PPU_WriteToPort(uint8_t data, uint16_t addr) { - //switch(addr) - switch(addr & 0x7) - { - //case 0x2000: - case 0: - { - ppu->bg_pattern_table_addr = (data & 0x10) ? 0x1000 : 0x0000; - ppu->spr_pattern_table_addr = (data & 0x08) ? 0x1000 : 0x0000; - ppu->ppu_addr_inc = (data & 0x04) ? 32 : 1; + // uint32_t t; + ppu->LowRegs[addr & 0x0007] = data; - // t:0000110000000000=d:00000011 - ppu->loopy_t = (ppu->loopy_t & 0xF3FF) | (((uint16)(data & 0x03)) << 10); + // switch(addr) + switch (addr & 0x7) { + // case 0x2000: + case 0: { + ppu->bg_pattern_table_addr = (data & 0x10) ? 0x1000 : 0x0000; + ppu->spr_pattern_table_addr = (data & 0x08) ? 0x1000 : 0x0000; + ppu->ppu_addr_inc = (data & 0x04) ? 32 : 1; - break; - } + // t:0000110000000000=d:00000011 + ppu->loopy_t = (ppu->loopy_t & 0xF3FF) | (((uint16_t)(data & 0x03)) << 10); - // Rick, lazy updating stuff - //case 0x2001: -// case 1: -// bg_enabled(); -// -// spr_enabled(); -// break; + break; + } - //case 0x2003: - case 3: - ppu->spr_ram_rw_ptr = data; - break; + // Rick, lazy updating stuff + // case 0x2001: + // case 1: + // bg_enabled(); + // + // spr_enabled(); + // break; - //case 0x2004: - case 4: - spr_ram[ppu->spr_ram_rw_ptr++] = data; - break; + // case 0x2003: + case 3: + ppu->spr_ram_rw_ptr = data; + break; - //case 0x2005: - case 5: - ppu->toggle_2005_2006 = !ppu->toggle_2005_2006; + // case 0x2004: + case 4: + spr_ram[ppu->spr_ram_rw_ptr++] = data; + break; - if(ppu->toggle_2005_2006) - { - // first write - - // t:0000000000011111=d:11111000 - ppu->loopy_t = (ppu->loopy_t & 0xFFE0) | (((uint16)(data & 0xF8)) >> 3); + // case 0x2005: + case 5: + ppu->toggle_2005_2006 = !ppu->toggle_2005_2006; - // x=d:00000111 - ppu->loopy_x = data & 0x07; + if (ppu->toggle_2005_2006) { + // first write - } - else - { - // second write + // t:0000000000011111=d:11111000 + ppu->loopy_t = (ppu->loopy_t & 0xFFE0) | (((uint16_t)(data & 0xF8)) >> 3); - // t:0000001111100000=d:11111000 - ppu->loopy_t = (ppu->loopy_t & 0xFC1F) | (((uint16)(data & 0xF8)) << 2); - - // t:0111000000000000=d:00000111 - ppu->loopy_t = (ppu->loopy_t & 0x8FFF) | (((uint16)(data & 0x07)) << 12); - - } + // x=d:00000111 + ppu->loopy_x = data & 0x07; - break; + } else { + // second write - //case 0x2006: - case 6: - ppu->toggle_2005_2006 = !ppu->toggle_2005_2006; + // t:0000001111100000=d:11111000 + ppu->loopy_t = (ppu->loopy_t & 0xFC1F) | (((uint16_t)(data & 0xF8)) << 2); - if(ppu->toggle_2005_2006) - { - // first write + // t:0111000000000000=d:00000111 + ppu->loopy_t = (ppu->loopy_t & 0x8FFF) | (((uint16_t)(data & 0x07)) << 12); + } - // t:0011111100000000=d:00111111 - // t:1100000000000000=0 - ppu->loopy_t = (ppu->loopy_t & 0x00FF) | (((uint16)(data & 0x3F)) << 8); - } - else - { - // second write - // t:0000000011111111=d:11111111 - ppu->loopy_t = (ppu->loopy_t & 0xFF00) | ((uint16)data); + break; - // v=t - ppu->loopy_v = ppu->loopy_t; - } + // case 0x2006: + case 6: + ppu->toggle_2005_2006 = !ppu->toggle_2005_2006; - break; + if (ppu->toggle_2005_2006) { + // first write - //case 0x2007: - case 7: - write_2007(data); - break; + // t:0011111100000000=d:00111111 + // t:1100000000000000=0 + ppu->loopy_t = (ppu->loopy_t & 0x00FF) | (((uint16_t)(data & 0x3F)) << 8); + } else { + // second write + // t:0000000011111111=d:11111111 + ppu->loopy_t = (ppu->loopy_t & 0xFF00) | ((uint16_t)data); + + // v=t + ppu->loopy_v = ppu->loopy_t; + } + + break; + + // case 0x2007: + case 7: + write_2007(data); + break; } } //***************************************************************************** -#define DRAW_BG_PIXEL() \ - col = attrib_bits; \ - \ - if(pattern_lo & pattern_mask) col |= 0x01; \ - if(pattern_hi & pattern_mask) col |= 0x02; \ - \ - if(col & 0x03) \ - { \ - *p = ppu->bg_pal[col]; \ - /* set solid flag */ \ - *solid = BG_WRITTEN_FLAG; \ - } \ - else \ - { \ - *p = ppu->bg_pal[0]; \ - /* set solid flag */ \ - *solid = 0; \ - } \ - solid++; \ - p++; \ +#define DRAW_BG_PIXEL() \ + col = attrib_bits; \ + \ + if (pattern_lo & pattern_mask) \ + col |= 0x01; \ + if (pattern_hi & pattern_mask) \ + col |= 0x02; \ + \ + if (col & 0x03) { \ + *p = ppu->bg_pal[col]; \ + /* set solid flag */ \ + *solid = BG_WRITTEN_FLAG; \ + } else { \ + *p = ppu->bg_pal[0]; \ + /* set solid flag */ \ + *solid = 0; \ + } \ + solid++; \ + p++; \ //*************************************************************************************** -#define NEW_BG_PIXEL() \ - if (col) {\ - col |= attrib_bits; \ - *solid = BG_WRITTEN_FLAG; \ - } else { \ - col = 0; \ - *solid = 0; \ - } \ - *p = ppu->bg_pal[col]; \ - solid++; \ - p++; \ +#define NEW_BG_PIXEL() \ + if (col) { \ + col |= attrib_bits; \ + *solid = BG_WRITTEN_FLAG; \ + } else { \ + col = 0; \ + *solid = 0; \ + } \ + *p = ppu->bg_pal[col]; \ + solid++; \ + p++; +void render_bg(uint8_t *buf) { + uint8_t *p; + uint32_t i; + uint8_t *solid; + uint8_t *data; + uint32_t col; -void render_bg(uint8* buf) -{ - uint8 *p; - uint32 i; - uint8 *solid; - uint8 *data; - uint32 col; + uint32_t tile_x; // pixel coords within nametable像素坐标内nametable + uint32_t tile_y; + uint32_t name_addr; + uint32_t line; + uint32_t pattern_addr; - uint32 tile_x; // pixel coords within nametable像素坐标内nametable - uint32 tile_y; - uint32 name_addr; - uint32 line; - uint32 pattern_addr; + uint32_t attrib_addr; + uint32_t attrib_bits; - uint32 attrib_addr; - uint32 attrib_bits; - -#if NES_RAM_SPEED==1 //1:内存占用小 0:速度快 - uint8 pattern_lo; - uint8 pattern_hi; - uint8 pattern_mask; -#else - int col2; -#endif +#if NES_RAM_SPEED == 1 // 1:内存占用小 0:速度快 + uint8_t pattern_lo; + uint8_t pattern_hi; + uint8_t pattern_mask; +#else + int col2; +#endif tile_x = (ppu->loopy_v & 0x001F); tile_y = (ppu->loopy_v & 0x03E0) >> 5; name_addr = 0x2000 + (ppu->loopy_v & 0x0FFF); - attrib_addr = 0x2000 + (ppu->loopy_v & 0x0C00) + 0x03C0 + ((tile_y & 0xFFFC)<<1) + (tile_x>>2); - if(0x0000 == (tile_y & 0x0002)) - if(0x0000 == (tile_x & 0x0002)) + attrib_addr = 0x2000 + (ppu->loopy_v & 0x0C00) + 0x03C0 + + ((tile_y & 0xFFFC) << 1) + (tile_x >> 2); + if (0x0000 == (tile_y & 0x0002)) + if (0x0000 == (tile_x & 0x0002)) attrib_bits = (VRAM(attrib_addr) & 0x03) << 2; else attrib_bits = (VRAM(attrib_addr) & 0x0C); + else if (0x0000 == (tile_x & 0x0002)) + attrib_bits = (VRAM(attrib_addr) & 0x30) >> 2; else - if(0x0000 == (tile_x & 0x0002)) - attrib_bits = (VRAM(attrib_addr) & 0x30) >> 2; - else - attrib_bits = (VRAM(attrib_addr) & 0xC0) >> 4; + attrib_bits = (VRAM(attrib_addr) & 0xC0) >> 4; - p = buf + (SIDE_MARGIN - ppu->loopy_x); - solid = ppu->solid_buf + (SIDE_MARGIN - ppu->loopy_x); // set "solid" buffer ptr + p = buf + (SIDE_MARGIN - ppu->loopy_x); + solid = + ppu->solid_buf + (SIDE_MARGIN - ppu->loopy_x); // set "solid" buffer ptr - line = (ppu->loopy_v & 0x7000) >> 12; // draw 33 tiles - for(i = 33; i; i--) - { - - pattern_addr = ppu->bg_pattern_table_addr + ((int32)VRAM(name_addr) << 4) + line; + for (i = 33; i; i--) { - // CHECK_MMC2(pattern_addr);//******************************************************* + pattern_addr = + ppu->bg_pattern_table_addr + ((int32_t)VRAM(name_addr) << 4) + line; -#if NES_RAM_SPEED==1 //1:内存占用小 0:速度快 - data = TILE(pattern_addr) + line; - - pattern_lo = *data; - pattern_hi = *(data + 8); - pattern_mask = 0x80; + // CHECK_MMC2(pattern_addr);//******************************************************* - DRAW_BG_PIXEL(); - pattern_mask >>= 1; - DRAW_BG_PIXEL(); - pattern_mask >>= 1; - DRAW_BG_PIXEL(); - pattern_mask >>= 1; - DRAW_BG_PIXEL(); - pattern_mask >>= 1; - DRAW_BG_PIXEL(); - pattern_mask >>= 1; - DRAW_BG_PIXEL(); - pattern_mask >>= 1; - DRAW_BG_PIXEL(); - pattern_mask >>= 1; - DRAW_BG_PIXEL(); -#else - data = TILE(pattern_addr) + TILE_OFFSET(line); +#if NES_RAM_SPEED == 1 // 1:内存占用小 0:速度快 + data = TILE(pattern_addr) + line; - col2 = *data++; - col = col2 >> 6; - NEW_BG_PIXEL(); - col = (col2 >> 4) & 0x03; - NEW_BG_PIXEL(); - col = (col2 >> 2) & 0x03; - NEW_BG_PIXEL(); - col = col2 & 0x03; - NEW_BG_PIXEL(); - - col2 = *data++; - col = col2 >> 6; - NEW_BG_PIXEL(); - col = (col2 >> 4) & 0x03; - NEW_BG_PIXEL(); - col = (col2 >> 2) & 0x03; - NEW_BG_PIXEL(); - col = col2 & 0x03; - NEW_BG_PIXEL(); -#endif + pattern_lo = *data; + pattern_hi = *(data + 8); + pattern_mask = 0x80; + + DRAW_BG_PIXEL(); + pattern_mask >>= 1; + DRAW_BG_PIXEL(); + pattern_mask >>= 1; + DRAW_BG_PIXEL(); + pattern_mask >>= 1; + DRAW_BG_PIXEL(); + pattern_mask >>= 1; + DRAW_BG_PIXEL(); + pattern_mask >>= 1; + DRAW_BG_PIXEL(); + pattern_mask >>= 1; + DRAW_BG_PIXEL(); + pattern_mask >>= 1; + DRAW_BG_PIXEL(); +#else + data = TILE(pattern_addr) + TILE_OFFSET(line); + + col2 = *data++; + col = col2 >> 6; + NEW_BG_PIXEL(); + col = (col2 >> 4) & 0x03; + NEW_BG_PIXEL(); + col = (col2 >> 2) & 0x03; + NEW_BG_PIXEL(); + col = col2 & 0x03; + NEW_BG_PIXEL(); + + col2 = *data++; + col = col2 >> 6; + NEW_BG_PIXEL(); + col = (col2 >> 4) & 0x03; + NEW_BG_PIXEL(); + col = (col2 >> 2) & 0x03; + NEW_BG_PIXEL(); + col = col2 & 0x03; + NEW_BG_PIXEL(); +#endif tile_x++; name_addr++; // are we crossing a dual-tile boundary?我们穿越dual-tile边界吗? - if(0x0000 == (tile_x & 0x0001)) - { + if (0x0000 == (tile_x & 0x0001)) { // are we crossing a quad-tile boundary? - if(0x0000 == (tile_x & 0x0003)) - { + if (0x0000 == (tile_x & 0x0003)) { // are we crossing a name table boundary? - if(0x0000 == (tile_x & 0x001F)) - { + if (0x0000 == (tile_x & 0x001F)) { name_addr ^= 0x0400; // switch name tables attrib_addr ^= 0x0400; name_addr -= 0x0020; @@ -852,211 +781,192 @@ void render_bg(uint8* buf) attrib_addr++; } - if(0x0000 == (tile_y & 0x0002)) - if(0x0000 == (tile_x & 0x0002)) + if (0x0000 == (tile_y & 0x0002)) + if (0x0000 == (tile_x & 0x0002)) attrib_bits = (VRAM(attrib_addr) & 0x03) << 2; else attrib_bits = (VRAM(attrib_addr) & 0x0C); + else if (0x0000 == (tile_x & 0x0002)) + attrib_bits = (VRAM(attrib_addr) & 0x30) >> 2; else - if(0x0000 == (tile_x & 0x0002)) - attrib_bits = (VRAM(attrib_addr) & 0x30) >> 2; - else - attrib_bits = (VRAM(attrib_addr) & 0xC0) >> 4; + attrib_bits = (VRAM(attrib_addr) & 0xC0) >> 4; } } -// if(bg_clip_left8()) -// { -// // clip left 8 pixels夹了8个像素SIDE_MARGIN = 8, -// memset(buf + SIDE_MARGIN, bg_pal[0], 8); -// memset(solid + SIDE_MARGIN, 0, sizeof(solid[0])*8); -// } -} -void render_spr(uint8* buf) -{ - int32 s; // sprite # - int32 spr_x; // sprite coordinates - uint32 spr_y; - uint8* spr; // pointer to sprite RAM entry - uint8* p; // draw pointer - int line; - //uint32 *solid; - uint8 *solid; - uint32 priority; - uint32 tile_addr; - int32 inc_x; // drawing vars - int32 start_x, end_x; - int32 x,y; // in-sprite coords - uint32 col; - uint32 num_sprites = 0; - uint8 *t; - - uint32 spr_height; - -#if NES_RAM_SPEED==1 //1:内存占用小 0:速度快 - - uint8 pattern_lo; - uint8 pattern_hi; -#else - uint32 pattern; -#endif - - spr_height = sprites_8x16() ? 16 : 8; - - //for(s = 0; s < 64; s++) - for(s = 0, spr = spr_ram; s < 64; s++, spr+=4) - { - - spr_y = spr[0]+1; - - // on current scanline对当前扫描线? - if((spr_y > ppu->current_frame_line) || ((spr_y+(spr_height)) <= ppu->current_frame_line)) - continue; - - num_sprites++; - if(num_sprites > 8) - { - /*if(!show_more_than_8_sprites)*/ break;//************************************** - } - - // get x coord - spr_x = spr[3]; - - start_x = 0; - end_x = 8; - - // clip right - if((spr_x + 7) > 255) - { - end_x -= ((spr_x + 7) - 255); - } - - // clip left - if((spr_x < 8) && (spr_clip_left8())) - { - if(0 == spr_x) continue; - start_x += (8 - spr_x); - } - - y = ppu->current_frame_line - spr_y; - -// CHECK_MMC2(spr[1] << 4);//************************************************************************** - - // calc offsets into buffers - p = &buf[SIDE_MARGIN + spr_x + start_x]; - solid = &ppu->solid_buf[SIDE_MARGIN + spr_x + start_x]; - - // flip horizontally? - if(spr[2] & 0x40) // yes - { - inc_x = -1; - start_x = (8-1) - start_x; - end_x = (8-1) - end_x; - } - else - { - inc_x = 1; - } - - // flip vertically? - if(spr[2] & 0x80) // yes - { - y = (spr_height-1) - y; - } - line = y & 7; - - // get priority bit - priority = spr[2] & 0x20; - - tile_addr = spr[1] << 4; - if(sprites_8x16()) { - if(spr[1] & 0x01) { - tile_addr += 0x1000; - if(y < 8) tile_addr -= 16; - } else { - if(y >= 8) tile_addr += 16; - } - } else { - tile_addr += ppu->spr_pattern_table_addr; - } - -#if NES_RAM_SPEED==1 //1:内存占用小 0:速度快 - t = TILE(tile_addr) + line; - - pattern_lo = *t; - pattern_hi = *(t + 8); - -#else - // read 16bits = 2bits x 8pixels - t = TILE(tile_addr) + TILE_OFFSET(line); - pattern = ((uint32)*t << 8) | *(t + 1); - -#endif - - for(x = start_x; x != end_x; x += inc_x) - { - //uint8 col = 0x00; - - // if a sprite has drawn on this pixel, don't draw anything如果一个雪碧吸引了这个像素,不画任何东西 - if(!((*solid) & SPR_WRITTEN_FLAG)) - { - -#if NES_RAM_SPEED==1 //1:内存占用小 0:速度快 - - col = ((pattern_hi>>(7-x)<<1)&2)|((pattern_lo>>(7-x))&1); -#else - col = pattern >> ((7 - (x & 7)) * 2); -#endif - col &= 0x03; - - if (col) { - col |= (spr[2] & 0x03) << 2; - - // set sprite 0 hit flag - if(!s) - { - if((*solid) & BG_WRITTEN_FLAG) - { - ppu->LowRegs[2] |= 0x40; - } - } - - (*solid) |= SPR_WRITTEN_FLAG; - if(priority) - { - //(*solid) |= SPR_WRITTEN_FLAG; - if(!((*solid) & BG_WRITTEN_FLAG)) - { - *p = ppu->spr_pal[col]; - } - } - else - { - - *p = ppu->spr_pal[col]; - } - } - } - - p++; - solid++; - } - } - - if(num_sprites >= 8) - { - ppu->LowRegs[2] |= 0x20; - } - else - { - ppu->LowRegs[2] &= 0xDF; - } + // if(bg_clip_left8()) + // { + // // clip left 8 pixels夹了8个像素SIDE_MARGIN = 8, + // memset(buf + SIDE_MARGIN, bg_pal[0], 8); + // memset(solid + SIDE_MARGIN, 0, sizeof(solid[0])*8); + // } } +void render_spr(uint8_t *buf) { + int32_t s; // sprite # + int32_t spr_x; // sprite coordinates + uint32_t spr_y; + uint8_t *spr; // pointer to sprite RAM entry + uint8_t *p; // draw pointer + int line; + // uint32_t *solid; + uint8_t *solid; + uint32_t priority; + uint32_t tile_addr; + int32_t inc_x; // drawing vars + int32_t start_x, end_x; + int32_t x, y; // in-sprite coords + uint32_t col; + uint32_t num_sprites = 0; + uint8_t *t; + uint32_t spr_height; +#if NES_RAM_SPEED == 1 // 1:内存占用小 0:速度快 + uint8_t pattern_lo; + uint8_t pattern_hi; +#else + uint32_t pattern; +#endif + spr_height = sprites_8x16() ? 16 : 8; + // for(s = 0; s < 64; s++) + for (s = 0, spr = spr_ram; s < 64; s++, spr += 4) { + spr_y = spr[0] + 1; + // on current scanline对当前扫描线? + if ((spr_y > ppu->current_frame_line) || + ((spr_y + (spr_height)) <= ppu->current_frame_line)) + continue; + num_sprites++; + if (num_sprites > 8) { + /*if(!show_more_than_8_sprites)*/ + break; //************************************** + } + + // get x coord + spr_x = spr[3]; + + start_x = 0; + end_x = 8; + + // clip right + if ((spr_x + 7) > 255) { + end_x -= ((spr_x + 7) - 255); + } + + // clip left + if ((spr_x < 8) && (spr_clip_left8())) { + if (0 == spr_x) + continue; + start_x += (8 - spr_x); + } + + y = ppu->current_frame_line - spr_y; + + // CHECK_MMC2(spr[1] << + //4);//************************************************************************** + + // calc offsets into buffers + p = &buf[SIDE_MARGIN + spr_x + start_x]; + solid = &ppu->solid_buf[SIDE_MARGIN + spr_x + start_x]; + + // flip horizontally? + if (spr[2] & 0x40) // yes + { + inc_x = -1; + start_x = (8 - 1) - start_x; + end_x = (8 - 1) - end_x; + } else { + inc_x = 1; + } + + // flip vertically? + if (spr[2] & 0x80) // yes + { + y = (spr_height - 1) - y; + } + line = y & 7; + + // get priority bit + priority = spr[2] & 0x20; + + tile_addr = spr[1] << 4; + if (sprites_8x16()) { + if (spr[1] & 0x01) { + tile_addr += 0x1000; + if (y < 8) + tile_addr -= 16; + } else { + if (y >= 8) + tile_addr += 16; + } + } else { + tile_addr += ppu->spr_pattern_table_addr; + } + +#if NES_RAM_SPEED == 1 // 1:内存占用小 0:速度快 + t = TILE(tile_addr) + line; + + pattern_lo = *t; + pattern_hi = *(t + 8); + +#else + // read 16bits = 2bits x 8pixels + t = TILE(tile_addr) + TILE_OFFSET(line); + pattern = ((uint32_t)*t << 8) | *(t + 1); + +#endif + + for (x = start_x; x != end_x; x += inc_x) { + // uint8_t col = 0x00; + + // if a sprite has drawn on this pixel, don't draw + // anything如果一个雪碧吸引了这个像素,不画任何东西 + if (!((*solid) & SPR_WRITTEN_FLAG)) { + +#if NES_RAM_SPEED == 1 // 1:内存占用小 0:速度快 + + col = + ((pattern_hi >> (7 - x) << 1) & 2) | ((pattern_lo >> (7 - x)) & 1); +#else + col = pattern >> ((7 - (x & 7)) * 2); +#endif + col &= 0x03; + + if (col) { + col |= (spr[2] & 0x03) << 2; + + // set sprite 0 hit flag + if (!s) { + if ((*solid) & BG_WRITTEN_FLAG) { + ppu->LowRegs[2] |= 0x40; + } + } + + (*solid) |= SPR_WRITTEN_FLAG; + if (priority) { + //(*solid) |= SPR_WRITTEN_FLAG; + if (!((*solid) & BG_WRITTEN_FLAG)) { + *p = ppu->spr_pal[col]; + } + } else { + + *p = ppu->spr_pal[col]; + } + } + } + + p++; + solid++; + } + } + + if (num_sprites >= 8) { + ppu->LowRegs[2] |= 0x20; + } else { + ppu->LowRegs[2] &= 0xDF; + } +} diff --git a/Project/Src/NES/nes_ppu.h b/Project/Src/NES/nes_ppu.h index e690c56..e08b3ee 100644 --- a/Project/Src/NES/nes_ppu.h +++ b/Project/Src/NES/nes_ppu.h @@ -1,143 +1,128 @@ +////////////////////////////////////////////////////////////////////////////////// +// 本程序移植自网友ye781205的NES模拟器工程 +// ALIENTEK STM32F407开发板 +// NES APU 驱动代码 +// 正点原子@ALIENTEK +// 技术论坛:www.openedv.com +// 创建日期:2014/7/1 +// 版本:V1.0 +////////////////////////////////////////////////////////////////////////////////// + #ifndef __NES_PPU_H -#define __NES_PPU_H +#define __NES_PPU_H + #include "nes_main.h" -////////////////////////////////////////////////////////////////////////////////// -//本程序移植自网友ye781205的NES模拟器工程 -//ALIENTEK STM32F407开发板 -//NES APU 驱动代码 -//正点原子@ALIENTEK -//技术论坛:www.openedv.com -//创建日期:2014/7/1 -//版本:V1.0 -////////////////////////////////////////////////////////////////////////////////// +#undef NULL +#define NULL 0 -#undef NULL -#define NULL 0 - -#ifndef TRUE -#define TRUE 1 +#ifndef TRUE +#define TRUE 1 #endif -#ifndef FALSE -#define FALSE 0 +#ifndef FALSE +#define FALSE 0 #endif -static const unsigned int NES_Palette[64]= -{ - 0x73AE,0x20D1,0x0015,0x4013,0x880E,0xA802,0xA000,0x7840, - 0x4160,0x0220,0x0280,0x01E2,0x19EB,0x0000,0x0000,0x0000, - 0xBDF7,0x039D,0x21DD,0x801E,0xB817,0xE00B,0xD940,0xCA61, - 0x8B80,0x04A0,0x0540,0x0487,0x0411,0x0000,0x0000,0x0000, - 0xF79E,0x3DFF,0x5CBF,0xA45F,0xF3DF,0xFBB6,0xFBAC,0xFCC7, - 0xF5E7,0x8682,0x4EE9,0x5FD3,0x075B,0x0000,0x0000,0x0000, - 0xF79E,0xAF3F,0xC6BF,0xD65F,0xFE3F,0xFE3B,0xFDF6,0xFED5, - 0xFF34,0xE7F4,0xAF97,0xB7F9,0x9FFE,0x0000,0x0000,0x0000 -}; +static const unsigned int NES_Palette[64] = { + 0x73AE, 0x20D1, 0x0015, 0x4013, 0x880E, 0xA802, 0xA000, 0x7840, + 0x4160, 0x0220, 0x0280, 0x01E2, 0x19EB, 0x0000, 0x0000, 0x0000, + 0xBDF7, 0x039D, 0x21DD, 0x801E, 0xB817, 0xE00B, 0xD940, 0xCA61, + 0x8B80, 0x04A0, 0x0540, 0x0487, 0x0411, 0x0000, 0x0000, 0x0000, + 0xF79E, 0x3DFF, 0x5CBF, 0xA45F, 0xF3DF, 0xFBB6, 0xFBAC, 0xFCC7, + 0xF5E7, 0x8682, 0x4EE9, 0x5FD3, 0x075B, 0x0000, 0x0000, 0x0000, + 0xF79E, 0xAF3F, 0xC6BF, 0xD65F, 0xFE3F, 0xFE3B, 0xFDF6, 0xFED5, + 0xFF34, 0xE7F4, 0xAF97, 0xB7F9, 0x9FFE, 0x0000, 0x0000, 0x0000}; /* static unsigned int NES_Palette[64]= { - 0x73AE,0x20D1,0x0015,0x4013,0x880E,0xA802,0xA000,0x7840, - 0x4160,0x0220,0x0280,0x01E2,0x19EB,0x0000,0x0000,0x0000, - 0xBDF7,0x039D,0x21DD,0x801E,0xB817,0xE00B,0xD940,0xCA61, - 0x8B80,0x04A0,0x0540,0x0487,0x0411,0x0000,0x0000,0x0000, - 0xF79E,0x3DFF,0x5CBF,0xA45F,0xF3DF,0xFBB6,0xFBAC,0xFCC7, - 0xF5E7,0x8682,0x4EE9,0x5FD3,0x075B,0x0000,0x0000,0x0000, - 0xF79E,0xAF3F,0xC6BF,0xD65F,0xFE3F,0xFE3B,0xFDF6,0xFED5, - 0xFF34,0xE7F4,0xAF97,0xB7F9,0x9FFE,0x0000,0x0000,0x0000 + 0x73AE,0x20D1,0x0015,0x4013,0x880E,0xA802,0xA000,0x7840, + 0x4160,0x0220,0x0280,0x01E2,0x19EB,0x0000,0x0000,0x0000, + 0xBDF7,0x039D,0x21DD,0x801E,0xB817,0xE00B,0xD940,0xCA61, + 0x8B80,0x04A0,0x0540,0x0487,0x0411,0x0000,0x0000,0x0000, + 0xF79E,0x3DFF,0x5CBF,0xA45F,0xF3DF,0xFBB6,0xFBAC,0xFCC7, + 0xF5E7,0x8682,0x4EE9,0x5FD3,0x075B,0x0000,0x0000,0x0000, + 0xF79E,0xAF3F,0xC6BF,0xD65F,0xFE3F,0xFE3B,0xFDF6,0xFED5, + 0xFF34,0xE7F4,0xAF97,0xB7F9,0x9FFE,0x0000,0x0000,0x0000 }; */ +extern uint8_t + *VROM_banks; // VROM开始地址 图案表************************************* +extern uint8_t *VROM_tiles; +extern uint8_t *PPU_VRAM_banks[12]; +extern uint8_t *PPU_tile_banks[8]; +extern uint8_t *PPU_patterntables; // 8192//VROM开始地址 + // 图案表************************************* +extern uint8_t *spr_ram; // sprite ram - -extern u8* VROM_banks; //VROM开始地址 图案表************************************* -extern u8* VROM_tiles; -extern uint8* PPU_VRAM_banks[12]; -extern uint8* PPU_tile_banks[8]; -extern uint8* PPU_patterntables; //8192//VROM开始地址 图案表************************************* -extern uint8* spr_ram; //sprite ram - -enum -{ - NES_SCREEN_WIDTH = 256, - NES_SCREEN_HEIGHT = 240, - SIDE_MARGIN = 8, - NES_SCREEN_WIDTH_VIEWABLE = NES_SCREEN_WIDTH, - NES_BACKBUF_WIDTH = NES_SCREEN_WIDTH + (2*SIDE_MARGIN) +enum { + NES_SCREEN_WIDTH = 256, + NES_SCREEN_HEIGHT = 240, + SIDE_MARGIN = 8, + NES_SCREEN_WIDTH_VIEWABLE = NES_SCREEN_WIDTH, + NES_BACKBUF_WIDTH = NES_SCREEN_WIDTH + (2 * SIDE_MARGIN) }; -enum -{ - BG_WRITTEN_FLAG = 0x01, - SPR_WRITTEN_FLAG = 0x02 -}; +enum { BG_WRITTEN_FLAG = 0x01, SPR_WRITTEN_FLAG = 0x02 }; -typedef struct -{ - uint32 in_vblank; - uint32 current_frame_line; - uint16 bg_pattern_table_addr; - uint16 spr_pattern_table_addr; - uint16 ppu_addr_inc; - uint16 loopy_v; // vram address -- used for reading/writing through $2007 - // see loopy-2005.txt - uint16 loopy_t; // temp vram address - uint8 loopy_x; // 3-bit subtile x-offset - uint8 toggle_2005_2006; - uint8 spr_ram_rw_ptr; // sprite ram read/write pointer内存读/写指针 - uint8 read_2007_buffer; - uint8 LowRegs[0x08]; - uint8 bg_pal[0x10]; //extern BYTE BGPal[0x20]; //背景调色板 - uint8 spr_pal[0x10]; //extern BYTE SPPal[0x20]; //精灵调色板 +typedef struct { + uint32_t in_vblank; + uint32_t current_frame_line; + uint16_t bg_pattern_table_addr; + uint16_t spr_pattern_table_addr; + uint16_t ppu_addr_inc; + uint16_t loopy_v; // vram address -- used for reading/writing through $2007 + // see loopy-2005.txt + uint16_t loopy_t; // temp vram address + uint8_t loopy_x; // 3-bit subtile x-offset + uint8_t toggle_2005_2006; + uint8_t spr_ram_rw_ptr; // sprite ram read/write pointer内存读/写指针 + uint8_t read_2007_buffer; + uint8_t LowRegs[0x08]; + uint8_t bg_pal[0x10]; // extern BYTE BGPal[0x20]; + // //背景调色板 + uint8_t spr_pal[0x10]; // extern BYTE SPPal[0x20]; + // //精灵调色板 - uint8 PPU_nametables[4*0x400]; //4096 PPU真正的的RAM - // Rick - uint8* PPU_VRAM_banks[12]; - uint8* PPU_tile_banks[8]; - uint8* PPU_tile_tables; - uint8 solid_buf[NES_BACKBUF_WIDTH]; // 当前像素的位标志线 - uint8 dummy_buffer[NES_BACKBUF_WIDTH]; // used to do sprite 0 hit detection when we aren't supposed to draw - - -} ppu_data; + uint8_t PPU_nametables[4 * 0x400]; // 4096 PPU真正的的RAM + // Rick + uint8_t *PPU_VRAM_banks[12]; + uint8_t *PPU_tile_banks[8]; + uint8_t *PPU_tile_tables; + uint8_t solid_buf[NES_BACKBUF_WIDTH]; // 当前像素的位标志线 + uint8_t dummy_buffer[NES_BACKBUF_WIDTH]; // used to do sprite 0 hit detection + // when we aren't supposed to draw +} ppu_data; -extern ppu_data *ppu; -extern u8 *spr_ram; - +extern ppu_data *ppu; +extern uint8_t *spr_ram; - -uint32 spr_enabled(void); -uint32 bg_enabled(void); -void set_name_table(uint8 bank, int bank_num); -void set_tile_bank(int i, uint8 *bank); -void compile(int count, uint8 *src, uint8 *dest); -void set_tile_banks(uint8 *bank0, uint8 *bank1, uint8 *bank2, uint8 *bank3, -uint8 *bank4, uint8 *bank5, uint8 *bank6, uint8 *bank7); +uint32_t spr_enabled(void); +uint32_t bg_enabled(void); +void set_name_table(uint8_t bank, int bank_num); +void set_tile_bank(int i, uint8_t *bank); +void compile(int count, uint8_t *src, uint8_t *dest); +void set_tile_banks(uint8_t *bank0, uint8_t *bank1, uint8_t *bank2, uint8_t *bank3, + uint8_t *bank4, uint8_t *bank5, uint8_t *bank6, uint8_t *bank7); void PPU_reset(void *lcd_addr); void PPU_start_frame(void); -void set_mirroring(uint32 nt0, uint32 nt1, uint32 nt2, uint32 nt3);//设置垂直水平镜像 -uint8 ReadLowRegs(uint32 addr); -void WriteLowRegs(uint32 addr, uint8 data); +void set_mirroring(uint32_t nt0, uint32_t nt1, uint32_t nt2, + uint32_t nt3); // 设置垂直水平镜像 +uint8_t ReadLowRegs(uint32_t addr); +void WriteLowRegs(uint32_t addr, uint8_t data); void scanline_draw(int LineNo); -void do_scanline_and_draw(uint8* buf); +void do_scanline_and_draw(uint8_t *buf); // Rick -void start_frame(uint8 *buf, int ypitch); -void end_frame(uint8 *buf); +void start_frame(uint8_t *buf, int ypitch); +void end_frame(uint8_t *buf); void do_scanline_and_dont_draw(int LineNo); -uint32 NMI_enabled(void); +uint32_t NMI_enabled(void); void start_vblank(void); void end_vblank(void); -void render_bg(uint8* buf); -void render_spr(uint8* buf); -void update_tile(int byteOffset, uint8 data); +void render_bg(uint8_t *buf); +void render_spr(uint8_t *buf); +void update_tile(int byteOffset, uint8_t data); + #endif - - - - - - - - -