ATtiny2313 ROMエミュレータを使ってみる
なんちゃってROMの動きを確実に確かめるために、なにかよいアプリケーションはないかと考えました。 そこで、Joystick版のSDカードアダプタからの読み込みをすることにしました。
とはいっても、Joystick版の場合、SPIの動作をすべてAY-3-8910のI/Oで実現する必要があるため、非常に多くのコードが必要になります。 たとえば、1ビットの何かを出力するためにも、
ld a, #0x0f out (#0xa1), a ld a, #value out (#0xa2), a
といった具合に、愚直に実現すると8バイトもかかってしまいます。
なんちゃってROMに許されたアドレス空間は、アドレス線の本数の制約により128バイト。 先頭の4バイトはBIOSがROMの判別とジャンプアドレスを得るために必要なため、実際は124バイトしかありません。
そこで、ファイルを読み込むのは最初からあきらめ(FATなんてとても入らない)、セクタ0を読み込むことにしました。 もともとセクタ0の最初の446バイトは、ブートアップのためのコードを格納する領域ですしね。
それでも、電源ON->初期化->読み込みとあるため、結構大変です。 リリース済みのドライバを見てみたら、398バイトもありました。
それを削りに削りました。 エラーチェックやらレジスタの使い回しやら、それはもう、あらゆる手を使って。 で、なんとか124バイトの枠内に収めました。
Z80変態プログラム
で、できたものがこれです。 これから先は変態プログラムです。 よい子は見てはいけません。
SDDRV_DI = 0x10 ; output, pin8 SDDRV_CS = 0x02 ; output, pin7 CMD_READ = 17 | 0x40 ; command for read REG = 0xa0 ; I/O port AY-3-8910 register latch WRITE = 0xa1 ; I/O port AY-3-8910 write READ = 0xa2 ; I/O port AY-3-8910 read REG_SEL = 0x07 ; AY-3-8910 I/O select REG_IOA = 0x0e ; AY-3-8910 I/O A (input) REG_IOB = 0x0f ; AY-3-8910 I/O B (output) .org 0x4000 .db 0x41 ; 'A' .db 0x42 ; 'B' .db 0x04 .db 0x40 ; start from 0x4004 ;; from 0x0083, Z=1, Cy=0, StackTop=0x0084 ;; A=0x42, B=0x00, C=0x3d, D=0xfb, E=0x61, H=0x40, L=0x04 _boot_start:: ld de, #0x0f08 ; REG_IOB, counter ld a, #REG_SEL ; 0x07 out (#REG), a rrca ; 0x83 out (#WRITE), a ; setup AY-3-8910 I/O ld a, d ; 0x0f out (#REG), a ld a, #(SDDRV_DI | SDDRV_CS) ;0x12 out (#WRITE), a _boot_init_loop: out (#WRITE), a ; DI | CS inc a out (#WRITE), a ; DI | CS | CLK dec a djnz _boot_init_loop call _boot_cmd ; H=0x40 (reset), H is set by caller inc h _boot_init_cmd1: call _boot_cmd ; H=0x41 (init) dec c jr nz, _boot_init_cmd1 ld h, #CMD_READ call _boot_cmd ; H=0x52 (read) call _boot_wait ld h, #0xe2 ; L=0 _boot_read_loop: call _boot_bytein ld (hl), c inc l jr nz, _boot_read_loop ; fall through ;; AFBC________ ;; out C=input byte, B=0, A=0or1 _boot_bytein: ld b, e _boot_bytein_loop: ;; 8 times of bit read ld a, d ; 0x0f out (#REG), a inc a out (#WRITE), a ; DI inc a out (#WRITE), a ; DI | CLK ld a, #REG_IOA ; 0x0e out (#REG), a in a, (#READ) ; if A[0]=1, then data=1 rrca ; A[0]->CY rl c ; cy<-[7<-0]<-cy djnz _boot_bytein_loop ret ;; AFB_________ ;; in C=output byte ;; out B=0, A=0x01/0x11 _boot_byteout: ld b, e _boot_byteout_loop: ld a, d ; 0x0f out (#REG), a inc a ; 0x10 rlc c jr c, _boot_byteout_data xor a _boot_byteout_data: out (#WRITE), a ; (DI) inc a out (#WRITE), a ; (DI) | CLK djnz _boot_byteout_loop ret ; B=0, A=0x01/0x11, Cy=0, Z=0 ;; AFBC___L____ ;; in: H=cmd (must have 0x40 offset) ;; out: C=result+1 (1, 2, 0xff), B=0, L=0, A=0x00/0x01, Z=0, Cy=0 _boot_cmd: ld c, #0xff call _boot_byteout ; dummy ld c, h ; A=0x11 call _boot_byteout ; cmd ld c, b ; 0x00 ld l, #0x04 _boot_cmd_loop: call _boot_byteout ; arg dec l jr nz, _boot_cmd_loop ld c, #0x95 call _boot_byteout ; CRC (for CMD0) _boot_wait: ; L=0, A=0x11 call _boot_bytein inc c ret nz ; bytein != 0xff (0, 1, 0xfe), Z=0 jr _boot_wait
実際にはプログラムは122バイト(全体で126バイト)で済んでいます。 なお、タイムアウト判定を省略しているので、正常にSDカードが挿さっていないと無限ループします。 そのチェックは容量内ではできませんでした。 また、セクタ0の最初の256バイトのみ読んでいます。
まぁ、言うほど変態チックじゃないかな?
動かしてみると、正常に読んでいるため、20MHz動作なら問題ないみたいです。
匿名
画面が真っ暗、でもカーソルは出てる状況。
探して、ここにたどり着きました。
パスワード入力で、復活!
修理に出す寸前でした。ホントにありがとう!