前言:
现时各位老铁们对“c语言迷宫堆栈”大致比较关心,大家都需要剖析一些“c语言迷宫堆栈”的相关内容。那么小编在网络上汇集了一些关于“c语言迷宫堆栈””的相关知识,希望你们能喜欢,同学们一起来了解一下吧!本教程将使用C语言以及raylib库来实现chip-8模拟器的开发。
什么是chip-8
Chip-8是一种解释型编程语言,由 Joseph Weisbecker 开发。它最初在20世纪70年代中期应用于 COSMAC VIP 和 Telmac 18008位微型计算机。Chip-8程序在 chip-8虚拟机上运行。它的出现是为了让电子游戏更容易为这些计算机编程, CHIP 8由于其简单性至今仍在使用,因此也可用于任何平台和二进制数的编程教学。
大约在15年后,chip-8被引入,衍生解释器出现在一些型号的图形计算器上(从20世纪80年代后期开始,这些手持设备在许多方面比大多数70年代中期的爱好者的微型计算机拥有更强的计算能力)。
chip-8应用程序
有许多经典的电子游戏移植到CHIP-8上,如《Pong》、《太空入侵者》、《俄罗斯方块》和《吃豆人》。还有一些应用,如随机迷宫生成器和康威的生命游戏。
chip-8架构
内存
Chip-8最常用于4k 系统,如 Cosmac VIP 和 Telmac 1800。这些机器有4096(0x1000)kb内存大小,chip-8解释器本身占用了这些机器上前512个字节的内存空间。由于这个原因,大多数chip-8程序从内存位置512(0x200)开始,不访问位置512(0x200)以下的任何内存。最上面的256个字节(0xF00-0xFFF)保留用于显示刷新,下面的96个字节(0xEA0-0xEFF)保留用于调用堆栈、内部使用和其他变量。
寄存器
CHIP-8有16个8位数据寄存器,命名为V0到VF。VF寄存器作为一些指令的标志。在加法操作中,VF是进位标志,而在减法操作中,它是“没有借位”标志。在绘制指令中,像素碰撞时也会设置VF。
地址寄存器名为I,宽度为12位,与几个涉及内存操作的操作码一起使用。
堆栈
堆栈仅用于在调用函数时存储返回地址。
计时器
CHIP-8有两个定时器。它们都以60赫兹的频率倒数,直到达到0。
延迟计时器:该计时器用于为游戏事件计时。它的值可以设置和读取。
声音计时器:这个计时器用于音效。当它的值非零时,发出哔哔声。
输入
输入是用十六进制键盘完成的,它有从0到f的16个键。'8','4','6'和'2'键通常用于方向输入。三个操作码用于检测输入。其中一个会在按下特定键时跳过指令,而另一个则在未按下特定键时跳过指令。第三个等待键按下,然后将其存储在数据寄存器之一。
图形和声音
chip-8显示分辨率为64×32,颜色为单色。图形仅通过绘制精灵绘制到屏幕上,精灵宽度为8像素,高度为1到15像素。精灵像素与相应的屏幕像素是异或的。换句话说,被设置的精灵像素会翻转相应屏幕像素的颜色,而未设置的精灵像素则什么都不做。当绘制精灵时,如果任何屏幕像素从set翻转到unset,则进位标志(VF)将被设置为1,否则将被设置为0。这是用于碰撞检测。
如前所述,当声音计时器的值非零时,将播放蜂鸣声。
操作码表
CHIP-8有35个操作码,都是两个字节长,存储大端数。操作码如下所示,以十六进制表示,并带有以下符号:
NNN:地址NN:8bit常数N:4bit常数X和Y: 4位寄存器标识符PC:程序计数器I: 16位寄存器(用于内存地址)(类似于void指针);VN: (寄存器)16个可用变量之一。N可以是0到F(十六进制);
操作码
类型
C 风格代码
解释
0NNN
Call
调用地址NNN处的机器码。
00E0
Display
disp_clear()
清空屏幕
00EE
Flow
return;
从一个函数返回
1NNN
Flow
goto NNN;
跳转到地址NNN
2NNN
Flow
*(0xNNN)()
调用地址NNN处的函数。
3XNN
Cond
if (Vx == NN)
如果VX等于NN,则跳过下一条指令。(通常下一条指令是跳过代码块的跳转);
4XNN
Cond
if (Vx != NN)
如果VX不等于NN,则跳过下一条指令。(通常下一条指令是跳过代码块的跳转);
5XY0
Cond
if (Vx == Vy)
如果VX等于VY,则跳过下一条指令。(通常下一条指令是跳过代码块的跳转);
6XNN
Const
Vx = N
将VX设置为NN。
7XNN
Const
Vx += N
将NN添加到VX。(进位标志VF不改变);
8XY0
Assig
Vx = Vy
将VX设置为VY的值。
8XY1
BitOp
Vx |= Vy
将VX设置为VX或VY。(按位或操作);
8XY2
BitOp
Vx &= Vy
将VX设置为VX和VY。(按位和操作);
8XY3
BitOp
Vx ^= Vy
将VX设置为VX 异或 VY。
8XY4
Math
Vx += Vy
将VY添加到VX。当有进位时,VF被设为1,当没有进位时,VF被设为0。
8XY5
Math
Vx -= Vy
VX减去VY。当有借位时,VF设为0,当没有借位时,VF设为1。
8XY6
BitOp
Vx >>= 1
将VX的最低有效位存储在VF中,然后将VX向右移1。
8XY7
Math
Vx = Vy - Vx
将VX设置为VY - VX。当有借位时,VF设为0,当没有借位时,VF设为1。
8XYE
BitOp
Vx <<= 1
将VX的最高有效位存储在VF中,然后将VX向左移1。
9XY0
Cond
if (Vx != Vy)
如果VX不等于VY,则跳过下一条指令。(通常下一条指令是跳过代码块的跳转);
ANNN
MEM
I = NNN
设置I为地址NNN。
BNNN
Flow
PC = V0 + NNN
跳转到地址NNN + V0。
CXNN
Rand
Vx = rand() & NN
将VX设置为对随机数(通常为0到255)和NN进行按位操作的结果。
DXYN
Disp
draw(Vx, Vy, N)
在坐标(VX, VY)上绘制一个宽度为8像素、高度为N像素的精灵。从内存位置I开始,读取每一行8个像素作为位编码;I值在执行这条指令后不会改变。如上所述,如果任何屏幕像素在绘制精灵时从set翻转到unset, VF将被设置为1,如果没有发生这种情况,VF将被设置为0
EX9E
KeyOp
if (key() == Vx)
如果按下存储在VX中的键,则跳过下一条指令。(通常下一条指令是跳过代码块的跳转);
EXA1
KeyOp
if (key() != Vx)
如果没有按下存储在VX中的键,则跳过下一条指令。(通常下一条指令是跳过代码块的跳转);
FX07
Timer
Vx = get_delay()
将VX设置为延迟定时器的值。
FX0A
KeyOp
Vx = get_key()
等待按键,然后存储在VX中。(阻塞操作。所有指令暂停,直到下一个按键事件按下按键);
FX15
Timer
delay_timer(Vx)
将延迟定时器设置为VX。
FX18
Sound
sound_timer(Vx)
将声音计时器设置为VX。
FX1E
MEM
I += Vx
将VX添加到i, VF不受影响。
FX29
MEM
I = sprite_addr[Vx]
将I设置为VX中字符的精灵位置。字符0-F(十六进制)用4x5字体表示。
FX33
BCD
set_BCD(Vx)*(I+0) = BCD(3);*(I+1) = BCD(2);*(I+2) = BCD(1);
存储VX的二进制编码的十进制表示,地址为I的三位中最高有效的一位,中间的一位为I + 1,最低有效的一位为I + 2。(换句话说,取VX的十进制表示,将百位放在内存中I的位置,十位放在内存中I+1的位置,个位放在内存中I+2的位置。)
FX55
MEM
reg_dump(Vx, &I)
存储从V0到VX(包括VX)在内存中,从地址I开始。从I开始的偏移量为每写入一个值增加1,但I本身没有修改。
FX65
MEM
reg_load(Vx, &I)
从V0到VX(包括VX)填充内存中的值,从地址I开始。每写入一个值,从I开始的偏移量就增加1,但I本身没有被修改。