CHIP-8に基づく゚ミュレヌションの原則

耇雑なシステムの゚ミュレヌトを開始する前に、たずえばChip-8などの単玔なものから始める必芁があるず考えられおいたす。 この蚘事では、仮想マシンでこの蚀語の実装を䜜成する方法のすべおの偎面を怜蚎したす。 どのプログラミング蚀語でも実行できたすが、その単玔さから、Delphiを遞択したす。



埅っお、すぐに゚ディタヌに突入しないでください。最初にペンずノヌトが必芁です。ここで、私たち自身のためにすべおの重芁な情報を曞き留めたす。 それはすべお圌女の怜玢から始たりたす。 たず、これはもちろんGoogleです。 30分間リンクをたどるず、どのシステムに察しお既にいく぀の実装が䜜成されおいるかを確認できたす。遞択はしたくありたせんが、他の゜ヌスコヌドを芋るのではなく、独自に䜜成したす。





歎史的背景





CHIP-8は、RCAのTELMAC 1800やCOSMAC VIPなどの䞀郚の小型商甚コンピュヌタヌや、ETI 660やDREAM 6800のような安䟡な「自分で䜜成」コンピュヌタヌで70幎代埌半から80幎代前半に䜿甚された蚀語むンタヌプリタヌです。 ...



CHIP-8により、ゲヌムのプログラミングが簡単になりたした。 TELMAC 1800およびCOSMAC VIPは、RCA CDP-1802プロセッサに基づいおいたした。 どちらも1977幎の12ゲヌム以䞊のオヌディオカセットが付属しおいたす。 むンタヌプリタヌには、数孊、デヌタフロヌの制埡、グラフィックス、サりンドなど、40未満のコマンドがありたした。



これらのコンピュヌタヌのメモリ制限のため、むンタヌプリタヌは非垞に小さくする必芁がありたした。COSMACVIPは2Kbただし、32Kbに拡匵可胜で、TELMACは4Kbでした。 CHIP-8の長さは512バむトのみでした。

蚀語のシンプルさにより、ビデオゲヌムの最初の段階でプレむしたPong、Brix、Invaders、Tankを䜜成できたした。 優れたプログラマヌは、これらのゲヌムを256バむト未満で入れるこずができたす。



DREAM-6800ナヌザヌの1人のCHIP-8に぀いおの短いストヌリヌを次に瀺したす。

「 ... DREAMずETI 660は、オヌストラリアの電子雑誌にビルドプロゞェクトずしお登堎したした。これらのコンピュヌタヌを組み合わせ、信じられないほど䜎䟡栌玄100ドル、16進キヌボヌドの䜿甚、非垞に限られたグラフィックス64 x 32ピクセルETI 660 64 x 48たたは64 x 64倉曎時をテレビに転送し、玄1キロバむトのRAM、およびCHIP-8ず呌ばれる高レベルの擬䌌蚀語を実行する機胜COSMACグラフィックをデモンストレヌションするためにRCAが開発したようです。

...

ある日、兄がDREAM 6800を組み立おたした。なんおコンピュヌタヌなのでしょう DREAMETI 660ビルドの蚘事ず䞀緒に、CHIP-8のゲヌムリストが山ほどありたした。 䞀郚のゲヌムは200バむト以䞋であったため、それらを入力するこずは氞遠にかかりたせん。 そしお、これらは玠晎らしいゲヌムでした。 圌らは遅くなかった。 したがっお、CHIP-8は叀兞的なテレビゲヌム甚に非垞にうたく蚭蚈されおいたした。 」

Paul HyterAmigaのCHIP-8むンタヌプリタヌが投皿



その埌、90幎代前半にHP48蚈算機でCHIP-8が䜿甚されたした。これは、CHIP-8でゲヌムをより速く曞く方法がなかったためです。 CHIP-8のほずんどすべおのオリゞナルゲヌムもCHIP48むンタヌプリタヌで動䜜したしたが、倚くの新しいゲヌムが䜜成されたした。

その埌、新しいバヌゞョンの蚀語-SUPER-CHIPがリリヌスされたした。 圌は暙準のすべおの機胜を備えおいたしたが、128x64の解像床で既に動䜜するこずができたした。



建築





CHIP-8のすべおのプログラムは200時間で始たりたすが、ETI-660は600時間で始たりたす。 これは、蚀語むンタヌプリタヌ自䜓が000h-1FFhにあるためです。



すべおのメモリは完党にアドレス可胜でアクセス可胜です。 呜什は16ビットを占有するため、通垞は偶数アドレスを持ち、8ビットがコヌド内に挿入されるず、アドレスは奇数になりたす。



メモリアドレスに䜿甚される12ビットに基づいお、トリックなしの最倧メモリ量は4096バむト000h-FFFhであるず蚈算できたす。 ただし、アドレスF00h-FFFhはビデオメモリによっお占有され、EA0h-EFFhはCHIP-8のスタックおよび内郚倉数を栌玍するために䜿甚されたす。



むンタヌプリタヌは、8ビットのボリュヌムを持぀16個の汎甚レゞスタヌを䜿甚したす。 V0..VFずしお利甚可胜です。 さらに、VFは、転送の堎合は算術挔算のフラグずしお、スプラむトを描画するずきは衝突怜出噚ずしお䜿甚されたす。



サむズが16ビットのアドレスレゞスタIも1぀ありたす。 メモリは4キロバむトしかないため、むンタヌプリタヌは䞋䜍12ビットのみを䜿甚したした。 ただし、フォントが8110にあるため、䞊䜍4ビットはフォントのダりンロヌド機胜に䜿甚できたす。



レゞスタに加えお、2぀のタむマヌがありたした。 1぀は遅延タむマヌ、もう1぀はオヌディオタむマヌです。 䞡方ずも8ビットの長さであり、その時点でれロでない堎合、1秒あたり60回コンテンツを削枛したした。 ぀たり、呚波数は60ヘルツでした。 サりンドタむマヌの倀がれロ以倖の堎合、サりンドが再生されたした。

スタックの次元は䞍明のたたでしたが、16レベル2x16バむトで行うのが䞀般的です。



グラフィックは、バむト単䜍で゚ンコヌドされた1..15ピクセルの8぀のスプラむトでレンダリングされたす。 原点は巊䞊隅にあり、ポむント0から始たりたす。すべおの座暙は正であり、それぞれ64たたは32による陀算の残りず芋なされたす。 画面ぞの出力はXORモヌドです。 1぀以䞊のピクセルがクリアされるず色を1から0に倉曎する、VFレゞスタは01hず00hに蚭定されたす。 Chip-8には、文字0-9およびAFを含む4x5ピクセルのフォントがありたす。



明確にするために、スプラむトずそのコヌディングの䟋を考えおみたしょう。 8x5のスプラむトを取りたす。







次のバむトセットを取埗したす0 A0 0 A0 0





完党にクリアするには、別の1スプラむト8x8を䜿甚したす。







スプラむトは8バむトを占有し、次の構造を持ちたす0 60 30 18 0 06 03





CHIP-8のキヌボヌドは16番目で、次の倖芳がありたす。







そのようなキヌボヌドの利䟿性ず䟿宜性は、議論ず議論しかできたせん。 しかし、すべおがそのようなキヌボヌドのために特別に開発されたので、我々はオリゞナルから出発したせん。



コマンドシステム





アドレスをNNN、KK-8ビット定数、XおよびY-4ビット定数ずしお指定するこずをすぐに蚀う必芁がありたす。

次に、コマンドのリストを怜蚎したす。



0NNN Syscall nnnコヌドNNNでプロセッサ1802の機械呜什呜什を呌び出したす。

00CN * scdown n画面をN行䞋にスクロヌルしたす。

00FB *画面を右に4ピクセルスクロヌルするScright

00FC *画面を巊に4ピクセルスクロヌルするScleft

00FD *゚ミュレヌタヌを終了する

00FE *䜎グラフィックモヌドをCHIP-864x32に蚭定したす

00FF *高グラフィックモヌドをスヌパヌチップ128x64に蚭定したす

00E0 Clsクリアスクリヌン

00EE Rtsルヌチンからの戻り

1NNN jmp nnnプログラム実行をNNNに転送

2NNN jsr nnn NNNでの関数呌び出し。 前のアドレスがスタックにプッシュされたす。

3XKK skeq vx、kk VX = KKの堎合、次の呜什2バむトをスキップしたす

4XKK skne vx、kk VX <> KKの堎合、次の呜什2バむトをスキップしたす

5XY0 skeq vx、vy VX = VYの堎合、次の呜什をスキップしたす

6XKK mov vx、kk VXレゞスタにKKを曞き蟌みたす

7XKKはvx、kkを远加したすVXレゞスタにVX + KKを曞き蟌みたすりィキペディアおよびその他の゜ヌスからの情報によるず、フラグには圱響したせん

8XY0 mov vx、vy VXでレゞスタVYの倀を曞き蟌む

8XY1たたはvx、vy VX = VXたたはVY。

8XY2およびvx、vy VX = VX AND VY

8XY3 xor vx、vy VX = VX XOR VY元の文曞には文曞化されおいたせん

8XY4は、vx、vy VX = VX + VYを远加したす。 VF =キャリヌ。

8XY5サブvx、vy VX = VX-VY。 *VF =借甚しない。

8X06 shr vx VX = VX SHR 1VX = VX / 2、VF =キャリヌ

8XY7 sub vy、vx VX = VY-VX、VF =借甚しない*元の文曞には蚘茉されおいたせん

8XYE shl vx VX = VX SHL 1VX = VX * 2、VF =キャリヌ

9XY0 skne vx、vy VX <> VYの堎合、次のステヌトメントをスキップしたす

ANNN mov I、nnn I = NNN

BNNN Jmi NNN NNN + V0ぞのプログラム実行の転送

CXKKランドvx、kk VX =乱数0..255およびKK

DXYN vx、vy、nを描画したす。レゞスタIに含たれるアドレスのメモリで始たる座暙VX、VYで、高さNN = 0カりントN = 16で幅8のスプラむトを描画したす。VF=衝突。

EX9E Skpr vx VXキヌが抌された堎合、以䞋の指瀺をスキップしたす。

EXA1 Skup vx VXで数字キヌが抌されおいない堎合、以䞋の指瀺をスキップしたす。

FX07 Gdelay vx VX =遅延タむマヌ

FX0A Key vxボタンが抌されるのを埅っお、VXに远加したす。

FX15 Sdelay vx遅延タむマヌ= VX

FX18 Ssound vxサりンドタむマヌ= VX

FX1E Add I、vx I = I + VX

FX29 Font vx VXに含たれるフォントスプラむト4 x 5の16進文字のIアドレスに入力

FX33 Bcd vx BCD VX衚珟をメモリのI..I + 2アドレスに配眮したす。 たずえば、VXに4Fhが含たれる堎合、00h 07h 09hがメモリに曞き蟌たれたす。぀たり、4Fhの10進衚珟です。

FX55 Save vx Saves V0 ... VXレゞスタヌはアドレスIから始たるメモリヌに保存されたす。

FX65 Load vxアドレスIから始たるメモリからレゞスタV0 ... VXをロヌドしたす

FX75 * Ssave vxはV0 ... VXX <8をHP48フラグに保存したす

FX85 * Sload vx HP48フラグからV0 ... VXX <8をロヌド



*-コマンドがSUPER CHIPむンタヌプリタヌにのみ関連するこずを意味したす。



*VX-VYが発生するず、VFはロヌンの拒吊に蚭定されたす。 ぀たり、VXがVY以䞊の堎合、ロヌン= 0であるため、VFは01に蚭定されたす。VXがVYより小さい堎合、ロヌン= 1であるため、VFは00に蚭定されたす。



基本的なスプラむトの準備





玙ずペンを䜿甚しお、フォントスプラむトの茪郭を描きたす。 このセットのようなものが埗られたす







それを䜿甚しお、各スプラむトの倀のバむトを曞き蟌みたす。



゚ミュレヌションの原則





すべおの゚ミュレヌションは、ほがこのタむプのサむクルで行われるず考えられおいたす。



繰り返す

//゚ミュレヌションを行いたす

quit_pr たで




ここで、quit_prぱミュレヌションを停止する兆候ず芋なされ、倖郚からだけでなく、゚ミュレヌションの内郚からも倉曎できたす。



遵守すべき最も重芁なポむントの1぀は、機噚の動䜜呚波数ず最適化の遵守です。 CHIP-8のような単玔な蚀語の゚ミュレヌションを蚘述するのが間違っおいる堎合、非垞に䜎いパフォヌマンスず非垞に高いプロセッサ時間を埗るこずができたすが、正しい゚ミュレヌションは最䜎コストで十分なパフォヌマンスを提䟛したす。



Delphiを䜿甚しお、システム゚ミュレヌションをクラスずしお開発するこずにし、このシステム内で䜿甚されるプロセッサのモデルに基づいお、「TCpu1802」ずいう名前を付けたした。 メむンの実行手順を怜蚎しおください。



プロシヌゞャ tcpu1802 走る

始める

delaytimer 。 有効  = true ;

サりンドタむマヌ。 有効  = true ;

drawtimer 。 有効  = true ;

work  = true ;

繰り返す

useopcode ;

cpumulty <> 0の 堎合

if  round  cycle  mod  2   = 0 then sleep  cpumulty  ;

アプリケヌション。 ProcessMessages ;

work = false たで 。

delaytimer 。 有効  = false ;

サりンドタむマヌ。 有効  = false ;

drawtimer 。 有効  = false ;

終わり ;







たず、起動時に、CHIP-8タむマヌの2぀の暙準ず、画面を再描画するために個別に入力された1぀の暙準をアクティブにしたす。 サむクル-コマンドの珟圚のサむクルを含む倉数。各コマンドの呌び出しにより、サむクルが1぀増加したす。 2番目のアクションごずに、cpumultyミリ秒間むンタヌプリタヌを䞀時停止しようずしたす。 これは、高速化が発生しないようにするために必芁です。



SoundtimerタむマヌずDrawtimerタむマヌの間隔は17ミリ秒です。぀たり、58.82ヘルツの呚波数で動䜜したす。これは、オリゞナルに可胜な限り近いものです。



ドロヌタむマヌの遅延は10ミリ秒に蚭定されおいたす。 ぀たり、平均しお、レンダリングは3〜4個のむンタヌプリタヌコマンドごずに実行されたす。 むンタヌプリタヌの実行プロセスを詰たらせないためにタむマヌぞの割り圓おが行われ、プロセスの䞊列化を実行するための通垞の手段を䜿甚するこずができたす。



゚ミュレヌション自䜓を完了するために必芁な倉数のリストを芋おみたしょう。



キヌコヌド バむト ; //抌されたキヌのコヌド

メモリ バむトの 配列 [ 0 .. 8191 ] 。 //フォントの堎所のために割り圓おられた8キロバむトのRAM

スタック 単語の 配列 [ 0..255 ] 。 //スタック

stacksize  byte ; //珟圚のスタックスむヌプ

videoarray  ブヌル倀の 配列 [ 0..2047 ] 。 //ビデオ配列

マスク ブヌル倀の 配列 [ 0..2047 ] 。 //ビデオ配列のマスク

Vreg  バむトの 配列 [ 0 .. 15 ] 。 //-V0..VFを登録したす

Ireg  蚀葉 。 // 2バむトのアドレスレゞスタ

CodeSender  ワヌド 。 //メモリ内の次のオペコヌドの堎所

音 ブヌル倀 ; //サりンドは珟圚再生䞭ですか




アヌキテクチャによれば、ビデオメモリは他のすべおず同じ量のRAMに配眮されたすが、そこぞの䞀定の読み取りず曞き蟌み、バむトの怜査ず分析は倚くのプロセッサリ゜ヌスを消費し、プログラムが䜕かを読み取るこずができるず仮定するず非珟実的ですそこから盎接、そのメモリ領域からの読み取りが発生した堎合、mirrorvideomemずいう远加のプロシヌゞャを呌び出すだけで、そこにビデオメモリの珟圚の内容を曞き蟌むこずができたす。 このような゜リュヌションは効果的ですが、RAMの䜿甚量がわずかに増えたす。 ミラヌスタックの手順は䌌おいたす。



プロシヌゞャ tcpu1802 mirrorvideomem ;

var

i 、 j  æ•Žæ•° 。

tmp  バむト ;

始める

if  Ireg> = $ F00  and  Ireg < = $ FFF  then

始める

for i  = 0 から 255 たで

始める

tmp  = 0 ;

for j  = 0 から 7 do

始める

videoarray [ i * j ] if tmp  = tmp + 1 ;

tmp  = tmp shl 1 ;

終わり ;

メモリ[ $ F00 + i ]  = tmp ;

終わり ;

終わり ;

終わり ;





プロシヌゞャ tcpu1802 mirrorstack ;

var

n 、 i  æ•Žæ•° ;

始める

if  Ireg> = $ EA0  and  Ireg < = $ EFF  then

始める

stacksize> 12 then n  = 11 else n  = stacksize - 1 ;

for i  = 0 から n

始める

メモリ[ $ EFF - i * 2 ]  = stack [ i ] div 256 ;

メモリ[ $ EFF - i * 2 + 1 ]  = stack [ i ] mod 256 ;

終わり ;

終わり ;

終わり ;





プロセッサを䜜成する前に、各コマンドが条件付きで4ビットの4぀のセクションに分割されおいるこずがわかりたす。 それらを䜿甚するために、opcodeデヌタ型が導入されたしたtype opcode = array [0..3] of byte;。



メモリから次のデヌタを倉換しお読み取るこずはしたせんが、゚ミュレヌションを実行する実行手順の構造に泚意を払いたす。 最適化のために、「if then else」ではなく「case」を䜿甚し、さらに倚くのコマンドを䜿甚しおアセンブラで䜿甚できるため、゚ミュレヌションがさらに高速化されたす。 そのようなコマンドの䟋を次に瀺したす。



op [ 3 ] = 1の 堎合

始める

tmp  = Vreg [ op [ 1 ] ] ;

tmp2  = Vreg [ op [ 2 ] ] ;

asm

mov ah 、 [ tmp ]

たたはああ、 [ tmp2 ] ;

mov [ tmp ] 、 ah ;

終わり ;

Vreg [ op [ 1 ] ]  = tmp ;

䜿甚 = true ;

コヌド送信者 =コヌド送信者+ 2 ;

終わり ;




これで、゚ミュレヌションのすべおの瞬間を考慮しお、独自のCHIP-8゚ミュレヌションを䜜成できたす。 私の蚘事を楜しんでいただき、それが圹に立おば幞いです。 読んでくれおありがずう。



䞭叀品

CHIP-8 / SCHIP゚ミュレヌタヌ

デむノィッド・りィンタヌHPMANIAC

りィキペディア



モゞュヌル゜ヌス

゜ヌスコヌド



ナヌザヌnsinrealから招埅状を受け取ったのは圌女のためでした。



送信できないため、この蚘事の公開の1時間前に衚瀺された蚘事を「コピヌアンドペヌスト」ず芋なさないようにずいう芁求。 モゞュヌルの内容や゚ミュレヌションぞのアプロヌチが異なるため、お互いの蚘事が衚瀺されなかったこずを事前に感謝しおください。



All Articles