ユーザ用ツール

差分

このページの2つのバージョン間の差分を表示します。

この比較画面へのリンク

次のリビジョン
前のリビジョン
mz-700 [2023/12/06 09:58] – 作成 arakimz-700 [2026/07/16 07:35] (現在) – [MZ-800エミュレータでMZ-700のIPLを使う] araki
行 2: 行 2:
  
 ===== 概要 ===== ===== 概要 =====
 +
 +{{:undefined:mz721.jpg?400|}}
 ===== MZ-800エミュレータでMZ-700のIPLを使う ===== ===== MZ-800エミュレータでMZ-700のIPLを使う =====
  
行 10: 行 12:
 但し、正しい作法を守れば、という条件がついている。 但し、正しい作法を守れば、という条件がついている。
 単純に、MZ-700のIPLを与えれば動くというものではないので、ここではその作法について説明する。 単純に、MZ-700のIPLを与えれば動くというものではないので、ここではその作法について説明する。
 +
 +なお、mz-800emuは2.0.x-previewから mz700emu-ntsc, mz700emu-pal, mz1500emu もビルドできるようになっており、それぞれの機種向けのROMも内包している。((ただしライセンス的に白かどうかは不明。MZ-1500に関しては、書籍でIPLが完全公開されているので問題はないかもしれないが。))
 +
 +ただし、実機から吸い出したROMを使用する場合は、たとえmz700emu-ntscであっても、以下で説明しているパッチを適用する必要がある。
  
 ==== MZ-800をMZ-700のようになるまで初期化する ==== ==== MZ-800をMZ-700のようになるまで初期化する ====
  
 +MZ-800はMZ-700互換であるが、異なるハードウェアである。
 +巷では、MZ-700の海外版であるかのように紹介されているが、MZ-700の海外版は海外版として存在している。
 +
 +MZ-800はMZ-700とMZ-1500の中間的なハードウェア構成であり、SN76489ANがあったり、ビットマップVRAMを持っていたり、PCGがあったりと、かなり異なるハードウェアであるため、正しくMZ-700モードに移行させてやらなければ、1Z-009Aは動作しない。
 +
 +ここでは、行うべき初期化について説明し、1Z-009Aにパッチを当てて、MZ-800 エミュレータ上で動作させる方法を説明する。
 +
 +これにあたっては、以下のものを用意する必要がある。
 +
 +  * MZ-700実機からコピーした IPL.ROM((モニタ上で S00000FFF0000 として、テープにセーブするなどして取り出す。))
 +  * MZ-800エミュレータ((svn checkout https://svn.code.sf.net/p/mz800emu/code/mz800emu-code として取得する。バイナリでも構わないが1.0.8 REV237以降を推奨する。))
 +  * [[https://www.wildtree.jp/~araki/ipl2.rom|MZ-800を初期化するコード(ipl2.rom)]]。
 +  * MZ-700WINなどで使用するFONT.ROM((MZ-700のCGROMはCPUにはつながっておらず、実機から吸い出すことは困難。))
 +
 +MZ-800エミュレータで1Z-009Aを動作させるためには、IPL.ROMの先頭3バイトを 0xc3,0x00,0xe8 に書き換え、ipl2.rom内の初期化ルーチンを呼び出す形にパッチを当てる必要がある。
 +パッチを当てたものを iplp.rom とする。
 +
 +また、フォントについてもMZ-700WINのものをそのままでは使用できず、フォントのビットマップパターンを左右反転させる必要がある。どのような方法でも構わないが、例えば、以下のような ruby のコードを使用すれば変換できる。
 +変換後のファイルを cgrom.romとする。
 +
 +<code>
 +#!/usr/bin/env ruby
 +
 +cgrom_rev = []
 +open('font.rom') do |f|
 +  cgrom = f.read.unpack("C*")
 +  cgrom.each do |c|
 +    i = 128
 +    j = 1
 +    d = 0
 +    while i > 0 do
 +      d |= j if c & i != 0
 +      j <<= 1
 +      i >>= 1
 +    end
 +    cgrom_rev.push(d)
 +  end
 +end
 +open('cgrom.rom','w')do |f|
 +  f.write cgrom_rev.pack("C*")
 +end
 +</code>
 +
 +ファイルが揃ったら、MZ-800エミュレータのメニューからROM→Settings for User Defined...を選んで、Enable User Defined ROMにチェックを入れたら、Seperate ROM Binary Filesを選び、それぞれのROMファイルを指定する。
 +
 +{{::mz800emu_user_defined_rom.png?400|}}
 +{{::mz800emu_rom_setting.png?400|}}
 +
 +Applyを押せば、1Z-009Aが起動する。
 +
 +{{::mz800emu_1z-009a.png?400|}}
 +
 +==== MZ-800の初期化処理について ====
 +
 +MZ-800は電源投入後、またはリセット直後は MZ-800モードで起動するが、その後、MZ-700モードに移行し、CGROMや周辺デバイスの設定を行った後、ディップスイッチの設定を読んで、MZ-800またはMZ-700それぞれのモードに移行する。
 +
 +MZ-700のROMを使うのであればディップスイッチの如何に関わらずMZ-700モードへと移行し、本来のモニターに制御を戻すようにしてやればいい。
 +
 +この時、MZ-700とは異なるMZ-800のハードウェアを適切に設定して、適切なポイントへ制御を戻す必要がある。
 +
 +具体的に問題となる、MZ-700とMZ-800との違いには以下のものがある。
 +
 +  * MZ-800モードとMZ-700モード
 +  * CGROMデータのPCGへの転送処理
 +  * 画面モードの設定と画面クリア
 +  * 8255/8253およびSN76489ANの初期化
 +
 +=== MZ-800モードとMZ-700モード ===
 +
 +MZ-800はポート0xceに0x08を出力することで、MZ-700モードへと移行する。
 +このポートはディスプレーモードレジスタにつながっていて、画面モードの設定を行うのだが、0x08を渡すと、メモリーマップがMZ-700相当のものになる。
 +
 +この時、0x0000~0x0fffと0xe000~0xffffにはROM(0xe000~0x00fはmemory mapped I/O)が割り当てられ、0xd000~0xdfffにはVRAMが割り当てられる。
 +
 +IPL2.ROMではまずこの処理を行う。
 +
 +=== CGROMデータのPCGへの転送処理 ===
 +
 +MZ-800はMZ-700とは異なり、CG-ROMにCPUからアクセスができる。
 +また表示に使われるデータはPCGのデータが参照されるため、CG-ROMの内容をPCGに設定する必要がある。
 +
 +MZ-700モードにあるときに、ポート0xe0から値を読むと、0x1000~0x1fffにCG-ROMが、0xc000~0xcfffにPCGがそれぞれ割り当てられるので、この状態で、CG-ROMの内容をPCGに転送する。
 +
 +転送が終わったら、ポート0xe1から値を読みだせば再び0x1000~0x1fff, 0xc000~0xcfffにDRAMが割り当てられた状態に戻る。
 +
 +<code>
 +in a,(0e0h)
 +
 +ld hl,01000h
 +ld de,0c000h
 +ld bc,01000h
 +ldir
 +
 +in a,(0e1h)
 +</code>
 +
 +これで、MZ-700のCG-ROMデータ((ここでは、エミュレータ用のデータだが。))が表示に使用されるようになった。
 +
 +=== 画面モードの設定と画面クリア ===
 +
 +MZ-700のROM内にも画面クリアーのコードがあるが、アトリビュートだけを0x71(文字色白、背景青)にするだけで、文字データ自体をクリアしない。
 +
 +MZ-700の場合はリセットでおそらくテキストVRAMがクリアされるのだが、MZ-800ではそうではないため、VRAMをクリアするコードを追加してやる必要がある。
 +これを行わないとリセット直後に謎の模様が画面に表示されることになる。
 +
 +
 +=== 8255/8253およびSN76489ANの初期化 ===
 +
 +MZ-700と異なり、MZ-800は8253のポート0の出力がスピーカーに直結せずに、代わりに SN76489ANの Audio INにつながっている。
 +また、SN76489ANにクロックの供給も行っている。
 +このクロックの供給の制御は 8255が行っている。
 +
 +このため、この関係に従って初期化を行わないと、謎のホワイトノイズが出っぱなしになり、8253にコマンドを送っても音を奏でることがなくなってしまう。
 +
 +MZ-700の8255の初期化は、8253からSN76489ANへのクロック供給を有効化しないため、これに代わる処理を行い、逆にMZ-700側の初期化ルーチンをバイパスしてやる必要がある。
 +
 +幸い、1Z-009Aの8253/8255の初期化はほぼ初めに行われるため、モニターのエントリーポイントではなく、この処理の直後に、IPL2.ROM側から戻してやることで、システムの状態を正しく保ったまま処理を継続させることができる。
 +
 +==== 初期化コード ====
 +
 +上記の処理を以下のように実装した。
 +
 +<code>
 +;===========================
 +; MZ-800 to MZ-700
 +;===========================
 +        .z80
 +        org     0e800h
 +mz700   equ     00052h  ; do not return to 004ah
 +stack   equ     010f0h
 +cgrom   equ     01000h
 +pcgram  equ     0c000h
 +mset53  equ     00308h
 +
 +entry:
 +        di
 +        im      1               ; set interrupt mode to 1
 +
 +        ld      a,8             ; set MZ-700 mode
 +        out     (0ceh),a
 +        ld      a,1             ; set CRTC to MZ-700 mode
 +        out     (0cdh),a
 +        out     (0cch),a
 +        out     (0e4h),       ; set memory map
 +        ld      sp,stack        ; initialize stack pointer
 +        ; init 8255
 +        ld      a,08ah
 +        ld      (0e003h),     ; set 8255 to MZ-700/800/1500 mode
 +        ld      a,1
 +        ld      (0e003h),     ; enable clock supply to SN76489AN
 +        ld      a,5
 +        ld      (0e003h),     ; enable timer interrupt
 +        ; init 8253
 +        ld      de,0
 +        call    mset53
 +        ; init PIO
 +        ld      bc,04fch
 +        ld      hl,piodat
 +        otir
 +        ld      bc,04fdh
 +        otir
 +        ; init SIO
 +        ld      a,1
 +        out     (0f7h),a
 +        xor     a
 +        out     (0f7h),a
 +        ; init PSG (SN76489AN)
 +        ld      b,4
 +        ld      a,09fh
 +psgset:
 +        out     (0f2h),a
 +        add     a,020h
 +        djnz    psgset
 +        ; init screen
 +        ld      hl,0d800h
 +        ld      de,0d000h
 +        ld      bc,0400h
 +cls_loop:
 +        ld      (hl),71h        ; set fgc=7/bgc=1
 +        inc     hl
 +        xor     a
 +        ld      (de),         ; erase vram
 +        inc     de
 +
 +        dec     bc
 +        ld      a,b
 +        or      c
 +        jr      nz,cls_loop
 +
 +        ; copy CGROM to PCG
 +        in      a,(0e0h)
 +        ld      de,pcgram
 +        ld      hl,cgrom
 +        ld      bc,1000h
 +        ldir
 +        in      a,(0e1h)
 +
 +        jp      mz700
 +
 +        org     0e900h
 +piodat  db      000h,0cfh,03fh,007h,000h,0cfh,000h,007h
 +
 +        end
 +</code>
  

This website uses cookies. By using the website, you agree with storing cookies on your computer. Also, you acknowledge that you have read and understand our Privacy Policy. If you do not agree, please leave the website.

More information