1

我正在使用这个头文件为 Game Boy Advance 创建两个与屏幕相关的函数。第一个函数ClearScreenWithColor获取红色、蓝色和绿色的值,并用该颜色擦除位图屏幕。第二个应该设置或清除更改颜色显示方式的未记录显示寄存器。由于这些是内存映射端口,因此必须将数据写入特定的内存地址。变量ScreenREG_GREENSWAP代表适当的内存地址。这是下面的代码。

//SCREEN SETTINGS FUNCTIONS
#ifndef SCREENFUNC_H
#define SCREENFUNC_H

#define RGB16(r,g,b) ((r)+(g<<5)+(b<<10))
void ClearScreenWithColor(int red, int green, int blue)
// must be in screen mode 3 or this won't work.
{
    unsigned short* Screen = (unsigned short*)0x6000000;
    // define the pointer variable Screen to contain
    // the memory address 0x06000000.
    int color = RGB16(red,green,blue);
    char x,y;
    
    for (x = 0; x < 240; x++)
    {
        for (y = 0; y < 160; y++)
        {
            Screen[x+y*240] = color;
        }
    }
}

void GreenSwap(short toggle)
{
    unsigned short* REG_GREENSWAP = (unsigned short*)0x04000002;
    
    REG_GREENSWAP = toggle;
}

#endif

当我编译文件时,我收到以下警告:

C:\gbaprog\gbaprint_test>gcc -S -o gbaprint_test.asm gbaprint_test.c
In file included from C:/gbaprog/lib/lib_header.h:9,
                 from gbaprint_test.c:19:
C:/gbaprog/lib/screenfunc.h: In function `GreenSwap':
C:/gbaprog/lib/screenfunc.h:28: warning: assignment makes pointer from integer without a cast

话虽如此,该函数ClearScreenWithColor不会产生此错误消息,即使它使用相同的语法来分配变量Screen。为什么函数GreenSwap不同,我的变量声明有什么不同?

4

1 回答 1

4

问题出在这一行:

REG_GREENSWAP = toggle;

toggle具有类型shortREG_GREENSWAP具有类型short *,因此(如错误消息所述)您将整数值分配给没有强制转换的指针。这也覆盖了REG_GREENSWAP初始化的值。

大概,您真正想要做的是取消引用REG_GREENSWAP并写入它指向的内存位置。

*REG_GREENSWAP = toggle;

没有错误,Screen[x+y*240] = color;因为数组索引隐式取消引用指针。

附带说明一下,在头文件中实现函数并不是一个好主意。如果该头文件包含在多个源文件中,则该函数将在每个目标文件中定义,当您尝试链接它们时,您将收到多重定义错误。

标头应仅包含函数的声明,而实现应恰好位于一个源文件中。

于 2021-08-08T00:14:26.890 回答