私は、Ca65アセンブラとld65リンカを使用して、Commodore 64用の6502アセンブラで短いプログラムを作成しました。プログラムは、ディスプレイの中央近くのどこかで塗りつぶされた正方形のスプライトをレンダリングする必要がありますが、何もレンダリングされていません。
これは私のアセンブリです:
.segment "CODE"
; set sprite pointer index
; this, multiplied by $40, is the address
; in this case, the address is $2000
; $80 * $40 = $2000
lda #$80
sta $07f8
; enable sprite 0
lda #$01
sta $d015
; set x and y position
lda #$80
sta $d001
sta $d002
loop:
jmp loop
.segment "GFXDATA"
.byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
.byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
.byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
.byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
.byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
.byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
.byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
.byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
これは私のリンカースクリプトで、c64での手書きのアセンブラ用にca65が推奨するリンカースクリプトから改作されたものです。私が行った唯一の変更は、「GFXDATA」セグメントを追加することでした。これにより、私のスプライトをaddressに保存できるようになりました$2000
。
FEATURES {
STARTADDRESS: default = $0801;
}
SYMBOLS {
__LOADADDR__: type = import;
}
MEMORY {
ZP: file = "", start = $0002, size = $00FE, define = yes;
LOADADDR: file = %O, start = %S - 2, size = $0002;
MAIN: file = %O, start = %S, size = $D000 - %S;
}
SEGMENTS {
ZEROPAGE: load = ZP, type = zp, optional = yes;
LOADADDR: load = LOADADDR, type = ro;
EXEHDR: load = MAIN, type = ro, optional = yes;
CODE: load = MAIN, type = rw;
RODATA: load = MAIN, type = ro, optional = yes;
DATA: load = MAIN, type = rw, optional = yes;
GFXDATA: load = MAIN, type = ro, optional = yes, start = $2000;
BSS: load = MAIN, type = bss, optional = yes, define = yes;
}
これは、コンパイルとリンクに使用しているコマンドです。
cl65 -o graphics.prg --mapfile graphics.map -u __EXEHDR__ -t c64 -C linker.cfg graphics.asm
これはコンパイル後のマップファイルの内容です:
Modules list:
-------------
graphics.o:
CODE Offs=000000 Size=000015 Align=00001 Fill=0000
GFXDATA Offs=000000 Size=000040 Align=00001 Fill=0000
/usr/share/cc65/lib/c64.lib(exehdr.o):
EXEHDR Offs=000000 Size=00000C Align=00001 Fill=0000
/usr/share/cc65/lib/c64.lib(loadaddr.o):
LOADADDR Offs=000000 Size=000002 Align=00001 Fill=0000
Segment list:
-------------
Name Start End Size Align
----------------------------------------------------
LOADADDR 0007FF 000800 000002 00001
EXEHDR 000801 00080C 00000C 00001
CODE 00080D 000821 000015 00001
GFXDATA 002000 00203F 000040 00001
Exports list by name:
---------------------
__EXEHDR__ 000001 REA __LOADADDR__ 000001 REA
Exports list by value:
----------------------
__EXEHDR__ 000001 REA __LOADADDR__ 000001 REA
Imports list:
-------------
__EXEHDR__ (exehdr.o):
[linker generated]
__LOADADDR__ (loadaddr.o):
[linker generated] linker.cfg(5)
そして、最終的なバイナリファイルの16進ダンプ:
0000000 0801 080b 0320 329e 3630 0031 0000 80a9
0000010 f88d a907 8d01 d015 80a9 018d 8dd0 d002
0000020 1f4c 0008 0000 0000 0000 0000 0000 0000
0000030 0000 0000 0000 0000 0000 0000 0000 0000
*
0001800 ff00 ffff ffff ffff ffff ffff ffff ffff
0001810 ffff ffff ffff ffff ffff ffff ffff ffff
*
0001840 00ff
0001841
「GFXDATA」セグメントは私のスプライトです。スプライトは64バイトの$FF
なので、塗りつぶされた正方形のように見えるはずです。このスプライトデータは、アドレスにあります$2000
。
"CODE"セグメントは通常のBASIC開始位置から始まり、ca65がBASICローダーを挿入してくれるのでrun
、プログラムをロードした直後に入力できます。
私はVICのバンクを切り替えていないため、画面はデフォルトのアドレス範囲($0400-$07FF
)のままです。この範囲の最後の8バイトは私のスプライトポインターです。スプライト$07f8
が1つしかないため、スプライトポインター0()のみを使用しています。
プログラムを実行すると、すべてがハングアップします。これは、プログラムが無限ループで終了するためです。しかし、スプライトは画面のどこにも表示されません。
何が欠けていますか?
.org
ディレクティブを使用したり、PCを直接設定して、保存場所を制御したりしました。ca65
ただし、バイナリのどこに配置するかを制御する適切な方法はリンカースクリプトを使用することであると主張して、これは推奨されません。そして、私は(私はそう思いますか?)リンカーセットアップを正しく取得したので、それらのポイントを確認します-すべてを整理する方がはるかに簡単です。