レス数が1スレッドの最大レス数(1000件)を超えています。残念ながら投稿することができません。
おちゃめくらぶ掲示板
-
プチコンでマルチタスクOS PART2
プチコンでマルチタスク、マルチウインドウのOSもどきのプログラムを作る場合には6月25日に
書いたようにまずはGRP面が4面では全く足らないにょ。
ただし、これは逆に言えば4面で収まる範囲内であれば作れるということも意味するにょ。
つまり、開いているウインドウの合計サイズが256x192以下になればいいということだからね。
ということで、即興で最低限の機能のみを作ったPetit OSだけどその続きを仮に作る場合は
他にどのような問題があるのか、どうやって実現させたらいいのかということについて
書いていくことにするにょ。(以下、「OSもどき」を「OS」と記述)
さて、まずはマルチウインドウを実現するためには重なった部分をバッファに入れていく
ことになるにょ。
別にバッファに入れなくても重なっているウインドウを常に下から順に全部表示していけば
いいのだけどそんなことをしたら何も動作をしていないウインドウをドラッグするだけでも
30fpsを下回る可能性さえあるにょ。
これがバッファに入っている部分だけ再描画するならばウインドウをドラッグする際の描画
速度は数倍にアップするにょ。
そして、ウインドウ用バッファだけではなく表示用バッファも必要になるにょ。
マルチタスク、マルチウインドウを実現するためには直接画面表示するわけにはいかず
一端表示用バッファ(要するに仮想画面)に描画したあとにそれを実画面に転送することが
必要になってくるにょ。
そうしないと管理が複雑になりすぎて実用にならないからにょ。
それだけでなくコンソール表示(テキスト表示)は基本的にキャラ単位でないと表示する
ことができず、マルチウインドウに対応して自由にウインドウをドラッグなんてことは実現
できないにょ。
コンソール表示だけならばBG画面を用いればマルチウインドウ対応にすることは可能だけど
その際も自由に使えるのは2面だけになってしまうにょ。(その代わり1つのウインドウは
512x512ドットまで可能になる)
表示用バッファを用意することでマルチウインドウ処理は簡単になるのだけどそれでも
マルチタスク、マルチウインドウに対応させるためには下記のような6つの重要な問題を
抱えているにょ。
(1)マルチウインドウのバッファ管理
(2)事実上グラフィック用命令以外は使えない
(3)事実上BGMPLAYは使えない
(4)ウエイトや一時停止を行う命令は使えない
(5)コンテキストスイッチの保存
(6)ラベル名、変数名の重複回避
(1)のみOS側の問題であとはアプリを作る際の問題となるにょ。
(1)合計で256x192となる最大バッファサイズを分割して管理することになるけどそれを
どのように割り当てて行くかということが問題にょ。
これがウインドウサイズが固定で128x96のようにキリの良いサイズだと単純に4分割して
それを割り当てればいいけどこれがサイズの異なるウインドウだとうまい具合に大きい
ウインドウから順に開いていってくれれば開いたサイズに割り当てを行うのは難しく
ないものの順不同で開いていくならば残りバッファサイズは十分なのに後から大きい
ウインドウを開けばバッファサイズが不十分になってしまう場合があるにょ。
これはバッファの断片化が起きるためにょ。
これは断片化解消ツールを作れば改善可能なので問題ないにょ。(リアルタイムで
この処理を行うことも可能だけど処理速度の大幅な低下を招いてしまうので実用レベルに
達しないだろうし、下記のダイレクトモード以外だとバッファを整理するための作業エリアの
確保ができないため実現が難しい)
ウインドウは今のところシステム変数としてSCREENX、SCREENYを用意してそれを元に起動時に
ウインドウサイズを決めているけどこれは可変式にすることも可能にょ。
唯一のアプリである「CAVE」は可変式に対応しており、描画される穴の幅などはウインドウ
サイズによって変化するにょ。
アプリの再起動によって変化させるだけではなく原理的にはWindowsのようにドラッグに
よってリアルタイムでウインドウ幅を変化させることもできる(単にSCREENX、SCREENYの
値を変えるだけでいい)けど上記の断片化問題を考えると厳しそうにょ。
(2)表示バッファから実画面への転送はGCOPYを使う都合上、表示バッファの描画はGRP面のみ
有効になるにょ。
つまり、マルチウインドウ処理が容易になる代償としてコンソール、スプライト、BGを使った
描画はできないということにょ。
表示を行う場合はグラフィック命令を用いるか、コンソール、スプライトキャラを表示する
場合はGPUTCHRで描画していく必要があるにょ。
それに加えて表示バッファの割り当てをOS側で行っているためバッファのGRP面に描画する
場合もその仮想画面の座標に描画しないといけないにょ。
例えば96x64のウインドウを(128,96)を起点としたバッファが確保されておりその上に
描画する場合は座標(0,0)がバッファ上の(128,96)に相当し、仮想画面の右下である
(95,63)が(223,159)に相当するにょ。
これを実際にプログラムを作る際に計算して作るのはかなり大変にょ。
まぁ、描画専用のAPI(というかサブルーチン)を用意してそれを経由して描画することで
自動的にOS上で割り当てられたバッファ上に描画するということも考えているけどかなり
面倒臭そうにょ。(機能を実装するのは簡単だけど実際にアプリを作るのは面倒)
(3)音楽を鳴らす場合は各ウインドウで独立して制御する必要があるにょ。
BGMPLAY命令では8チャンネルまで対応しているため最大ウインドウ数が8個ならば各
ウインドウに1チャンネルずつ割り当てれば鳴らすことはできるにょ。
ただし、それはバックグラウンドに移ったウインドウで鳴らしている音を鳴らし続けた
場合には同時発音数の問題で難しいにょ。
かといって、バックグラウンドに移ったゲームで使用されている音楽を停止した場合には
ウインドウを前面に持ってきた際にBGMを再び続きから鳴らすことは現在のBGMPLAY命令
ではできないにょ。
つまり、「BGM再生→BGM停止→BGMを停止箇所から再生」を行うためには音階演奏
プログラムを自前で用意するしかないにょ。
まぁこれはOMPがあるから何とかなるけどね。
(4)そして、マルチタスクに対応させるためにはアプリへの時間の割り当てが問題となるにょ。
WAITやVSYNCでそのアプリを一定時間停止してしまうとマルチタスク処理を行う場合には
他のアプリまで影響が出てしまうためアプリ内でそういう命令を使うことはできないにょ。
OSは60fpsでの動作を前提としているため30fpsのゲームを作る場合には2回に1回実行すれば
良いという感じだけど実際は処理落ちを起こしているということも想定しておかねばならない
ためにMAINCNTLのカウンタを用いて2フレームに1回処理するというように組む必要が
あるにょ。
あとINPUTなどの一時停止が行われる命令は使用することができないにょ。
これはINKEY$やKEYBOARDなどを用いてINPUTの代替となるサブルーチンを用意して解決する
しかないにょ。
(5)マルチタスクOSを作る場合に必要不可欠なのはコンテキストスイッチの保存にょ。
といっても、ただのOSもどきなので本来のコンテキストスイッチとは全然異なるものにょ。
私が作ろうとしているPetitcom OSにおいてアプリA、アプリB、アプリCの3つのアプリを
同時に動かす場合には下記のようになるにょ。
アプリA→アプリB→アプリC→OS→アプリA(以下略)
↑--- この間が1/60秒 --- ↑
ただし、これもアプリAからアプリBに処理が移る場合にアプリAのどの部分まで処理が
行われたのかを一端保存して再びアプリAを実行する際にはその続きから実行する必要が
あるにょ。
これがマルチタスクではなく起動しているアプリが1本ならばアプリからGOSUBでOSを
呼び出せば簡単にできるけどマルチタスクの場合は自前で実行箇所のフラグとなるものを
保存してそこにGOTOでジャンプするしかないにょ。
(6)ラベル名が重複してしまうとエラーによって実行不可能になるため事前にチェックして
おく必要があるにょ。
とはいえ、そのプログラム内で使われているラベルを調べることは手動で行わない限りは
無理なのであらかじめそのアプリで使われているラベルを書き記したデータを用意して
インストール時にチェックするしかないにょ。
アプリはAPPEND命令によって追加予定だけど追加しただけではOS上から使用することは
できないためそのアプリが追加されたことをどこかに記す必要があるにょ。
それはOS内にインストーラーを用意してそれを用いてインストール処理を実現する予定と
なっているにょ。(この方法を用いればアンインストール時はアンインストール処理を
OS上で行いAPPENDしたプログラムを削除するだけなので簡単)
その際にアプリ内にあるアイコンデータと使用ラベル一覧を呼び出しアイコンデータを
元にBG面に書き込み、ラベル一覧を元にチェックして現在インストールされている
プログラムとラベル重複がないかをチェックしてそれで使用可能になるにょ。(ラベル
重複がある場合にはインストール済みのどのアプリで使用されているのかということも
表示する)
基本的にラベルはなるべく他のアプリと被らないように先頭の数文字はアプリ名を
使ったものにする(CAVEにおける@MAINならば@CAVEMAINとする)ということを推奨
しているけどね。
次に変数の重複問題にょ。
変数の場合は配列変数で二重定義にならない限りはエラーが出ないため問題ないとも
いえるけどラベル数よりも使用する変数の数の方が多くなるだろうから厄介にょ。
そこで考えたのはA〜Zの1文字変数の疑似ローカル変数化にょ。
これによってA〜Zまでは使用変数一覧を作成することなく自由に使えるようになる(どの
アプリでもA〜Zは重複して使用可能になる)けどその代償として速度の低下を招いてしまう
ことになりそうにょ。
使用しているラベルや変数名は配列変数に入れていると同時にGRPにも書き込み、OSの
ブート時には再びそこから使用している配列変数に読み込む予定にょ。
ラベル名が16バイトx1つのアプリで50個使用、変数名が16バイトx1つのアプリで100個使用
と考えた場合には2400バイトとなり、48KBのGRPには20本分のアプリデータを保存可能に
なるにょ。(「MEM$では全く足らない」というのはこれで分かると思う)
実際はデフォで用意するアプリなんて数本だろうし、誰かが自分で追加するなんて可能性も
上記のアプリの作りにくさを考えると望みが薄そうなので48KBあればかなり余裕だけどね。
以上が「Petitcom OS」を脳内シミュレーションで動作させた場合に見つかった問題点にょ。
処理速度の問題やOSそのものの使い勝手の問題は実際に作ってみないと分からないので
「少なくとも」これだけの問題があるということにょ。
さて、これではあまりに制約がありすぎて使えないOSとなってしまいそうにょ。
そこで考えたのはダイレクトモードの搭載にょ。
マルチタスク、マルチウインドウではなくシングルタスク専用モードにょ。
このモードで動作させれば上記の制約はほぼ無くなりプチコンで用意されているほとんどの
機能が使えると同時にすでに作られているプログラムも一部の手直しをするだけでこの
Petitcom OS上で動作させることが可能になるにょ。(アイコンデータと使用ラベルデータ、
変数データを用意して、OSに復帰する処理を加えるだけでいい)
上記のインストーラーや断片化解消ツールなどはこのダイレクトモードでないと作るのが
難しいけどそれをユーザー側(一般アプリ作成側)にも開放しようというものにょ。
ただし、マルチタスク、マルチウインドウがウリとなっているためこのモードを前面に
出してしまうことは両刃の剣となってしまうのが問題にょ。
このモードは端的にいえばたくさんのプログラムをAPPENDでつなげてそれを選択実行
できるランチャー機能でしかないわけだしね。(OSっぽさを出すならばやっぱりマルチ
ウインドウでないと・・・)
したがって、マルチタスク、マルチウインドウが実用レベルになっているかということが
重要になるにょ。
まぁ実用ソフトではなくネタソフトと考えれば「マルチタスク、マルチウインドウの
OSもどき」ということでそれなりの価値はあるだろうけど作るための大変さとネタ的な
面白さを天秤に掛けると微妙なので一晩で作った試作品の続きを作る気力が失われて
しまっているにょ。
これだけ競合が多ければ目新しさも薄れてしまうだろうからね。
簡単に作れるプログラムならばさっさと完成させてもいいけど、どう考えても1週間程度
では完成しそうもないためそれなりの気力がないと駄目にょ。
それにコンテストに出すならば締め切りはまだ先なのでギリギリにならないとエンジンが
かからない私にとってはまだあわてる時間ではないしね(笑)
|
|
|
掲示板管理者へ連絡
無料レンタル掲示板