68kいじってみた感想文
'21.3.20 作成
・1.7GHzのパソコンでも一応動くけどスクロールちらつく。
激しい運動のゲーム作っても遅いCPUでは動かすのは無理。(今さら何を作る気だw)
・88VA触りたいw
・命令長さが16bit x 1〜3らしい。
メモリマップドI/Oらしく、in/out命令がない。(I/O用の配線がCPUにない。)
1バイト命令がない分、ある意味でZ80Aより遅くてバイナリが大きいのかも?
複雑ややこしい命令がない、スッキリしている。
・スーパーマリオ+FM音源を88VAで作ろうと思ったけど・・・88VA実機+HDMIコンバータ+....
と結構費用がかかりそうで止めたw
(BIOSは一応ネット探せばすぐ出て来るみたいけど違法だしぃ)
x68kは違法じゃないしBIOS、DOSは公開されてるけど、X-BASICのopmdrv3.xが無かったり
結構四苦八苦。X-BASICから音出ないよー。
・BIOSとエミュレータ(xm6)を落とす。human68kイメージの方を落とす。
biosROMファイルをx64とかのフォルダに入れる。xm6utilityでフォントROMファイル、SCSIパラメータファイル?を作る。
HDD空のイメージをエミュレータのメニューから作る。エミュレータのメニューからオプションを呼び出し
作ったからのHDDイメージを指定して設定。
システム転送付きでhuman68kのbin\format.xで
DOS>format
HDDをhuman68k上からフォーマットして、
DOS>switch
でSRAMのオプションを変える。HDDから起動するように変更。
human68kのファイルを全部HDDのルートにコピー(COPYALLコマンドがある)。これでHDDから起動できる。
(HDDないと毎回フロッピー抜き差しする必要が出て来るのであった方がいい気がする)
gcc2相当を落とす。メニューから空の2HDフロッピーディスクイメージを作り、
vector辺りからdiskExplorerでgcc2相当のファイルを、bin、素のままフォーマットで
開いてドラッグアンドドロップして、gcc2 FDイメージを作る。HDDにgcc2 FDイメージを全部コピーする。
ed コマンドでtest.s を作り、path をA:\GCC2> に設定(MS-DOSと同じでpath=でいけるのかな?)。
アセンブラの命令、文法は一応どっかから手に入る。
test.s の中身はこんな感じで・・・。
top:
nop
nop
nop
nop
jmp top
DOS>g2as test.s
DOS>g2lk test.o
DOS>test.x
おお!アセンブラ!!すげぇw
はんぐあっぷしますた。。。w
で。PRO68Kのデバッガ等ツール一式、SX-WINDOWの辞書ファイルもHDDに入れる。
c00000番地に自力アセンブラで書き込んだ挑戦アセンブラコードが
以下。
.text
movem.l a0-a5,(sp)
; printf Test
pea ?LC0
dc.w $ff09
; super visor test
move.l #$0,-(sp)
dc.w $ff20
bra VRAM_TEST
nop
nop
nop
dc.w $ff00
nop
.text
?LC0:
.dc.b 'abcde',$0a,$0d,$00
VRAM_TEST:
; 漢字のコメントを入れても大丈夫な能力があるか確かめてみるw
;;どうでもいいけど、最近のPCでも漢字系のボタンがいろいろあって
;使い方よく分からないよね。
; VC R1($e82500)でTVRAM,GVRAM,SPRITE
; の各優先順位を設定する。
move.l #$e82500, a0
; TVRAM > GVRAM > SPRITE, G0>G1>G2>G3
move.w #$31e4,(a0)
move.l #$e82600, a0
; GVRAM有効に。
move.w (a0),d0
and.w #$fff0,d0
or.w #$001f,d0
move.w d0, (a0)
move.l #$e80028, a0
; GVRAM有効に。
move.w (a0),d0
and.w #$f7ff,d0
move.w d0, (a0)
move.l #$40000,d1
move.l #$c00000,a1
move.l #$0,d2
LOOP_START:
move.w d2,(a1)+
add.w #1,d2
sub.l #1,d1
cmp.l #0,d1
BGT.B LOOP_START
LOOP_END:
dc.w $ff01
nop
nop
dc.w $ff00
これをg2as>g2lk。アセンブラの文法が分からなければ
Cコンパイラで-Sでおkwwwww(なんちゅう乱暴な…
やっとVRAMで絵がかけた〜〜〜〜。長かった…。
で?こんな模様かけてなんか意味あんのこれ?wオレさんぼけてなくね?w
pc98 MOS-DOSと違い、human68kはコマンドの履歴機能がかなり改善されている。
[PageUp][PageDown][Tab]で入力補完ばっちり。
ファイル名は頭だけ入れて[Tab]で補完。候補が違えばもっと[Tab]推せばそのうち
必要な候補になる。
以前入力したコマンドであれば、その頭だけ入れて[PageUp][PageDown]で続きを
補完してくれる。
history.xの方はヘルプはhuman68k上あるけど見方がよく分からん…。
マニュアルを紹介しているHPはないようです。
で。VSYNC割り込みを足したのがこんな感じ。
.text
move.l #__STACK_START,sp
movem.l a0-a5,-(sp)
; printf Test
pea ?LC0
dc.w $ff09
addq.l #4,sp
; super visor test
moveq.l #$0,d0
move.l #$0,-(sp)
dc.w $ff20
addq.l #4,sp
move.l d0, __SP_SUPER
move.l #$c00000,a0
VRAM_RESET:
move.w #0,(a0)+
move.l a0,d0
cmpi.l #$c80000,d0
bmi.b VRAM_RESET
bra VRAM_TEST
nop
nop
nop
dc.w $ff00
nop
.text
?LC0:
.dc.b 'abcde',$0a,$00
.even
VRAM_TEST:
; 漢字のコメントを入れても大丈夫な能力があるか確かめてみるw
;;どうでもいいけど、最近のPCでも漢字系のボタンがいろいろあって
;使い方よく分からないよね。
;
move.l #$00c40000, VRAM_POINTER
move.l #$100, VRAM_COLOR_CNT
move.l #10, VRAM_WRITETRYCNT
move.l #0, VRAM_WRITETRYCNT_60
; VC R1($e82500)でTVRAM,GVRAM,SPRITE
; の各優先順位を設定する。
move.l #$00e82500, A0
; TVRAM > GVRAM > SPRITE, G0>G1>G2>G3
move.w #$31e4,(a0)
;VC R2($e82600):
move.l #$e82600, a0
; GVRAM有効に。
move.w (a0),d0
and.w #$fff0,d0
or.w #$0011,d0
;or.w #$001f,d0
;or.w #$0000,d0
move.w d0, (a0)
;CRTC R20($e80028)
move.l #$e80028, a0
; GVRAM有効に。
move.w (a0),d0
and.w #$f7ff,d0
move.w d0, (a0)
; V-DISP割り込みベクタを変更
move.l #$000118,a0
move.l #__INT_VDISP, d0
move.l d0,(a0)
;MFP GPIP($e88001):
; V-SYNCが動くように変えてみる
move.l #$e88000,a0
; MFP AER($e88003)
; bit4,V-DISP を1>0の変化で割り込みを発生させる
or.b #$10,$3(a0)
.globl __INT_VDISP
;MFP IERB($e88009):
; MFP AER($e88009)
; bit6,V-DISP 割り込み「発生」を許可
or.b #$40,$9(a0)
;MFP IPRB($e8800d):
; (IERB と同様)
; (IPRA と同様)
; 1:割り込みが発生中(ペンでいんぐ) 0:割り込みは発生してない
; V-DISP割り込み発生フラグが立っていたらクリアする
IPRB_CHECK_LOOP:
move.l #$e88000,a0
and.b #$bf, $d(a0)
move.b $d(a0),d0
and.b #$40,d0
bne.b IPRB_CHECK_LOOP
ISRB_CHECK_LOOP:
and.b #$bf, $11(a0)
move.b $11(a0),d0
and.b #$40,d0
bne.b ISRB_CHECK_LOOP
; MFP IMRB($e88015)
or.b #$40,$15(a0)
or.b #$40,$9(a0)
move.l #0,INT_VDISP
WAIT_VDISP:
; 特権モードじゃないとできねーじゃんこいつ。
stop #$2000
; 別の割り込み要因でもここにきてしまうので。
; 割り込み要因をよくみなくてはいけない。
MOVE.L INT_VDISP, d0
CMP.L #1,d0
bne.b WAIT_VDISP
nop
MOVE.L #0, INT_VDISP
nop
bsr INT_VRAMTRYWRITE
CMP.L #0, VRAM_WRITETRYCNT
beq.b WAIT_VDISP_END
bra WAIT_VDISP
WAIT_VDISP_END:
; 終了前に割り込み解除しないとハングする。
move.l #$e88000,a0
and.b #$bf, $15(a0)
and.b #$bf, $9(a0)
nop
dc.w $ff00
bra WAIT_VDISP
__INT_VDISP:
movem.l a0,-(sp)
move.l #$e88000,a0
and.b #$bf, $d(a0)
and.b #$bf, $11(a0)
move.l #1, INT_VDISP
movem.l (sp)+,a0
rte
INT_VRAMTRYWRITE:
movea.l #VRAM_WRITETRYCNT_60, a0
add.l #1, (a0)
cmp.l #55,(a0)
bmi.b SKIP_VRAMWRITE_TEST
move.l #0, (a0)
bsr VRAMWRITE_TEST
subi.l #1, VRAM_WRITETRYCNT
SKIP_VRAMWRITE_TEST:
rts
;とりあえず終了
pea ?LC1
dc.w $ff09
addq.l #4,sp
dc.w $ff01
dc.w $ff00
nop
nop
nop
?LC1:
.dc.b '割り込みが成功したぽい!!',$0a,$00
.even
VRAMWRITE_TEST:
move.l #$8000,d1
move.l VRAM_POINTER,a1
move.l VRAM_COLOR_CNT,d2
LOOP_START:
move.w d2,(a1)+
;addi.w #1,d2
subi.l #1,d1
cmp.l #0,d1
BGT.B LOOP_START
LOOP_END:
move.l a1,d0
cmpi.l #$0c78000,d0
bmi.b VRAMWRITETEST_USEPOINTER
movea.l #$00c40000,a1
VRAMWRITETEST_USEPOINTER:
move.l a1, VRAM_POINTER
addi.l #$03030303,d2
move.l d2,VRAM_COLOR_CNT
nop
nop
rts
dc.w $ff00
.bss
.even
; xdef, .comm は外部参照可能なシンボル名の定義らしい。
.xdef __SP_SUPER
.comm __SP_SUPER, 4
INT_VDISP:
ds.l 1
VRAM_POINTER:
ds.l 1
VRAM_COLOR_CNT:
ds.l 1
VRAM_WRITETRYCNT:
ds.l 1
VRAM_WRITETRYCNT_60:
ds.l 1
; スタックの宣言
.stack
.ds.w 240
.xdef __STACK_START
__STACK_START:
.end
xm6上では一応このコードで1秒ごとに書き込んで
くれるようです。が、Android版px68kv0.15だとエミュレータが
ハングアップするw
まだまだ欠陥コードですw
human68k上では常にカーソル点滅用か何かの timer-C割り込み
と、マウスデータ受信用のSCC-Bが動く所までは分かっているんですが、
エミュレータごとハングアップする理由がイマイチ不明。
たぶんV-DISP割り込み自体、使っているソフトがほとんどなくて
エミュレータ側の対応がきちんと出来てないケースがあるのでしょう。
それと命令違反をこのコードのどっかでやっているらしく、
それを特定しない事には、なんともなんとも。
ちょっとコードが整理されなくて、スタックの設定値が
これでいいかも怪しいw
自力でここまで自力で作るとなると相当大変。何しろ、human68kの
割り込みが自作コードと競合したりとか…。
ここまで作るのにすっごい時間がかかります。自力で割り込みを
コードするのは極力避けた方がいい。
interruptボタンによるデバッグが非常に便利です。
プログラムがハングしてもhuman68kに制御が戻る。
ただしスタック等の条件によってはこのデバッグ機能は
使えない場合があるようです。
さらにマニュアル類がほとんど手元にない状態での作業。
ツール類の使い方もよく分かりません。
オススメはhuman68kマニュアル、PRO68系マニュアル、
ここらはほぼ絶対に揃えた方がいいです。
プログラムするなら必須同然です。ネットには一応pdfがある
ようですが。
さらにこのMC68000のコアマニュアルもどうにか入手した方が
いいです。命令がかなり動きが複雑。
加算減算とかやってるうちに、いつの間にか物理アドレス>
論理アドレスの変換をやってくれるらしく、
自分が思ったように計算出来ませんw
リロケータブルオブジェクトを使えるようにするために、
cmp命令やmove命令がかなり特殊な動き、自動加算、自動アドレスマスク
をするようです(どうやらそうらしい)。
ただし、スーファミやPC88等と違って、ソースコードデバッガ
SCD.Xがあり、さらにInterruptボタンがデバッグ機能として
使える。さらにXM6エミュレータ側でメモリダンプや内蔵IOの
設定値が見れたり、ブレークポイントが張れたりするので、
実際にはスーファミエミュレータや88エミュレータよりも
「マニュアル類が揃っていて、使い方を覚えていて、
使いこなしているなら」という条件付きならばかなり
デバッグが容易です。何しろソースコード付きでセルフデバッガが
使えるのは非常に大きい。
x68kは軽く、デバッグ性能に優れているようです。
(HDDがあってメモリが一杯積んであるなら、という事だと
思いますが。)
さらにx68kのエミュレータ上とwindows双方での操作も
ほとんど苦になりません。68のワードプロセッサ機能は
意外と賢く、標準エディタedが、使い方さえ覚えてくれば
かなり便利です。
[ESC],Q:終了、[ESC],H : 保存 [ESC],F : 新しく開く、
[ESC],[A]/[D] : ファイルを変更
[F6]:コピー元の行を指定開始>
[F7]:削除&カット/[F8]:コピー、[F9]:ペースト
などなど。
あ。X68k上では漢字コードはSJISのようです。
VisualStudio Codeなどで文字コードを変換しないと
x68k上で漢字は読めないのであしからず…。
コンパイラ系はほとんど触ってないのでどんな様子か
分かりませんが…。
あと_SUPERは d0 に変更上書き前のsspを返します。
次にユーザモードに移行する時にこのsspが必要です。
スタック上に書き込む時は、絶対アドレス指定で
スタックに書き込まないといけないようです。
間接アドレス指定で書き込むと、物理>論理アドレス
変換をCPUが勝手にやってしまうようです。
(これでオオハマリしたw)
ひょえーーー、すっげー大変だよ〜〜デバッグ…。
割り込みのデバッグ超しんど過ぎる…。
割り込みの概要としては。
・ベクタテーブルに実行アドレスを書き込む
(0番地〜はブート後は自動的にハードウェアが
内蔵ROM>RAMに切り替えるのでそのまま書き込んでいいらしい)
・割り込み要因「発生」の許可をする
・割り込みマスクのオフをする(上とは別にいるらしいwしらんがなそんなのw)
・srレジスタで割り込みレベルを下げる
などなどやればどうやら動くようです。でも割り込みルーチンは
rte命令で戻らないと駄目らしいですねこれ。なんでだろ…。
ま、ソフト作るなら素直に本買って勉強しろって事でしょうね。
なげーーよ、やっとコア部分が少し出来たよ…しんどい…。
でw
その後w
「スーパーバイザーモードを使わず、IOCS経由で動かせばpx68kでも
動くんじゃね?」という発想から全部書き直したのが以下の感じ。
px68kで作ったプログラムが動かないというのは都合が悪過ぎます。何しろユーザーの
8割以上を捨てるも同じ。
IOCSとは、x68000 BIOS ROM上に入っている、サブルーチンセット集です。
今でいうx86パソコンのBIOSの先駆けとなるもので、ROM BIOSにみんながよく使いそうな
よく作りそうなプログラムをROM上に入れちゃおう!という感じ。
スーパーバイザーモードにせずとも内蔵I/Oにアクセス出来るのと、
割り込みの設定やらでマニュアルをめくって作る必要もなく、割り込みプログラミング
であーだーこーだー悩みながら作る必要がない、非常に便利な関数機能群という
訳です。
いわば、この機能セットを使えばプログラミングが簡単に出来ちゃうよ、みたいな。
x68k自体、RAMがけっこー広大な1MBあるので、human68kのバージョンアップと
同時にRAM上にIOCSを展開するようにしたりしているようです。
(リセット直後しかROM ベクタを参照せず、あとはベクタは内蔵RAMに切り替わるので
ベクタテーブルの内容をユーザーやプログラムが自由に変更出来る。
簡単にBIOS関係のベクタテーブルを変更出来る。便利だ!)
IOCSは結構便利で、スプライトやVRAMのR&Wから画面モードの設定変更、ADPCM
再生録音などが入っています。でも音楽関係は別途ドライバを組み込まないと
駄目なようです。ほとんどBASICで動かすのと変わらない感じ。
だたゲームの場合は、グラフィック処理ではその都度フルアセンブラで最適化して
ギリギリの高速化を行う事が多そうなので(特にシューティングゲームなんかは
ギリギリまで高速化したりしますよね)、実行速度最優先で作るには
ちょっと向いてない感もありますが。
.text
move.l #(__STACK_START-4), sp
movem.l a0-a5,-(sp)
;pea (STACK)
;dc.w $ff20
;addq.l #4,sp
; printf Test
pea ?LC0
dc.w $ff09
addq.l #4,sp
; IOCS $90 _G_CLR_ON を呼び出して
; グラフィック関係内部変数を初期化
move.l #$90,d0
trap #15
; IOCS $b5 _WIPE
; グラフィック画面をクリアする
move.l #$b5,d0
trap #15
; IOCS $b9 _BOX
; box を描画する
sub.l #12,sp
move.w #100, 0(sp)
move.w #100, 2(sp)
move.w #400, 4(sp)
move.w #400, 6(sp)
; パレットコード
move.w #1, 8(sp)
; ラインスタイル
move.w #$ffff, 10(sp)
move.l sp,a1
move.l #$b9,d0
trap #15
add.l #12,sp
cmp.w #0,d0
beq.b BOX_OK
pea ?LC1
dc.w $ff09
addq.l #4,sp
BOX_OK:
;dc.w $ff01
;dc.w $ff00
; スーパーバイザーモードに遷移して
; VDISP割り込み時に絵をかく
; スーパーバイザーモードへ。
;move.l #0,a1
;dc.w $ff20
;move.l d0, __SP_SUPER
;add.l #4,sp
move.l #0,INT_VDISP_ON
move.w #20, VDISP_CNT
move.w #300,VDISP_Y
; IOCS $6c: 垂直同期割り込みを設定
move.l #INT_VDISP, a1
move.l #($0+27),d1
move.l #$6c,d0
trap #15
cmp.b #0,d0
beq.b INTSET_OK
; 「割り込み設定に失敗。」
pea ?LC3
dc.w $ff09
add.l #4,sp
dc.w $ff00
.even
nop
INTSET_OK:
SLEEP_LOOP:
.if 0
; スーパーバイザーモードの使い方がよく分からん。
; どうやっても暴走するんだが。
move.l #0,a1
dc.w $ff20
move.l d0, __SP_SUPER
add.l #4,sp
; stop で割り込み待ち!としたい所だけどとりあえずループで。
stop #$2000
move.l __SP_SUPER,a1
dc.w $ff20
move.l d0, __SP_SUPER
add.l #4,sp
.endif
cmp.l #1, INT_VDISP_ON
bne.b SLEEP_LOOP
sub.w #1,VDISP_CNT
beq.b VDISP_CNT_END
bsr.b VDISP_DRAWBAR
move.l #0,INT_VDISP_ON
bra SLEEP_LOOP
VDISP_CNT_END:
; IOCS $6c: 垂直同期割り込みを解除
move.l #0, a1
move.l #($0+27),d1
move.l #$6c,d0
trap #15
pea ?LC2
dc.w $ff09
addq.l #4,sp
; human68k, _exit
dc.w $ff00
VDISP_DRAWBAR:
movem.l d0/a1,-(sp)
; IOCS $b9 _FILL
; カラーバーを描画する
sub.l #10,sp
move.w #300, 0(sp)
move.w VDISP_Y,d0
move.w d0, 2(sp)
move.w #500, 4(sp)
add.w #30,d0
move.w d0, 6(sp)
move.w d0, VDISP_Y
; パレットコード
move.w VDISP_CNT, d0
and.w #$000f,d0
move.w d0, 8(sp)
;move.w #1, 8(sp)
move.l sp,a1
move.l #$ba,d0
trap #15
add.l #10, sp
; INT_VDISP_Y が500になったら200に戻す
cmp.w #450,VDISP_Y
bmi.b VDISP_DRAWBAR_END
move.w #300, VDISP_Y
VDISP_DRAWBAR_END:
movem.l (sp)+,d0/a1
rts
.global INT_VDISP
INT_VDISP:
movem.l d0/a0,-(sp)
move.l #1, INT_VDISP_ON
movem.l (sp)+,d0/a0
rte
.text
?LC0:
.dc.b 'abcde',$0a,$0d,$00
?LC1:
.dc.b '戻り値が0以外。',$0a,$0d,$00
?LC2:
.dc.b '処理終了',$0a,$0d,$00
?LC3:
.dc.b '割り込み設定に失敗。',$0a,$0d,$00
.even
.bss
.even
.xdef __SP_SUPER
.comm __SP_SUPER,4
.xdef INT_VDISP_ON
.comm INT_VDISP_ON, 4
.comm VDISP_CNT,2
.comm VDISP_Y,2
; スタックの宣言
.stack
.ds.w 240
.xdef __STACK_START
__STACK_START:
.end
IOCSを呼び出す際はこんな感じ。
・汎用レジスタのd0でIOCS機能番号を指定( 32bit?8bit指定でも平気そうだけど)
・機能番号ごとにその他レジスタを設定
・trap #15 命令を使って 0x000000bc 番地ベクタを呼び出す
スーパーバイザーじゃなくても動くのがラクでいいですよね。でも
その都度スーパーバイザーモードに変更するのでパフォーマンスはどうかという
印象がありますが。
_BOX命令を使って箱を表示するコードに最初挑戦してみたのですが、最初はサッパリ
動きませんでしたwいっくらやっても_WIPEやっても_WINDOSやっても_APAGEやっても
_VPAGEやってもやっぱり動かない。
「なんで動かないんだよこいつ・・・」
さらに都合の悪い事に、PRO68kの scd.x ソースコードデバッガと相性がよろしくない。
IOCS周りでstep実行を行うと、どういう訳か「正常終了」と表示されてプログラムが
終了してしまう。go-breakやブレークを張る感じとか、マウス右クリックによる
go-breakならtrap絡んだコードでも動くようです。
(xm6 の場合。px68k上だとそもそもstep実行するとpx68k自体がハングアップしてしまう)
xm6上でそもそもブレークポイントを張る機能があるので、多少動かないぐらいで
大騒ぎする必要もないように思えますが、
それでもhuman68k上でその都度自分が作ったソフトがRAM上のどこに読み込まれたのか
確認する必要があります。ブレークをはるアドレスをその都度調べなきゃいけない。
そのアドレスをいちいち確認するのはかなり面倒です。やり方分からないし。
human68k自体はマルチプロセス、マルチタスク実行が前提らしく、
動的に aaa.x を任意のメモリに読み込む仕様となっています。そのせいで
デバッグの際、ブレークポイントを一か所固定で特定出来ません。
(88やスーファミだと動的ロードにしずらいCPU構造なので)
どうやらドライバの動的ロードに対応している、らしい。でもそんなコマンド、human68k
にはざっと見た感じ無さそうです。config.sysにはドライバを指定してますが…。
勉強不足なのでちょっとよく分かりませんが。
ちょっと謎なのが、CPUコアにデータポインタがないw
セグメントレジスタ相当やデータポインタに相当する、
プロセス毎に使用するベースアドレス?相当がCPUにない。
もっと細かく丁寧に言うならば、例えばユーザープロセスが自分が用意したグローバル変数にアクセス
する際に変数をどうやって指定しているんでしょう?これ?
メモリ位置の動的ロードに対応したCPUであれば必ずデータポインタ相当を用意するのが定番の
はず?
変数 nSoftCount というのがあったとします。
human68kにより 8 0000 番地に読み込まれたとします。
8 0000番地+オフセット値でユーザープロセスはメモリにアクセスする事で
nSoftCount という変数にアクセスするはず。オフセット値だけはユーザープロセスの
バイナリに埋め込み。
もし、絶対アドレス指定で最初から 8 0000番地という固定アドレスをユーザープログラムの
バイナリに埋め込んでしまった場合、任意のメモリアドレスにユーザープログラムを
ロードできませんよね・・・。
これどうやってんだろ?アセンブラ側で自動的に絶対アドレス指定を変化させてるのかなぁ。
内蔵IOアドレスと変数、bssセクション内の場合とで自動判別してるんでしょうか。
リンカやローダーが勝手に判断してるんでしょうか?
謎ですw
これに合わせて、CPUが絶対アドレスを勝手にどっかでコンバートしているようですw
いやぁ。さっぱり訳が分からない謎だらけですw
バスコントローラ、アドレスデコーダー相当はどうやら無さそうだし…
IOCS系を使う時は呼び出しに失敗した時に d0 に-1とか-2を返してくるので、
それをトラブル時に見る必要がありそうな感じ。ちょっと面倒くさい。
で、あれこれ試した結果、IOCSのグラフィックの初期化関数を呼び出して無かったのが
原因らしいですw IOCS $90 _G_CLR_ON を呼び出しておかないとグラフィック関数系は
まるごとコケるようです。
これかなりダイジw
このコードで作ったバイナリ.x は一応px68k上で動くようです。2回ほど確認。
スーパーバイザーモードを一切自分で設定せずに一応GVRAMに書き込めるようです。
あとちょっと分からないのが、GVRAMへ書き込むタイミング。スーファミだと
垂直/水平同期ブランキング期間でないと、VRAM操作をやった際に、ビデオICとアクセス競合が
発生してデータ化けが起きます。
(水平帰線期間とも言うらしい。)
SFCなんかだとVRAMへのアクセス量を増やすために強引に水平同期ブランキング期間中に
VRAMに書き込む方法を取る場合もある(・・・が、ほとんどのソフトはここまでやってないので
そもそもエミュレータがこの機能に対応しておらず、フツーにVRAMに書き込んでも反応
してくれないwクロノトリガーのメニュー表示などがその例のようです)
さて、68だと大丈夫なのかな?いつでもVRAMに書き込んでいいのかしらん?
という辺りがちょっと不明確でよく分かりませんね。エミュレータでここまで丁寧に
対応する事もそもそも滅多にないでしょうし…。
こればっかりは実機で検証しないと分かりませんし、そもそもエミュレータ側で
対応してない、動かないならほとんどのユーザーがこのメリットに触れる機会も
無いのでここまで必要ないのかも。
SFCの例に漏れず、おとなしく素直に水平ブランキング期間中に書き込む方が
どうも安全そうな気がします。ま、絵が出れば後はどうでもいいですけどw
作ってる最中にHDDがクラッシュ。原因不明…。フォーマットして入れ直しました。
ちなみにpx68kではどうやら、HDDにデータを1つ書き込むたびに、スマフォのフラッシュ上の
ファイルを更新しているようですw(書き込み異常に遅いんだよねどういう訳かw)
フォーマット操作をやってみたのですが、どういう訳かやたらと時間がかかる。
HDDが100MBで、HDDに100回書き込むと、100MBのHDDイメージをフラッシュROMに100回
保存という恐ろしい事をやっているでは・・・wという恐ろしい恐怖に憑りつかれたりして・・・w
どうやらAndroid上にRAMディスクを作らないと非常に危険そうな感じです。
ここら辺はpx68kのソースコードの中身見て見ないとよく分かりませんが、危ないので
原則px68k上では保存はやらない方が良さそうな感じです。
px68k上でHDDにデータを書き込む、という操作はとりあえず避けた方が安全そうですが、
実際のところは調べてみないとよく分かりませんが…。
HDDが2回ほどクラッシュしたのですが、ds.wとdc.wを間違えてやると
クラッシュしやすいのかな?という印象。
例えば
dc.w $ff00
を
ds.w $ff00
と間違えると、ほぼ64KBというくそでかいデータをデータ確保してしまうw
でもアセンブラ側はたいしたエラーチェックもせず、データ上限を無視して
実行してしまい、HDDなりにそのまま巨大データを作ってクラッシュするのでは?
みたいな印象でした。世代的にもファイルシステムドライバがまだ脆弱な時期のもののため、
定期的にバックアップを取る必要があるようです。
(っていうかうちのxm6環境で実機のSCSIイメージを使ってないのが悪いのかも)
あとCPUの割り込み待ち時間中にスーパーバイザーモードに変更してstop命令でまとうとすると
なんか動かないw
ユーザーモード中はstop命令がそもそも動きません。
昨今のMicroSoft Windowsは原則、winProcによるメッセージ待ち構造ですから、stopで割り込み
待ちコードにした方が無駄にCPUパワーを食わないで済みます。
メッセージが来るまでユーザープロセスはスリープ状態になる。
(無限ループ構造にする事も出来るけど、CPU使用率が100%になるので
シリアル通信でもしない限り滅多にこういう構造にはしない。)
ホストの負担も考えると、割り込み待ち=メッセージ待ちにした方がいいに決まってるw
でもなんでか動かないし…。
どう弄りまわしても動かなそうなので素直にループ待ちにした所やっとなんとか動いた感じw
IOCSのみで、CPUパワーのほとんどを使わないでゲーム作るという感じが無難そうですが…。
それだと市販ゲームで出ていたようなシューティングはちょっと難しそうですよね。
パロディウス辺りではCPUパワーが足らず、Cからアセンブラに作り直したという話もあったそうですし。
x68000のCPUコアであるMC68000はアセンブラ命令体系が極めて直交性が高いので、
C言語で描くのとそんな変わらない感じもします。が、
でも出力した.Sをちらっと見た感じだとCコンパイラやっぱかなり馬鹿っぽい印象がありますw
アセンブラとC言語、どちらで作ってもどっちもどっちな感じです。
アセンブラ:かなり高速化できる。その一方で作る手間が半端なく増える。デバッグが分かりずらい。
C言語:遅い。コンパイラのロジックバグが怖い。作る手間は早い。でもアセンブラの機能を使い切れない。
他のプラットフォームでもソースコードを流用出来なくもない。
(x68kはそもそもホビー用途に使われる事が多い。スプライト機能を考えると
ゲーム製作用途としては向いている。ゲームだとこの世代ではフルアセンブラにする事が多いので
「C言語で作って移植する」という発想がそもそも間違っているw)
C言語とアセンブラ、どっちで組むべきか…なんとも言えないですよねぇ・・・。
あとIOCS自体はSharp/Hudsonのライセンス、著作権ですし、今さらIOCSの動きがおかしい!とかいう
感じでバグで騒がれても作った人達の都合が悪いだろうし・・・。使用権がじゃーお幾らデスカー?
という話になって来るとこれまたグレーゾーンで、そりゃ当時作った人達だってお金すごい欲しい
って人もいれば、こんなもん今さら値段つく訳ねーだろ!という人もいる訳だし…。
でもIOCSで簡単にプログラム作れるっていうのは非常に魅力的ですよね。
今さらバージョンアップする訳にもいかないし、バージョンアップするぐらいなら
そもそもx68kで開発するのが無意味という話にもなって来るし、そもそもIOCS相当を自分で
立ち上げて作った方が良いという話にもなって来るしw
PCのビルト/実行環境の問題は悩みが本当に尽きないですよねw
何しろ、VisualStudioやJava Eclipse、Android Studioといった巨大な開発環境をインストールする必要が
無いというのはやっぱり便利。その代わり開発資料がすごく少ないのとあれこれx68k系の本を
買い漁る必要が出て来る訳ですがw
おまけにCPUパワーがしょぼいパソコンでもどうにか開発できて、エミュレータさえ移植されて
いれば実行環境がお手軽に手に入るというのもやっぱり魅力ではw
※NMIスイッチとスーパーバイザーモードの相性を調べてみました。
ユーザー空間中(srのD13=0)中だとNMIスイッチを押すと、中止再開が出来る。
これは多分 ssp 上にあるスタックから戻りアドレスを判断してるためと思われる訳ですが…。
じゃースーパーバイザーモードでNMIスイッチをデバッグ用途に使えるんでしょうか?
という感じで実験してみたのですが。
1.スーパーバイザーモードにして( dc.w $ff20)、無限ループ待ちにした状態で
NMIスイッチ>中止(A)をやるときちんと親プロセスに戻るようです。
2.sspを減らして変なスタック状態にしても、NMIスイッチ>中止(A)>親プロセス(human68k)に
戻るようです。なんで戻るんだろ・・・一体どこの変数見て親プロセスに戻ってるんだ…。
3.スーパーバイザーモードにしてstop 命令を使っても
stop #$2000
bra 上
の無限ループ待ちにしても、NMIスイッチで上位側に戻る。
4.さらにsspを無意味に使った状態(ssp に ssp-4 をセット)でもなぜか上位側に戻るw
(sspのスタック上に戻りそうなもんなのになぜw)
ユーザー空間上のプロセス管理ポインタをBIOS NMI ルーチンが見て上位側に戻る仕様
なんでしょうかこれ???訳分からんwどうやって上位側に戻ってるんだろうこれw
謎だらけチンプンカンプンですwなんでぼくの作ったVDISP割り込みだと暴走しまくり
だったのか、謎だらけw
・・・で、このぼくの作ったプログラム、いつになったらゲームになるのこれw
いつになったら音出るのよこれwいつになったらキャラクターを操作できるのよこれw
いつまで試作とテストやりゃいいんだよこれw
だいたい68でソフト作った所でみんなわざわざ金払ってやる人なんかおらんだろうってのにw
もどる
ほーむ