CHIP8簡介
對CHIP8一個簡單的介紹,參考資料來自於CHIP8的Wiki。
CHIP8是什麼?
我開始一直以爲CHIP8是什麼單片機的一種,後來才發現CHIP8是一種解釋性的編程語言。對,是語言!最初被應用是在1970年代中期。CHIP8的程序運行在CHIP8虛擬機中,它的出現讓電子遊戲編程變得簡單些了(相對於那個年代來說)。
用CHIP8實現的電子遊戲不少,比如小蜜蜂,俄羅斯方塊,吃豆人等。CHIP8還有個後代叫做SCHIP8(Super Chip8),它的出現讓遊戲編程相對於CHIP8來說更加簡單了,因爲它多了很多的操作碼。它們兩個在很多平臺上都實現了相應的模擬器,也有純硬件實現,比如用FPGA。
CHIP8虛擬機介紹
上文提到了運行CHIP8的程序是在CHIP8的虛擬機中,那麼作爲一個能運行CHIP8的虛擬機,具備了哪些要素呢?
內存
CHIP8基本是在一個有4K內存的系統上實現,也就是4096個字節。前512字節由CHIP8的解釋器佔據。所以CHIP8的程序都是從0x200地址開始的。最頂上的256個字(0xF00-0xFFF) 用於顯示刷新,在這下面的96個字節 (0xEA0-0xEFF) 用於棧, 內部使用或者其他變量。
發展到今天,CHIP8的實現的話不需要使用的空間都可以不使用,也就是不用完全那麼按照上面來。但是通常還是要在低512字節 (0x000-0x200)存放字體數據。
寄存器
CHIP8的話有16個數據寄存器,V0~VF。VF寄存器存放進位標識。還有一個地址寄存器叫做I,2個字節的長度。
棧
棧用於存放函數返回的地址值和保存一些數據,現在CHIP8的棧實現一般有16級。
定時器
CHIP8有兩個定時器,一個延時計時器,一個聲音計時器。延時計時器一般處理用戶遊戲事件,可讀可寫。聲音計時器顧名思義,用於發出聲音的,當其值非零,就會發出一個聲音。
輸入
輸入是一個十六進制的鍵盤,其中有16個鍵值,0~F。“8”“6”“4”“2”一般用於方向輸入。有三個操作碼用來處理輸入,其中一個是當鍵值按下則執行下一個指令,對應的是另外一個操作碼處理指定鍵值沒有按下則調到下一個指令。第三個操作碼是等待一個按鍵按下,然後將其存放一個寄存器裏。
圖像和聲音
顯示分辨率是64X32的像素,並且是單色的。某像素點爲1則屏幕上顯示相應像素點,爲0則不顯示。但某個像素點由有到無則進位標識被設置爲1,可以用來進行衝撞檢測。
操作碼
這是CHIP8的重點,CHIP8一共有35個操作碼。每個操作碼都是兩個字節長。最高字節首先被存放。下面是操作碼錶和其代表的意義:
- NNN: address
- NN: 8-bit constant
- N: 4-bit constant
- X and Y: 4-bit register identifier
Opcode | Explanation |
0NNN | Calls RCA 1802 program at address NNN. |
00E0 | Clears the screen. |
00EE | Returns from a subroutine. |
1NNN | Jumps to address NNN. |
2NNN | Calls subroutine at NNN. |
3XNN | Skips the next instruction if VX equals NN. |
4XNN | Skips the next instruction if VX doesn’t equal NN. |
5XY0 | Skips the next instruction if VX equals VY. |
6XNN | Sets VX to NN. |
7XNN | Adds NN to VX. |
8XY0 | Sets VX to the value of VY. |
8XY1 | Sets VX to VX or VY. |
8XY2 | Sets VX to VX and VY. |
8XY3 | Sets VX to VX xor VY. |
8XY4 | Adds VY to VX. VF is set to 1 when there’s a carry, and to 0 when there isn’t. |
8XY5 | VY is subtracted from VX. VF is set to 0 when there’s a borrow, and 1 when there isn’t. |
8XY6 | Shifts VX right by one. VF is set to the value of the least significant bit of VX before the shift.[2] |
8XY7 | Sets VX to VY minus VX. VF is set to 0 when there’s a borrow, and 1 when there isn’t. |
8XYE | Shifts VX left by one. VF is set to the value of the most significant bit of VX before the shift.[2] |
9XY0 | Skips the next instruction if VX doesn’t equal VY. |
ANNN | Sets I to the address NNN. |
BNNN | Jumps to the address NNN plus V0. |
CXNN | Sets VX to a random number, masked by NN. |
DXYN | Sprites stored in memory at location in index register (I), maximum 8bits wide. Wraps around the screen. If when drawn, clears a pixel, register VF is set to 1 otherwise it is zero. All drawing is XOR drawing (i.e. it toggles the screen pixels) |
EX9E | Skips the next instruction if the key stored in VX is pressed. |
EXA1 | Skips the next instruction if the key stored in VX isn’t pressed. |
FX07 | Sets VX to the value of the delay timer. |
FX0A | A key press is awaited, and then stored in VX. |
FX15 | Sets the delay timer to VX. |
FX18 | Sets the sound timer to VX. |
FX1E | Adds VX to I.[3] |
FX29 | Sets I to the location of the sprite for the character in VX. Characters 0-F (in hexadecimal) are represented by a 4x5 font. |
FX33 | Stores the Binary-coded decimal representation of VX, with the most significant of three digits at the address in I, the middle digit at I plus 1, and the least significant digit at I plus 2. (In other words, take the decimal representation of VX, place the hundreds digit in memory at location in I, the tens digit at location I+1, and the ones digit at location I+2.) |
FX55 | Stores V0 to VX in memory starting at address I.[4] |
FX65 | Fills V0 to VX with values from memory starting at address I.[4] |
以上就是對CHIP8的一個簡單介紹,要想實現CHIP8的模擬,重點就在於對其操作碼的模擬實現。