WWITCHのBIOS呼び出し(int 〜)の代わりに、対応するサブルーチンを呼ぶことによって、 MS−DOSモードで、VGAの320x200モードの画面を使用し、 ワンダーウィッチの画面と入力をエミュレートします。
これにより、ワンダーウィッチに転送せず、MS−DOSモードの環境で、 ワンダーウィッチ用のプログラムをテストランさせることができます。
とくに、アクションゲームを作成するために必要な部分から設計を行っているので、 ほかの分野のプログラムにはあまりなじまないと思われます。
→0.8a での重要な変更点
長所
画期的な長所
- ワンダーウィッチに転送する手間がありません。
ワンダーウィッチのフラッシュの寿命に貢献します。- MS−DOSで使えるデバッガが使えます。 (私のところで確認したのは、symdeb のみです。 まあ、大概のデバッガは使えるとは思いますが)
- int 21h など、MS−DOSで使えるシステムコールが使えます。 (アセンブラレベル、あるいは、MS−DOSコールを生成するコンパイラの設定を知っている場合)
些細な長所
- Windows以前のMS−DOSでも使えます。(そんな人いるんでしょうか?)
- 液晶を見ないでいいので、目が疲れません。
- 画面のスナップショットを簡単に取れます。
- 簡単なデバッグ文字列出力をサポートしており、 エミュレーション液晶の画面を汚さずデバッグ情報を画面に表示できます。
- ちょっと怪しいですが、縦に持つゲームも開発できます。(0.7h以降)
短所
重大な短所
- エミュレーションの対応がないBIOSは、働きません。
stdio などの、FreyaOSも働きません。(ファイルアクセスを行うものなど。) 現状では、多くのBIOSが未対応であり、物足りないと思います。- サウンドがまったく出ません。その他、ILはすべて使えません。 もちろん、FreyaOSに依存する部分はすべて動きません。
- もともと自分の使用が、アセンブラからのゲーム開発のためだけなので、 Cの人には不便なところがあるかもしれません。
そもそもLSICでは動くかどうかの確認もしていません。
アセンブラのサブルーチンをCから呼ぶときの挙動をしっかり理解していないと、 うまく使えないかもしれません。
些細な短所
- タイミング依存のプログラムには使えません。
シリアル通信など、実機にしかないハードウェアを使用するプログラムにも使用できません。- 実機の液晶のいろみと違って見えるかもしれません。
実機と細部の挙動が変わるかもしれません。横のスプライトオーバー(32キャラクタ)しなかったり、 いろいろ食い違うところがあるかもしれません。- DOS窓のフルスクリーンモードでないと、正常に画面の更新が行われません。 (ウィンドウ表示モードでも走るだけ、Windowsって偉い?) テストランのたびにモード切り替えすることになると思うので、 PCのディスプレイがカチカチ切り替わるのが心苦しい方もいると思います。(私もそうです)
- WindowsアプリケーションではないEXEファイルが出来るので、 何かと不便かもしれません。
- BIOSを介さずハードウェアを操作するプログラムは走りません。 物理アドレスに依存するプログラムも走りません (SSの値が違うと走らないようなコード。DSやSSの下のほうの桁が0であることを期待するコード等)
- BIOSと、無関係なレジスタの壊れ方が違うかも知れません。
基本的に全レジスタ壊れてしまうものと思ったほうが無難です。- たまにはDOS窓がきちんと処理されないアホなWindowsがいて、 まったく動かないかもしれません。
- リンク時やコンパイル時に、実機用とエミュレート用の環境を両方作るのが面倒くさいかもしれません。
- 軌道直後のVRAM、パレットなどがMegのものと同じではありません。
起動直後は画面の初期化などはきちんと行わないといけません。(手抜きできません)
ゲーム専用の開発で、ワンダーウィッチ実機でのデバッグにへきへきなさっている方は、 試してみるのもよいと思います。
アクションゲーム開発のためだけでなら、この短所をカバーして余りある長所を持っていると思います。
だいたいのWindows機で大丈夫だと思います。
VGAをきちんと処理できるビデオカード、ビデオドライバが必要です。
VGAの画面モード$13を使用します。
ウィンドウ表示(フルスクリーンでない)DOS窓の場合、VSYNC待ちがうまく処理されず、 画面の更新が異常になることがあるかもしれません(ビデオドライバ、ビデオカード次第)
CPUのパワーは、セレロンで466メガのものでも処理速度はかなり余裕がありますので、 1998年以降ぐらいにそろえたPCならだいたい大丈夫だと思います。 (やってみないと分かりませんが・・・)
wssimsam.lzh に、TCで使用できるサンプルがいくつか入れてあります。 ためしに見てください。make も、おそらくTCの中のmakeでいけると思います。 (VisualC++のある方なら、nmake.exeが確実)
正常に sys_wait() が回っていれば、ESC キーでDOSに戻るはずです。 ESC のチェックは、sys_wait() 内で行っています。
ワンダーウィッチとのキーの対応は、カーソル上下左右/テンキー2468 → Y方向キーです。
アルファベットのXSDE → X方向キー
ENTER → A
右SHIFT → B
SPACE → START
なお、大掛かりなサンプルとして、「親父王」が入れてあります。 性能や、その他の参考にご覧ください。
親父王はアセンブラで作られているので、 アセンブラからの使用のサンプルとしてもご覧ください。
wssimsam.lzh は大きいので、サンプルがひとつだけ、wssim.lzh にも 入っています。
重要なTIPSのある関数には、◎のマークがついています。
その先のリンクの説明は必ず目を通しておいてください。
画面BIOS
- DISPLAY_CONTROL
- DISPLAY_STATUS
- FONT_SET_MONODATA
- FONT_SET_COLORDATA
- FONT_GET_DATA
- FONT_SET_COLOR
- FONT_GET_COLOR
- SCREEN_SET_CHAR
- SCREEN_GET_CHAR
- SCREEN_FILL_CHAR
- SCREEN_FILL_ATTR
- SPRITE_SET_RANGE
- SPRITE_SET_CHAR
- SPRITE_GET_CHAR
- SPRITE_SET_LOCATION
- SPRITE_GET_LOCATION
- SPRITE_SET_CHAR_LOCATION
- SPRITE_GET_CHAR_LOCATION
- SPRITE_SET_DATA
- SCREEN_SET_SCROLL
- SCREEN_GET_SCROLL
- SCREEN2_SET_WINDOW
- SCREEN2_GET_WINDOW
- SPRITE_SET_WINDOW
- SPRITE_GET_WINDOW
- PALETTE_SET_COLOR
- PALETTE_GET_COLOR
- LCD_SET_COLOR
- LCD_GET_COLOR
- LCD_SET_SEGMENTS→◎
- LCD_GET_SEGMENTS→◎
- LCD_SET_SLEEP→◎
- LCD_GET_SLEEP→◎
カラーライブラリ→◎
- wwc_get_hardarch();
- wwc_set_color_mode();→◎
- wwc_get_color_mode();
- wwc_palette_set_color();→◎
- wwc_palette_get_color();
- wwc_font_set_colordata();→◎
- wwc_font_get_colordata();→◎
- wwc_clear_font()→◎;
テキストBIOSの一部(カーソル系はごっそりありません)◎
- TEXT_SCREEN_INIT
- TEXT_WINDOW_INIT
- TEXT_GET_MODE
- TEXT_PUT_CHAR
- TEXT_PUT_STRING
- TEXT_PUT_SUBSTRING
- TEXT_PUT_NUMERIC
- TEXT_FILL_CHAR
- TEXT_SET_PALETTE
- TEXT_GET_PALETTE
- TEXT_GET_FONTDATA
- TEXT_SET_SCREEN
- TEXT_GET_SCREEN
タイマBIOSの一部
キーBIOSの一部
- KEY_PRESS_CHECK →◎
- key_wait()(Cから呼び出せる関数)
システムBIOSの一部
その他の関数
- mmap() →◎
サウンドBIOSと、バンクBIOSはありません。 wssim.h には、一応「何もしない」サウンドBIOSが定義だけされています。 足りないBIOSの対応要望や、私のひまな時間が多くあれば、 どんどん対応を増やしていこうと思います。
ターボCからWSSIMを使用するには、以下のようにします。
- 必要なファイルはwwitch環境にコピーしてしまうのがいいでしょう。
c:\wwitch に環境があるなら、 wssim.h , wssin2.h , wssim.inc , wssimt.inc → c:\wwitch\include にコピーしてしまう。
ws_start.obj → c:\wwitch\lib にコピーしてしまう。
wssim.lib , wssimt.lib → c:\wwitch\lib にコピーしてしまう。
ついでに、include 以下/lib以下は全部読取専用ファイルにしとくと事故が減っていいでしょう。
- wssim.h をインクルードします。
#include "wssim.h"
- wssim2.h もインクルードするといいかもしれません。
これは wssim.h と違って必須ではありません。
wssim.h 内で定義されている、WSSIMの関数群は、必ず wssim_〜 で始まる名前で定義されています。
wssim2.h では、それをwssim_ をつけずに使用できるように #define しています。
どういうことかは、wssim2.h を見れば分かると思います。
wssim2.h を覗いてみて、「これはイラン」と思ったらinclude しなくてもよいでしょう。- tcc でリンクまで行わないようにします。
以下のようにコマンドラインからコンパイラを呼んではいけません。
tcc main.c c:\wwitch\lib\wssim.lib
この呼び方では、tcc は、中身的に以下のような手順を踏みます。
これでは、WSSIM用のスタートアップがリンクされません。
- main.cをコンパイルして、main.objを作る
- main.objをtlinkに与えて、EXEを作る
その際、c:\wwitch\lib\wssim.libをtlinkに与える。
それと、標準のスタートアップルーチンを使用するようにtlinkに与える- めでたく main.exe が出来た。
この問題を解決するには、以下のように、コマンドラインから直接リンカを起動します。
tcc -c main.c
tlink c:\wwitch\lib\ws_start.obj+main.obj,main.exe,main.map,c:\wwitch\lib\wssim.lib+c:\wwitch\lib\libww.lib
これではコマンドラインが長すぎるので、@とファイル名でリンク指示ファイルを作るのが良いでしょう。
tlink @linkfile.emu
linkfile.emu の内容
c:\wwitch\lib\ws_start.obj+main.obj
main.exe
main.map
c:\wwitch\lib\wssim.lib+c:\wwitch\lib\libww.lib
ver 0.7cから、正しく ws_start.obj をリンクしていないと、 リンクが成功しない(WS_WSSIM_DSEG_IDが無い!とtlinkに怒られる) ようになりました。tcc でリンクまで行うと、この状態になります。 tcc からリンクせず、tlink を明示的に自分で呼んでください。
具体的な技法はサンプルを参考にしてください。
makefile とか、make とか??という人は、この機会にmakeぐらいは使えるようになりましょう。- コンパイル時に、_WSSIM を定義するかどうかで、ソース内の記述を振り分けるのがいいでしょう。
tcc -D_WSSIM -c main.c
この辺は好みが別れるところですので、うまく気に入るようにやってみてください。
main.c の方では、
#ifdef _WSSIM
#define WS_NO_TEXTBIOS
#include <wssim.h>
#include <wssim2.h>
#else
#include <sys/fcntl.h>
#include <sys\bios.h>
#include <sys\libwwc.h>
#endif
こういう風にする。
あまり、こういう風なスタイルを使ったことがなく、あまりこだわらない。 という方は、makefile から、linkfile、#ifdef〜 などの振り分け方など、 WSSIM サンプルをまんまパチッてくるのがいいと思います。
makeの基本、linkfileの例など、初心者にはいい見本になると思います。
一般のアセンブラからWSSIMを使用するには、以下のようにします。
アセンブラでWSSIMを使用する方は、あるていどのスキルがあり、 あまり私のほうからあーだこーだ言わなくても、 うまくリンクして使ってくれるものだと信じます。(自分勝手?)
- wssim.inc をインクルードします。
ここには、BIOS呼び出しの定義、サブルーチンの定義などが行われています。
テキストBIOSを使用する場合は、wssim2.inc もインクルードします。
- 場合に応じて、BIOSを呼びます。
具体的なリファレンスは、この先を見てください→◎- リンク時、wssim.lib もリンクします
テキストBIOS使用時は、wssimt.lib もリンクします。
スタートアップには、 ws_start.obj をリンクします。c0wwjpn2.obj 相当です。
ws_start.obj をリンクせず、wssim.lib がリンクされると、リンクが通らないです。
以下に、さまざまな注意事項を記します。
分からない!や、走らない!場合に、参考にしてください。
- スタートアップ
スタートアップは、ws_start.obj を使用します。上の説明を読んでリンクしてください。
c0wwjpn2.obj 相当のものです。スタックは0xe00バイト、DS != SS になるようにしてあります。
未初期化セクションを0で埋めていません。未初期化のグローバル変数は0 で埋まってなくても動くようにしておいてください。(これは私の手抜きですゴメン)
_main が near call されますので、アセンブラの人も、_main を定義して、 そこからプログラムをはじめてください。
- コンパイラ
C言語には罠がいくつかあります。WSSIM にして動かなくなる罠はいくつかあります。 逆にWSSIM で動いていて、実機で駄目になるケースもいくつかあります。
そういう時は、以下のことをチェックしてみてください。
- ヘッダ
ターボCは、プロトタイプのない、未定義の関数を、適当に解釈して、 コンパイルしてしまう悪癖があります。
たとえば、以下のコードは思うように動かないことがあります。 (必ずかもしれない!?)#include <sys\bios.h>この場合、きちんとファイルが存在しても、mmap() に失敗するのです。
#include <stdio.h>
#include <stdlib.h>
extern void game( char far *p );
main()
{
char far *p = mmap( "/rom0/data" );}
if( p == NULL ) return 1;
game( p );
解消するには、#include <fcntl.h> すること。
すなわち、mmap() が未定義でも、コンパイラが適当に呼び出しコードを生成し、 思うとおりに動作しないコードを作ってしまいます。
まずは、きちんと必要なヘッダを全部入れているか?を疑いましょう。- ポインタ
静的に定義した配列へのポインタがFAR POINTER になると、 FreyaOSはそのポインタを解決できません。MS-DOSは解決できますので、WSSIM で動作し、実機で動作しない原因になります。
たとえば、以下のような書き方です。
char far *pointer = "STRING";この場合、pointer に、"STRING"のセグメントを代入するのは、DOS環境では MS-DOS が行っていますが、FreyaOS にはその機能がないので、出来ません。
これをソースデバッッギングでチェックするのは至難の業でしょう。
WSSIM サンプル内にある、ExeToBin.exe を使えば、EXE ファイル内のリロケーション情報が、スタートアップ内にあるものだけかを調べますので、 Exe2Bin → mkfent する際、これを使用するのを強く薦めます。 (ただし32ビットアプリケーションです)- スタック
スタックがあふれていると、まったく意味不明に誤動作します。
その症状はここでは一概にかけません。
sys_wait()内でのWSSIM エミュレーションコードがスタックオーバーフローなど、 起こしてしまうことも考えられます。- セクションサイズ
WSSIM の関数の多くは_TEXTではなく、別のセグメントにあります。
あまり64Kぎりぎりに作ると、libww.lib(実機用ライブラリ)をリンクしたときに、 64Kを超えてしまうこともあります。(libww.libのライブラリは、大体が_TEXTに ある。)- VSYNCの待ち方
VSYNCを待つ動作は、システムBIOSのSYS_WAITを呼びます。
Cなら、sys_wait() 関数を呼びます。
他の方法でVSYNCを待たないでください。
システムBIOSの、SYS_WAIT の内部で、液晶画面のエミュレーションと、 キーボード読み出しを行います。したがって、SYS_WAIT しないと、 画面がまったく変わりません。キー入力も受け付けられません。
必ず定期的に sys_wait() するようにしてください。
たまにVSYNC待ちもせず、sys_wait() もせず、単純なループでタイミングを取っているひとがいるようですが、 そういう作り方はこの機会にこれからはしないようにしましょう。
VSYNCって何?という人は、WSSIMを使用する前に、実機でVSYNCの何たるかを勉強したほうがいいでしょう。- VSYNCの速度、マシンの速度
VSYNCの速さが、なんとなくVGAとワンダーウィッチで違う気がします。 その辺は実機と合わないものだと思って開発中の調整を行ったほうがいいでしょう。
なお、ビデオカードによっては、フルスクリーンでない場合はVSYNCを正常に待てないことがあるかもしれません。 VSYNCは、昔の標準VGAのI/Oポート読み出しを使用して待っています。 また、単純にCPUの速さがワンダーウィッチとWindowsマシンではぜんぜん違うので、 Windows側で重たくないからといって本気を出し切ると、 ワンダーウィッチではくそ重たいということになりますので注意。- テキストBIOS全般の挙動
テキストBIOSは、ドキュメントがいまいちで、正確な挙動が分かりません。 もしかしたら実機と違う動作になるかもしれません。 その際は、ご連絡いただければ、即座に修正いたします。 もちろんカラーモードでテキストBIOSは使えません。(これはWSSIMが悪いわけではないのであしからず)
- テキストBIOSのライブラリ
v0.7f から、テキストBIOSのライブラリファイルをwssim.libとは別に分離しました。
常に漢字フォントのデータをリンクするのが無駄だと思ったからです。
テキストBIOSを使用する場合は、wssim.libと、wssimt.lib を両方ともリンクしてください。
なお、Cの人は、wssim.h を#includeするまえに、
#define WS_NO_TEXTBIOS
として、WS_NO_TEXTBIOSを定義しておくと、wssim.h からテキストBIOSの定義部分が、 すべて外れます。テキストBIOSを呼ばないことが分かっている場合は、 こうしておくほうがいいかもしれません。- フォントの形状
漢字のフォントは流しっぱなしで作成したので、とても汚いです。 愛敬だと思って許してください。
- 軌道直後のVRAM、パレット
起動直後のスクリーンメモリの内容は、MegやGEDのものと同じではありません。 起動直後は画面の初期化などはきちんと行わないといけません。(手抜きできません)
テキストBIOSで文字を書くだけの際でも、パレット設定などはきちんと行わないといけません。 (ワンダーウィッチ実機と表示が変わってしまいます)
Meg起動直後のパレットなどをそのまま使うアプリケーションは設計的に問題があるとおもいますので、 こちらではわざわざ合わせません。 (WSSIMが合わせても、必ず将来ほかで問題になるはずです)
この機会に、必ず画面、パレットなどのリソースは初期化するようにしましょう。
- デバッガでの注意
カラー化に従い、VGAの標準部(MS−DOSなどが表示に使っている部分) のパレットも使用してしまいます。SYMDEBなど、DOSの画面をそのまま使うデバッガを使う場合は、 パレット番号0のカラーは注意して設定しないと、 デバッガの文字が読めなくなってしまいます。特にパレット番号0は重要です。 パレット0は文字列(たとえばゲームでなら得点表示)などに使用し、 デバッガでも相性のいい色にするのがいいでしょう。
- libww.lib のリンク
FreyaOSを呼び出す処理はもちろんすべて動きませんが、 libww.lib をリンクしないと使用できない便利な関数がいくつかあるので、 とりあえずlibww.lib もリンクすることになると思います。
ただし、その際、FreyaOSを呼ぶような処理、デフォルトのILを使用するような処理がくると、 DOSではハングアップしたり、画面が壊れたり、 WindowsのDOS窓が閉じさせられたりいろいろな悪い症状がでます。 libww.lib 内の関数は注意して呼んでください。 (さしあたって、sprintf() は大丈夫みたいです。多分 string.h の関数群も大丈夫でしょう。)
sys/process.h , sys/service.h など、濃い定義が #define で設定されているので、 これらのコードを混ぜてもコンパイルが通ってしまうことがあります。 もちろんそれを実行するとハングアップしたりします。その辺特に要注意!!!!!
(procIL->_yield() 等)- 漢字コードの差異に関して
持っている漢字フォントのコードの範囲が実機と違うかもしれません。 WSSIM で表示された文字コードが、実機では表示されないということがあるかもしれません。
逆に、実機で表示できる文字が、WSSIM では表示出来ないこともあるかもしれません。
一応第1水準などの標準的に使われるコードはサポートしています。
すごく難しい第2水準の漢字や、罫線などはだめかもしれません。
0x00〜0x1fの記号は正しく出るはずです(マニュアル見ながら私が手で打ち込みました。)
- LCDでしか意味を成さないBIOSに関して
以下の関数は、次のようになっています。
LCD_SET_SEGMENT
縦持ちLCDと、横持ちLCDとのビット値に応じて、WS_SET_SCREEN_MODE_VH が呼び出されます。それ以外のビットは無視されます。WS_SET_SCREEN_MODE_VH の説明はこの先を見てください→◎LCD_GET_SEGMENT
WS_SET_SCREEN_MODE_VH の呼び出し状況に応じて、0x02 か、0x04 かのどちらかを返します(縦LCDがON か、横LCDがONかどちらか)LCD_SET_SLEEP なにもしない
LCD_GET_SLEEP つねに0を返す
- KEY_PRESS_CHECK に関して
従来のバージョン(0.7d以前)の WSSIM では、キーの更新に sys_wait() をおこなう必要があったため、 以下のようなコードはハングアップしてしまっていました。
while( !key_press_check() ) ;こういう記述を許すために、KEY_PRESS_CHECK が、sys_wait() がくる前に300回呼ばれたら、 内部的に sys_wait() の処理をおこなうように修正しました。 これにより、上のようなコードがきてもキーを受け付けなくなることがありません。
ただ、VSYNCを明示的に待たない作りのプログラムスタイルは、 将来ほかの環境で破綻するんではないかと思いますので、(私の主観ですけど) この機会にこれからは以下のように書くようにしましょう
while(1){
if( key_press_check() ) break;}
sys_wait(1);
- mmap() 関数に関して
mmap() 関数は、関数内部でMS-DOSのシステムコールを呼び出し、 対象のファイルを WSSIM の持っているメモリに読み出します。 したがって、以下の制約&実機との違いがあります。
- mmap() の呼び出し時点で、ディスクからファイルを読みます。 そのため、帰ってくるまで時間がかかることがあります。
- 与えるファイル名は、その時点でのディレクトリのMS-DOSのファイル名です。 もちろん /rom0 とか、FreyaOSのファイルシステムの名前を渡しても開けません。 #ifdef 等でファイル名を振り分けてください。
- もちろん fx を開くと、fx のヘッダをデータとみなしてそこのポインタを返します。 mkfent 前のファイルを使ってください。
- WSSIM 内部のバッファは 0x2a000 バイト準備されています。 mmapするファイルサイズの合計がそれ以上になるとエラーになります。
mmap関数の仕様上、一回mmapして確保してしまったバッファを開放する手段はありません。 どんなにDOSのコンベンションナルメモリに余裕があっても、あまったメモリを全部使い切るようなことはしません。 必ず 0x2a000 バイトです。(手抜きでごめんなさい)
mmap() 関数がリンクされるだけで、出来上がるEXEにこの分のファイルサイズが付加されてしまいます。 環境によっては、メモリ不足で起動できなくなるかもしれません。 (一応、うちのWin98(530K MS-DOSでフリー)なら、大丈夫なようです。)
0x2a000 に深い意味はありません。もっと多くてもいいようなら、多くします。- 帰ってくるFAR POINTER のオフセット部分は必ず0で帰ります。 もしも実機の mmap がそうでない場合、このオフセット部を必ず0で返すために正常動作していたコードが、 走らなくなる可能性があります。この辺は十分に注意してください。
- SYS_GET_TICK_COUNT
WSSIM が初期化された際、MS−DOSの時計から適当な値に内部カウンタを初期化し、 そのあと sys_wait() のたびに+1していく値を返します。
- SYS_GET_OWNERINFO
常に同じ値(作者のプロフィール)を返します。
- SYS_GET_VERSION
SYS_GET_VERSION は、WSSIM では、0xaaaa を返します。
恐らくこの先もあらゆるリリースのFreyaOS でこの値を返すことはないと私が勝手に判断しました。 この返り血を使用すれば、実機で走っているのか、WSSIM で走っているのかランタイムで判別することが出来ます。
デバッグに便利なことがあるかもしれません。- RTC_SET_DATETIME
RTC_SET_DATETIME は、WSSIM では、時刻を設定しません。(つまりなにもしない)
Windowsマシンの時刻を再設定してしまうのは行儀が悪いという判断から、 あえてそうしました。- カラーライブラリ全般
_TEXT セグメント内に入れてあります。
libwwc 実機用のライブラリでの関数の実体が、どこのセグメントにあるのかはわかりませんが、 一応こうしておきました。- wwc_set_color_mode()
libwwc.h に定義されている以外の値では、何も変更されません。
- wwc_palette_set_color()
白黒モードで呼ぶと、何もしないで帰ります。
パレット番号、カラー番号を正しく設定していないパラメータを渡すと、 どうなるかわかりません。 特に、4色カラーモードで4以上のカラーインデックスを渡した場合。- wwc_palette_get_color()
白黒モードで呼ぶと、常に0を返します。
- wwc_font_set_colordata()
白黒モードで呼ぶと、何もしないで帰ります。
4色カラーモードで呼ぶと、何もしないで帰ります。
wwc_font_get_colordata()も同様です。- wwc_clear_font()
何モードで呼んでも、正しくフォントをクリアします。
wwc_get_hardarch() が、白黒スワン状態でも、正しくクリアします。
WSSIM にだけあり、wwitch実機にないサブルーチン/関数の解説です。
- WS_BIOS_EXIT
void far wssim_exit(void);
ここへ飛ぶと、DOSに戻ります。
ワンダーウィッチの int 10h の代わりに使用してください。 一応、_main から、リターンしてもDOSに戻るようにはしてあります。
間違っても、MS−DOSの ah=4c int21h は、行わないように!- WS_SET_RASTER_SCROLL
void far wssim_set_raster_scroll( int sw,int line,int sc1x,int sc1y,int sc2x,int sc2y );
ラスタスクロールエミュレーションを設定します。
ahに、スイッチ、alに設定するライン番号、bx,cxに、SCREEN 1 の再設定座標 dx,siに、SCREEN 2 の再設定座標をいれて呼びます。
ah=0なら、そのラインでのラスタスクロール設定を解除、 ah=1なら、そのラインでのラスタスクロール設定を設定します。 bx や cx が0xffffなら、そのラインではそのBGのスクロールは再設定しません。 al=0xff,ah=0 なら、すべて解除します。
とりあえず、そのラインで再設定できるのは、スクロール量だけサポートしました。 ワンダーウィッチでは、ほかの表示パラメータを再設定するほどのことはそんなにないだろうという、 私の主観でこうしました。
この機能を使うと、実機でのラスタスクロール動作は、 完全に自分で別に作成しなければいけません。 実機でラスタスクロールさせるプログラムが作れない人は、 この機能を使用しないほうがいいでしょう。- SET_BIOS_KEY_PUSH_MODE
void far wssim_key_push_mode( int flags );
al に、PCのキーボード入力のキューへの入力をを捨てないかどうかのフラグをいれて呼びます。
初期状態では、v0.7g以前ではal=0 , v0.7h以降はal=1で設定されます。
alのbit0=0の状態では、キーボード入力は、ワンダーウィッチのキーBIOS に無関係な部分では捨てられます。 そのため、デバッガでブレークしたりした場合、キー操作が利かなくなっています。
alのbit0=1にして呼び出すと、キー入力は捨てられませんが、DOSのオートリピートのキーバッファが いっぱいになると、DOSの中で重たくなったりするかもしれません。
alのbit1=0にすると、ESCキーで常に終了する機能が有効です。
alのbit1=1にすると、ESCキーで常に終了する機能が禁止されます。
適宜選択して設定してください。- WS_TERMINAL_PRINT
void far wssim_terminal_print( int x,int y,char far *message,int fc,int bc );
ds:dx からの文字列を、(cx,dx)の仮想ターミナルの位置に、 文字色 bl , 背景色 bh で書きます。
\0まで出力します。
液晶部の外に表示しますので、デバッグ中の画面を汚しません。
仮想ターミナルは、通常の横モードで50桁、8行あります。
縦モード1なら、33桁、28行あります。
縦モード2では、表示が行われません。
横モード、縦モードの詳細はこの先
VSYNCを待たず、その場で書きますので、表示は信頼できます(キャッシュされたりしません)
bh,blの色は、以下のようになっています。16色カラーモードの場合、 カラー番号はワンダーウィッチに設定したカラーパレットそのもの (上4ビット=パレット番号、下4ビット=カラー番号)になります。 したがって、ワンダーウィッチのアプリケーション次第で何色に見えるかが変わってきます。 適当に見やすい色を選択してください。
- 0x00 ■ 黒
- 0x01 ■ 赤
- 0x02 ■ オレンジ
- 0x03 ■ 黄色
- 0x04 ■ 明るい緑
- 0x05 ■ 黄緑
- 0x06 ■ 青緑
- 0x07 ■ 間全他
- 0x08 ■ 青
- 0x09 ■ 濃い青
- 0x0a ■ 濃い紫
- 0x0b ■ 紫
- 0x0c ■ ピンク
- 0x0d ■ 暗いグレー
- 0x0e ■ 明るいグレー
- 0x0f ■ しろ
- 0x40〜0x43 パレット0液晶色
- 0x44〜0x47 パレット1液晶色
- 〜0x7f それ以降の液晶色
- 0x50 液晶のボーダーカラー
- それ以外 どう見えるか保証なし
0x00,0x10 のような、LCDには絶対表示されない色を使用するのもお勧めです。
全角文字は書けません。\nなどの特殊な文字も表示できません。 英小文字は、大文字にされます。Cのprintfなどのように、 %〜の書式変換のようなものもまったくありません。void near wssim_wwc_set_hardarch_mono(void)
エミュレータが、カラーのエミュレーションを行わず、 古いモノクロ液晶のワンダースワンになります。
これをmain()の頭で呼んでおくと、そのあと、wssim_wwc_get_hardarch() では、0が帰るようになります。(モノクロワンダースワンとみなされる)
両対応のソフトを作るときのチェックに使用します。 もちろん実機にこんな関数はありません。- WS_LOADFILE
WS_SAVEFILE
int far wssim_loadfile( char far *filename,void far *buffer,int count );
int far wssim_savefile( char far *filename,void far *buffer,int count );
ds:dx のファイル名のファイルを、es:si に、cx バイト数分読み書きします。 stdio のように、ファイルを開いて戻ってくるのではなく、 読み出し(書きこみ)を関数内で終わらせてファイルを閉じて戻ってきます。
ax に0以外が戻ってくれば、エラーです。
単純なゲームのハイスコアなどを読み書きする分にはこれで十分だろうと思います。
実際のワンダーウィッチ上では、下のサンプル関数で置き換えてください。サンプル関数:なぜこんな関数を準備して、FreyaOSのファイルアクセス関数をエミュレーションする関数を、 作らないかというと、FreyaOSのファイル関数は挙動不審で、しかも固まりやすいので、 あまりエミュレーションしたくない(つまり、使いたくない)のでした。 (挙動のチェックのために実機でファイルアクセスしなければならないし…)
WS_LOADFILE,WS_SAVEFILE は、Cで書くと以下のような動作を内部的に行っています。
ただし、creat などのファイル終端に関する制約がMS−DOSにはないので、 WS_SAVEFILEは、下の sample_savefile() と必ずしも同じ動作をするとは限りませんので注意! (特に save の場合は、サイズを128の倍数にするのが無難です。FreyaOSはこの辺すぐ固まるので)
WS_LOADFILE: static void sample_loadfile( char far *fname,char far *buffer,int size )
{
int c;}
FILE *fp;
fp = fopen( fname,"rb" );
if( fp == NULL ) return;
for( c=0; c < size; c++ ) buffer[c] = fgetc( fp );
fclose(fp);
WS_SAVEFILE:static void sample_savefile( char far *fname,char far *buffer,int size )
{
int fd;}
int c;
FILE *fp;
if( size & 127 ){
size |= 127;}
size++;
fp = fopen( fname,"wb" );
if( fp == NULL ){
fd = creat( fname,0,size/128 );}
if( fd != E_FS_SUCCESS ) return;
fp = fopen( fname,"wb" );
if( fp == NULL ) return;
for( c=0; c < size; c++ ) fputc( buffer[c],fp );
fclose(fp);
ごめんなさい。- WS_SNAPSHOT_SCREEN
int far wssim_snapshot_screen( char far *filename );
今の画面を、ds:dx で示す MS−DOSのファイル名で、 ビットマップファイルに出力します。224x144の24ビットの無圧縮BMPを作成します。 もちろんファイル名は8文字3文字のDOSのファイル名です。
エラーが出たら、ax に0以外が帰ります。ただし、ディスク容量が足りない場合は、 ax=0で帰り、ファイルが途中までしかできていません。
LCDが縦モードでも、横に見た場合のBMPを作りますので、 出力後おのおので90度まわして使用してください。
- WS_LCD_VGA_PALET
void far wssim_lcd_vga_palet( WS_LCD_VGA_COLORS far *colors );
LCD濃度に対応するVGAのパレットを設定します。
1バイトずつ、rgbと並べ、おまけに1バイト0をつけた、4バイトのカラーのデータを16個並べておいて、 それのアドレスを ds:si に入れて呼びます。
Cの構造体が分かる人は、wssim.h の WS_LCD_VGA_COLORS を見てくれれば分かると思います。
RGB各々の値は、0〜63まで有効です。
デフォルトの緑っぽい液晶エミュレーションのコントラストが、気に入らない場合などは設定するといいでしょう。
この関数で指定した色は、モノクロモードでのみ有効です。カラーモードでは無視されます。- WS_SET_KEY_TABLE
void far wssim_set_key_table( char far *table );
int far wssim_keycode_sc( void );
キーボード読み出しの際、どのキーがどのワンダーウィッチのボタンに相当するかのテーブルを、 上書きします。
デフォルトのキーボードの配置が気に入らない場合は、これで調整してください。 ただし、入力の数値はキーボードのスキャンコードと呼ばれる値で、 どのキーがどの値に対応するのかは自分で調べてください。
ds:si に、そのテーブルのアドレスを与えて呼びます。
si+0 Y1キーのスキャンコードスキャンコードを調べる際、最後に受け取ったスキャンコードを得る関数が、 wssim_keycode_sc() という名前で使えます。 アセンブラからなら、_wssim_keycode_sc というサブルーチンコールで al に返します。
si+1 Y3キーのスキャンコード
si+2 Y2キーのスキャンコード
si+3 Y4キーのスキャンコード
si+4 X1キーのスキャンコード
si+5 X3キーのスキャンコード
si+6 X2キーのスキャンコード
si+7 X4キーのスキャンコード
si+8 Aキーのスキャンコード
si+9 STARTキーのスキャンコード
si+10 Bキーのスキャンコード
有効なのは下位7ビットで、最上位は0なら押した(メイクコード)、 1なら離した(ブレイクコード)です。
WindowsのDOS窓の場合は、システムに関係するキーは受け取れないかも知れません。int far wssim_get_keyboard(void);
int 21h を使用して、キーボードから1文字受け取ります。
入力されたコードが帰ります。
何も押されていない場合は、すぐ帰ります。
キーのアスキーコードを返すので、デバッグには便利かもしれません。void far wssim_error_exit(char far *message);
画面にメッセージを表示して、DOSに戻ります。
DOSのシステムコールを使用するので、メッセージの最後には、$ をつけてください。
例: wssim_error_exit( "error occured!!$" );
起動時のエラーチェックなどに便利です。
環境によっては、漢字は表示できないものだと思ったほうがいいでしょう。
WS_SET_SCREEN_MODE_VH
void far wssim_set_screen_mode_vh( int mode,char far *table );
LCDを縦に表示するエミュレーションモードに設定します。
明示的に呼び出さなくても、画面BIOSの LCD_SET_SEGMENTS の中から、 LCDの表示にあわせて呼び出されます。
明示的に呼び出す場合には、AX に、以下のモードをひとつ洗濯して設定します。横モードは従来のWSSIMと同じ物です。
- WSSIM_SCREEN_MODE_VH_HORI 通常の横モード
- WSSIM_SCREEN_MODE_VH_VERT0 縦モード1
- WSSIM_SCREEN_MODE_VH_VERT1 縦モード2
縦モード1は、LCDを縦に持ったものとしてVGAに表示します。
ただし、その際、224ドットのLCDを196ドットに詰めて表示します。 (そうでないと、VGAの画面に入りきらないので)
縦モード2は、横に画面を2つ並べて、224ドット分表示します。(大変かっこ悪いですが)
縦モード1では、wssim_terminal_print の表示も縦に表示されます。 ただし、表示可能なカラム位置が、横0〜32まで、縦0〜27までと、エリアが変わっています。
縦モード2では、wssim_terminal_print は、表示が行われません。
このサブルーチンが呼び出されると、画面全体が消去されます。
ds:si には、WS_SET_KEY_TABLE と同じ仕様のキースキャンコードテーブルを渡します。
si が、NULL できた場合は、とりあえずデフォルトの値を使用します。
縦モード1で、224ドットのLCDを196ドットに詰める処理は、 単純に28ドット間引いているだけです。間引くラインは表示ごとに切り替えているので、 ちらついて見えます。(昔のファミコンなどのように見えます)
画面がインデックスカラーなので、これ以上うまい方法が思いつきませんでした。 だれかいい方法があったら教えてください。
縦モード2は、LCDエミュレーションの描画面積が大きいので、少し重たいです。
WSSIM のBIOSを、アセンブラから呼び出す場合の説明です。
wssim.inc 内に、必要な定義があります。一応、tasm でうまくいくことは確認しています。
optasm でも確認しています。masm では確認していません。
カラーライブラリは、直接 WS_SET_COLOR_MODE などの、wssim.inc の定義の サブルーチンを呼ばないでください。面倒でも、_wssim_wwc_set_color_mode などを、Cリンケージで呼んでください。
- WS_EMU_DISPBIOS
画面制御BIOS
ahに機能番号を入れ、far call します。
その他のレジスタは、機能次第で設定します。 戻り値に無関係なレジスタは保存します。 (実機がどうだか分からないので、保存されないものと思ったほうがいいでしょう)
マクロ_DISPBIOSを使用するのがいいでしょう(将来のWSSIMのバージョンのため。) また、equ で実機用とWSSIM用の環境を楽に切り替えるためにも。- WS_EMU_TEXTBIOS
テキストBIOS
詳細は、画面制御BIOSと同じです。 マクロ名は、_TEXTBIOSです。
これだけは、wssim.inc の定義ではなく、wssimt.inc の定義です。- WS_EMU_RTCBIOS
タイマBIOS
詳細は、画面制御BIOSと同じです。 マクロ名は、_TIMERBIOSです。
- WS_EMU_KEYBIOS
キーBIOS
詳細は、画面制御BIOSと同じです。 マクロ名は、_KEYBIOSです。
- WS_EMU_SYSTEMBIOS
システムBIOS
詳細は、画面制御BIOSと同じです。 マクロ名は、_SYSTEMBIOSです。
- WS_EMU_SOUNDBIOS
サウンドBIOS
この関数は、ありません。呼び出すとリンクでエラーにされます。 マクロ名は、_SOUNDBIOSです。
マクロはありますが、呼び出しても何もしません。
例:
push COLOR_MODE_16COLOR
call _wssim_wwc_set_color_mode
pop ax
最近更新していません。
DMCとかいう奴が流行ってるみたいなので、それで使えるかどうかのテストや、 それなりの対応でもしようかなぁ・・・。
プログラム&ドキュメント作成 ABS Systems.
- ご意見ご感想バグなどは、abs@mail.jcss.net あるいは、 http://www.jcss.net/~abs/ の掲示板まで。 できる範囲で対応させていただきます。
- わたしはこのBIOSをサポートしてくれないと足りない的な、 リクエストも適宜受け付けています。出来る範囲でサポートします。
- このプログラムを転載、その他コピー等することに関して、私 ABS Systems. ではまったく制限を加えません。
- 転載、コピーなど、ワンダーウィッチの制限の許される範囲内で、 ご自由に行っていただいて結構です。(私自身はうるさいことは言わないつもりです。)