Wikibooks jawikibooks https://ja.wikibooks.org/wiki/%E3%83%A1%E3%82%A4%E3%83%B3%E3%83%9A%E3%83%BC%E3%82%B8 MediaWiki 1.39.0-wmf.23 first-letter メディア 特別 トーク 利用者 利用者・トーク Wikibooks Wikibooks・トーク ファイル ファイル・トーク MediaWiki MediaWiki・トーク テンプレート テンプレート・トーク ヘルプ ヘルプ・トーク カテゴリ カテゴリ・トーク Transwiki Transwiki‐ノート TimedText TimedText talk モジュール モジュール・トーク Gadget Gadget talk Gadget definition Gadget definition talk 位相空間論 0 8493 206675 192089 2022-08-17T08:32:43Z 126.224.122.250 wikitext text/x-wiki このページでは、位相空間に関する基本的な一般論を解説する。集合論と解析学の初歩知識は仮定するので、おぼつかない読者は[[集合論]]や[[解析学基礎]]などを参照のこと。位相空間に関するより進んだ内容は、例えば[[位相幾何学]]などにいずれ書かれるだろう。 命題にはなるべく証明を付したが、まだ書きかけの教科書なので、証明のついていない命題もある。証明は一段下げて書いたので、事実だけをすばやく知りたいときは読み飛ばすこともできるが、はじめはなるべく証明を追うべきである。また、証明のまだついていない命題に対しては、読者は積極的に自分で証明を作りながら読み進めるべきである。 == 位相空間とはなにか == 位相空間とは、集合に対して、「位相」というある種の構造を付加したもののことである。 解析学においては、点列の収束や関数の連続性といった概念はとても重要な概念であった。これらの概念はEuclid空間でしか定義されていないが、もし他の集合でも同様の概念を定義できれば、その集合上でも解析学や幾何学が展開できるだろう。位相という概念を考える動機はここにある。すなわち、Euclid空間が持っているある種の構造を抜き出して特徴づけることで、他の集合にも同様の構造を与え、同じような理論を展開しようというものである。 それでは、具体的にはどのような構造を与えることが必要十分なのであろうか。それを考える上で、次の命題が重要な手がかりとなる。 '''命題''' 実数上の関数 <math>f \colon \mathbb{R} \to \mathbb{R}</math> について、次は同値である: # f は連続関数である; # 任意の開集合 <math>U \subset \mathbb{R}</math> に対して、 <math>f ^{-1} [U]</math>は開集合である; :(証明) :1⇒2: ''f'' を連続関数、''U'' を開集合とする。<math>x_0 \in f^{-1}[U]</math>を任意にとり、<math>y_0=f(x_0)</math>とする。<math>y_0 \in U</math>であり、''U''は開集合なので、ある <math>\varepsilon>0</math>が存在して、<math>|y-y_0|<\varepsilon \Rightarrow y \in U</math>である。''f''は連続なので、この <math>\varepsilon</math>に対してある <math>\delta</math>が存在して、<math>|x-x_0|<\delta \Rightarrow |f(x)-y_0|<\varepsilon</math>である。すなわち、<math>|x-x_0|<\delta \Rightarrow x \in f^{-1}[U]</math>である。したがって、<math>f^{-1}[U]</math>は開集合である。 :2⇒1: 次に、任意の開集合''U''に対して<math>f^{-1}[U]</math>は開集合だとする。<math>x_0 \in \mathbb{R},\, \varepsilon>0</math>を任意に取り、<math>y_0=f(x_0)</math>とする。<math>U:=\{y \in \mathbb{R};\ |y-y_0|<\varepsilon\}</math>は開集合なので、<math>f^{-1}[U]=\{x \in \mathbb{R};\ |f(x)-y_0|<\varepsilon\}</math>は開集合である。すなわち、ある <math>\delta>0</math>が存在して<math>|x-x_0|<\delta \Rightarrow |f(x)-f(x_0)|<\varepsilon</math>である。よって、''f'' は連続である。// この命題からわかることは、これまで関数の連続性は「近くが近くに移る」という概念だと理解してきたが、実は「開集合の逆像が開集合である」という概念だと言い換えることができる、ということである。すなわち、「開集合」という概念さえ定義できれば、「近く」という概念を定義せずとも連続性を扱えるということである。 == 位相空間の定義 == === 開集合の公理 === 前節では、集合に対して「開集合」という概念を与えると、集合の間の写像に対して「連続」という概念を考えることができそうだということを見た。しかし、「開集合」という概念の与え方が滅茶苦茶であったら、純粋に論理的に見るだけならば整合性はあったとしても、実際上の意味は皆無だろう。「開集合」という概念の与え方にある程度の制限をつけておく必要がある。もちろん、その制限を与える根拠は、既に知っているEuclid空間の開集合に求められるだろう。そのように考え、次のような制限を与えることにする。 '''公理''' 集合Xのある部分集合族 <math>\mathcal{O}</math>が次の3条件を満たすとき、<math>\mathcal{O}</math>はXに位相を与える、あるいは単にXの位相であるといい、集合 <math>S \in \mathcal{O}</math>を ''X'' の開集合という。開集合の補集合を閉集合という。集合 ''X'' と位相<math>\mathcal{O}</math>の組<math>(X,\mathcal{O})</math>を位相空間という。 # <math>O_1,O_2 \in \mathcal{O} \Rightarrow O_1 \cap O_2 \in \mathcal{O}</math> #<math>\{ O_\lambda\}_{\lambda \in \Lambda} \subset \mathcal{O} \Rightarrow \bigcup_{\lambda \in \Lambda} O_\lambda \in \mathcal{O}</math> #<math>X \in \mathcal{O}</math> Euclid空間における通常の意味での開集合がこの公理を満たしていることを確認されたい。Euclid空間に通常の意味での開集合を定義することで与えられる位相を、Euclid位相と呼ぶ。 注意すべきことは、同じ集合に対して異なる位相を与えることも可能であり、その場合、異なる位相を与えれば異なる位相空間とみなされるということである。例えば実数全体の集合にEuclid位相以外の位相を入れることも可能である。特に集合が有限集合の場合はその集合に何種類の位相を与えることができるかまで調べることが可能である(それを数えてもあまり意味はないが)。 この定義から直ちにわかる次の事実を示そう: '''定理 '''<math>(X,\mathcal{O})</math> を位相空間とするとき, <math>\emptyset \in \mathcal{O}</math> が成り立つ. '''証明 '''<math>\bigcup \emptyset=\bigcup_{A \in \emptyset}A=\{\ x \in X;\ \exists\ A \in \emptyset \text{ s.t. } x \in A\ \} =\{\ x \in X;\ \exists\ A \text{ s.t. } [A \in \emptyset \wedge x \in A]\ \} =\{\ x \in X;\ \text{false}\ \}=\emptyset</math> と公理の2から明らか. ■ '''注意 '''上記の公理は, 次のものに替えることもできる: *<math>\{O_\lambda\}_{\lambda \in \Lambda},\ \#\Lambda<\infty \Rightarrow \bigcap_{\lambda \in \Lambda}O_\lambda \in \mathcal{O}</math> *<math>\{ O_\lambda\}_{\lambda \in \Lambda} \subset \mathcal{O} \Rightarrow \bigcup_{\lambda \in \Lambda} O_\lambda \in \mathcal{O}</math> ==== 位相空間の例 ==== 位相空間の具体例を挙げる。先ほどから述べているように、Euclid空間に通常の意味での開集合を定義することで位相空間とみなすことができる。 '''例'''(Euclid位相) <math>X=\mathbb{R}^n</math>において、 :<math>X \in \mathcal{O} \Leftrightarrow [\forall\, x \in X,\ \exists\, \varepsilon >0 \text{ s.t. } |x-y|<\varepsilon \Rightarrow y \in X]</math> また、一般に、任意の集合''X''に対して次のような2つの位相を与えることができることがすぐわかる。 '''例'''(離散位相) <math>\mathcal{O} = \mathcal{P}(X):=\{ S;\ S \subset X \} </math> '''例'''(密着位相) <math>\mathcal{O} = \{ X , \emptyset \} </math> (これを密着位相という) これらの位相はもっとも極端な位相の一例である。これから先「位相空間であって、さらに~~という条件を満たすもの」といって幾種類かの位相空間を特別に扱うが、しばしばEuclid位相はその性質を満たしてしまうので、その条件がいったい何を要求しているのかがわかりづらい。離散位相や密着位相はしばしばその条件を満たさないので、理解の役に立つだろう。 '''例'''(補有限位相) <math>\mathcal{O}=\{\emptyset\} \cup \{S \subset X | \#(X \setminus S)<\infty \}</math> すなわち、有限集合(と''X''自身)を閉集合とするのである。これも位相空間の公理を満たすことが容易に確かめられる。なお、補有限位相は''X''自身が有限集合の場合は離散位相と一致するので、普通は''X''が無限集合の場合に考える。 === 連続写像 === 位相空間と開集合を定義することができたので、これによって、位相空間の間の写像の連続性を定義できることになる。 '''定義''' <math>(X,\mathcal{O}_X),(Y,\mathcal{O}_Y)</math>を位相空間とする。写像<math>f \colon X \to Y</math>が連続であるとは、<math>U \in \mathcal{O}_Y \Rightarrow f^{-1}[U] \in \mathcal{O}_X</math>が成り立つことである。特に、写像が連続かつ全単射で、逆写像も連続なとき、同相写像という。 2つの位相空間の間に同相写像があるとき、この2つの位相空間は同相であるという。 群同型などの定義を知っている読者は、同相写像の定義に「逆写像も連続なとき」という条件がわざわざついていることに違和感を感じるかもしれない。だが群などの場合は、全単射な準同型は逆写像も必ず準同型になることが保証されるので、たまたまこのような条件が不要なるというだけである。位相空間の間の連続な全単射の逆写像は必ずしも連続になるとは限らないので、この条件がなければ2つの位相空間が同相という関係が(対称律を満たさないので)同値関係ではなくなってしまう。 '''例''' 元が2つ以上ある集合''X''に離散位相を入れた空間を<math>X_d</math>とし、密着位相を入れた空間を<math>X_t</math>とする。このとき、恒等写像 <math>\text{id} \colon X_d \to X_t</math> は連続であるが、逆写像 <math>\text{id}^{-1} \colon X_t \to X_d</math>は連続でない。 === 開核と閉包 === 位相空間Xとその部分集合Aについて、Aに含まれるXの開集合で(包含関係について)最大のものをAの'''開核'''または'''内部'''といい、<math>A^\circ</math>であらわす。また、Aを含む閉集合で最小のものをAの'''閉包'''といい、<math>\overline{A}</math>であらわす。また <math>\partial A:=\overline{A} \setminus A^\circ</math>をAの'''境界'''という。また、さらに <math>X=\overline{A}</math>が成り立つとき、AはXで'''稠密'''であるという。 開核と閉包を用いて、開集合と閉集合を特徴づけることができる。 '''命題''' 位相空間Xの部分集合Aについて次が成り立つ。 # ''A''は開集合である ⇔ <math>A=A^\circ</math> # ''A''は閉集合である ⇔ <math>A=\overline{A}</math> == 誘導位相・部分位相・商位相 == === 誘導位相 === 集合<math>X</math>と位相空間<math>(Y,\mathcal{O}_Y)</math>の間に写像<math>f \colon X \to Y </math>があるとする。この状況において<math>X</math>に新たに位相を与えるとすれば、どのような位相を与えるのが自然だろうか?当然、写像<math>f</math>が連続になるように与えるのが自然であろう。すなわち、 <math>\mathcal{O}_X:=\{f^{-1}[U];\ U \in \mathcal{O}_Y\}</math> とすればよさそうである。実際、このように定めると位相空間の公理を満たす。このようにして与えられる<math>X</math>の位相を、写像<math>f</math>によって誘導される位相という。 ===部分位相=== <math>(X,\mathcal{O}_X)</math>を位相空間とする。Xの部分集合Sに位相を与えるには、包含写像が誘導する位相を与えるのが一般的である。すなわち、 <math>\mathcal{O}_S:= \{ U \cap S;\ U \in \mathcal{O}_X \}.</math> このようにして定める位相を、部分位相ないしは相対位相という。以下、特に断りがなければ位相空間の部分集合には部分位相を与える。部分位相を与えられた部分空間を部分空間という。 '''例''' 整数の集合<math>\mathbb{Z}</math>はEuclid空間<math>\mathbb{R}</math>の部分集合なので、部分位相を入れることができる。この位相は離散位相と一致する。 '''問''' これを示せ。 ===商位相=== <math>(X,\mathcal{O}_X)</math>を位相空間とする。Xを同値関係で割った商集合X/~に位相を与えるには、次のように与えるのが一般的である。 <math>\mathcal{O}_{X/\sim} := \{ U;\ \pi ^{-1} [U] \in \mathcal{O}_X \}</math> ただし<math>\pi</math>は商集合への自然な全射である。自然な全射が連続となるように位相を定めたと理解できる。このようにして定める位相を、商位相ないし等化位相という。以下、特に断りがなければ位相空間の商集合には商位相を与える。商位相を与えられた位相空間を商空間という。 '''例''' Euclid空間<math>\mathbb{R}</math>上の同値関係~を <math>x \sim y :\Leftrightarrow x-y \in \mathbb{Z}</math>で定める。このとき、商空間<math>\mathbb{R}/{\sim}</math>は、<math>\mathbb{R}^2</math>の部分空間 <math>S^1:=\{(x,y)\in\mathbb{R}^2;\ x^2+y^2=1\}</math>と同相である。 '''問''' これを示せ。 == 開集合の基と積位相 == === 基と準基 === 位相空間 <math>(X,\mathcal{O}_X)</math> において、''X''の部分集合族 <math>\mathcal{B}</math> の部分集合 <math>\mathcal{U}</math> を用いて任意の開集合''U''が <math>U=\bigcup \mathcal{U}</math> と表されるとき、<math>\mathcal{B}</math>はこの開集合系の'''基'''であるという。位相空間が高々可算の濃度からなる基を持つとき、この空間は'''第二可算公理'''を満たすという。 逆に、部分集合族を任意に与えたとき、その部分集合族を基とする開集合系が存在するだろうか。一般には存在しないが、部分集合族<math>\mathcal{B}</math>が次の条件を満たせばよい。 '''命題''' 集合''X''の部分集合族 <math>\mathcal{B}</math> が次の条件を満たすとき、<math>\mathcal{O}:=\left\{ \bigcup \mathcal{U};\ \mathcal{U}\subset\mathcal{B} \right\}</math>は開集合系の公理を満たし、<math>\mathcal{B}</math>を基とする開集合系となる。 # <math>\bigcup\mathcal{B}=X</math> #<math>\forall\ B_1 ,\, B_2 \in \mathcal{B},\ \exists \ \mathcal{V} \subset \mathcal{B} \text{ s.t. } B_1 \cap B_2 = \bigcup \mathcal{V}</math> では、この条件を満たさない部分集合族から位相を構成するにはどうすればよいだろうか。そのためには、次のように修正すればよい。 '''命題''' 集合''X''の部分集合族<math>\mathcal{B}'</math>が<math>\bigcup\mathcal{B}'=X</math>を満たすとき、<math>\mathcal{B}:=\left\{\bigcap_{i=1}^{n}S_i;\ S_i \in \mathcal{B}' \right\}</math>は開集合の基となる条件を満たす。 すなわち、族に属する集合たちの有限個の交わりを追加するのである。このようにして作った<math>\mathcal{B}</math>を基とする位相を<math>\mathcal{B}'</math>が生成する位相といい、<math>\mathcal{B}'</math>をこの位相の'''準基'''という。 なお、<math>\mathcal{B}</math>が基となる条件を満たす場合、<math>\mathcal{B}</math>が生成する位相は<math>\mathcal{B}</math>を基とする位相に他ならない。 === 積位相 === 位相空間<math>(X_i,\mathcal{O}_{X_i}) \ (i=1,2,...)</math>の直積に位相を入れることを考える。部分位相や商位相の場合と同じように、直積の場合は第i成分への射影<math>p_i \colon X_1 \times X_2 \times \cdots \to X_i</math>が連続になるような位相を入れることを目標にしたい。 最も安直な発想をするならば、<math>\mathcal{S} := \bigcup_{i=1}^\infty \{ p_i^{-1}[U];\ U \in \mathcal{O}_{X_i} \}</math>という集合族が考えられる。しかし、この集合族は位相空間の公理を満たさず、開集合系ではない。だが、前節で見た開集合基となるための条件は満たしている。そこで、直積集合には、<math>\mathcal{S}</math>によって生成される開集合系によって位相を与えることにする。このようにして与えられる位相を'''積位相'''という。以下、特に断りがなければ位相空間の直積には積位相を与える。 == 連結・コンパクト・Hausdorff == この項では、位相空間の中で特別なよい性質を満たすものに特別な名前を与えていく。これらの性質がどのようなものであるかをよく理解するために、本文中で与える例のほかにも、それぞれの性質を満たす位相空間と満たさない位相空間の例を作りながら読むとよいだろう。 === 連結空間 === 位相空間が連結であるとは、直感的にはその空間が「繋がっている」ということである。より厳密には下のように定義される。 '''定義''' 位相空間Xが連結であるとは、Xの開かつ閉な部分集合はX自身と空集合に限ることである。 この定義が何を言わんとしているかを少し直感的に解説する。数直線<math>\mathbb{R}</math>の部分空間[0,1] &cup; [2,3]を考える。この集合は、直感的には「繋がっていない」。ところで、この集合の部分集合[0,1]は開集合であり、また[2,3]も開集合である(よくわからなければ部分位相の定義を確認せよ)。したがって、[0,1]と[2,3]は開集合であり、また閉集合でもある。ところが、直感的に見て「繋がっている」部分空間[0,1]を考えると、そのような開かつ閉な部分集合はありそうにない。以上の例から、この定義の妥当性が少しは納得できただろうか。 '''命題''' 連結集合の連続写像による像は連結である。 :(証明)<br />Xを連結な位相空間、Yを位相空間、<math>f \colon X \to Y</math>を全射な連続写像とする。Yが連結でないと仮定すると、Yの空でない真部分集合であって、開かつ閉であるものが存在する。これをUと書き、<math>V:=Y \setminus U</math>とする。U,Vは開集合で、fは連続写像なので、<math>f^{-1}[U],\ f^{-1}[V]</math>は開集合である。また、<math>f^{-1}[U]=X \setminus f^{-1}[V]</math>であり、したがって<math>f^{-1}[U]</math>は閉集合である。また、fは全射なので、<math>f^{-1}[U],\ f^{-1}[V]</math>は空でない。したがって、<math>f^{-1}(U)</math>はXの開かつ閉な空でない真部分集合であり、このような集合が存在することは矛盾。ゆえにYは連結である。// '''命題''' 連結集合の直積は連結である。 一方、連結集合の部分集合は連結とは限らない。<math>\mathbb{R}</math>は連結なので、先ほど挙げた例が反例になっている。 連結性とよく似た概念に、弧状連結性がある。 '''定義''' 位相空間Xが弧状連結であるとは、任意の <math>a,b \in X</math>に対して、ある連続写像 <math>\gamma \colon [0,1] \to X</math>であって<math>\gamma(0)=a,\ \gamma(1)=b</math>を満たすものが存在すること。 つまり、位相空間Xの任意の2点を結ぶ「弧」がある、ということである。 '''命題''' 弧状連結な位相空間は連結である。 ところが、連結であっても弧状連結であるとは限らない。反例を作ってみよ。(少し難しい) === コンパクト空間 === 位相空間Xの開集合の族であって、<math>\bigcup \mathcal{U} = X</math>を満たすものを開被覆という。Xの任意の開被覆が、そのうちの有限個だけをとってもやはり開被覆となっているとき、Xはコンパクトであるという。 コンパクトな集合の例と、コンパクトでない集合の例を挙げる。 '''例''' 集合''X''に密着位相を入れた空間はコンパクトである。 :(証明)<br />開被覆は<math>\{X\}</math>だけであり、これ自身有限部分被覆である。 '''例''' 有限集合はコンパクトである。 :(証明)<br />n個の元を持つ有限集合の部分集合の個数は2<sup>n</sup>個なので、この集合の開部分集合の個数はこれより少ない(有限個である)。よって、有限集合の任意の開被覆は有限個の開集合によって成っているので、それ自身が有限部分被覆である。// '''例''' 集合''X''に補有限位相を入れた空間はコンパクトである。 :(証明) :開被覆<math>\mathcal{U}</math>を任意にとり、空でない開集合<math>U_0 \in \mathcal{U}</math>をひとつとる。<math>X \setminus U_0</math>は有限集合なので、<math>X \setminus U_0=\{x_1,x_2,\cdots,x_n\}</math>とする。<math>\mathcal{U}</math>は開被覆なので、各<math>x_i</math>に対してその元を含む開集合<math>U_i \in \mathcal{U}</math>が存在する。このとき、<math>\{U_i\}_{i=0,1,2,\cdots,n}</math>は<math>\mathcal{U}</math>の有限部分被覆である。 '''例''' 無限集合''X''に離散位相を入れた空間はコンパクトではない。 :(証明)<br /> <math>\mathcal{U}=\{\ \{x\};\ x \in X\ \}</math>は''X''の開被覆だが、有限の部分被覆を持たない。 '''例''' <math>\mathbb{R}</math>の部分集合(0,1)はコンパクトではない。 :(証明)<br /><math>\mathcal{U}=\Big\{ \Big(\frac{1}{n},1\Big);\ n=2,3,\dots \Big\}</math>は(0,1)の開被覆だが、有限の部分被覆を持たない。// また、一般に次が成り立つ。 '''命題''' コンパクト集合の連続写像による像はコンパクト。 :(証明)<br />Kをコンパクト位相空間、Yを位相空間、<math>f \colon K \to Y</math>を全射な連続写像とする。Yの開被覆<math>\{ U_\lambda \}</math>を任意にとる。fは連続なので、各<math>f^{-1}[U_\lambda]</math>は開集合であり、特に<math>\{ f^{-1}[U_\lambda] \}</math>はKの開被覆である。Kはコンパクトなので、この開被覆は有限部分被覆<math>\{ f^{-1}[U_{\lambda_n}] \}_n</math>を持つ。このとき、<math>\{ U_{\lambda_n} \}_n </math>は<math>\{ U_\lambda \}</math>の有限部分被覆になっている。したがってYはコンパクトである。// '''命題''' コンパクト集合の直積はコンパクト。 '''命題''' コンパクト集合の有限個の和集合はコンパクト。 '''命題''' 位相空間のコンパクト部分集合と閉集合の交わりはコンパクトである。 :(証明)<br />Xを位相空間とし、KをXのコンパクト部分集合、FをXの閉部分集合とする。<math>K \cap F</math>の開被覆<math>\mathcal{U}</math>をとる。このときFは閉集合なので<math>X \setminus F</math>は開集合であり、<math>\mathcal{U} \cup \{\ \{X \setminus F \}\ \}</math>はKの開被覆である。Kはコンパクトなのでこの開被覆の有限部分被覆<math>\mathcal{V}</math>が存在する。<math>\mathcal{V} \setminus \{\ \{X \setminus F \}\ \}</math>は<math>\mathcal{U}</math>の有限部分被覆になっている。// コンパクトという性質を特徴づける条件をいくつか紹介する。Euclid空間の部分集合については、次の事実(Heine-Borelの定理)がよく知られている。 '''定理''' Euclid空間の部分集合がコンパクトであることは、有界かつ閉集合であることと同値。 この定理の証明のために、先に次の補題を示しておく。 '''補題''' 有界閉区間<math>I=[a,b] \subset \mathbb{R}</math>はコンパクト :(証明) :<math>\mathcal{U}</math>を''I''の開被覆とする。''I''の部分集合''I'''を ::<math>I'=\{x \in I|</math>ある有限集合<math>\mathcal{U}'\subset\mathcal{U}</math>が存在して<math>[a,x] \subset \bigcup\mathcal{U}'\}</math> :と定義する。<math>a \in I'</math>なので''I'''は空ではない。<math>\sup I'=c</math>とする。''c''≦''b''なので、''c''=''b''を背理法で示すために、''c''<''b''と仮定する。このとき、<math>c \in I</math>なので、<math>c \in U \in \mathcal{U}</math>なる開集合''U''がある。<math>\varepsilon</math>を十分小さくとれば<math>[c-\varepsilon,c+\varepsilon] \subset U,c+\varepsilon<b</math>とすることができる。また<math>c=\sup I'</math>であることからある有限集合<math>\mathcal{U}' \subset \mathcal{U}</math>について<math>[a,c-\varepsilon] \subset \bigcup\mathcal{U}'</math>である。よって、閉区間<math>[a,c+\varepsilon]</math>は<math>\mathcal{U'} \cup \{U\}</math>という<math>\mathcal{U}</math>の有限部分集合に被覆されるので、<math>c+\varepsilon \in I'</math>となるが、これは<math>c=\sup I'</math>であることに反し、矛盾。よって、''c''=''b''であり、<math>b \in I'</math>である。これは''I''がコンパクトであることを意味する。// :(定理の証明) :<math>S \subset \mathbb{R}^n</math>がコンパクトであるとする。このとき、''S''はHausdorff空間のコンパクト部分集合なので、閉集合である(次節参照)。また正の実数''r''に対して<math>B_r=\{x \in \mathbb{R}^n|||x||<r\}</math>とすると、<math>\{B_r\}_{r>0}</math>は''S''の開被覆なので、有限部分被覆<math>\{B_{r_i}\}_{i=1,2,\cdots,m}</math>を持つ。このとき、''S''の任意の元''x''について<math>||x||<\max_{i=1,2,\cdots,m}r_i</math>なので、''S''は有界である。 :逆に<math>S \subset \mathbb{R}^n</math>が有界閉集合であるとする。このとき、ある閉区間<math>J=[a_1,b_1]\times[a_2,b_2]\times\cdots\times[a_n,b_n]</math>が存在して''S''は''J''の閉部分集合である。補題より''J''はコンパクトなので、その閉部分集合''S''もコンパクトである。// 特に実数上の有界閉集合は最大値と最小値を持つので、ここからコンパクト集合上の実数値連続関数は最大値・最小値を持つことが従う。 一般の位相空間については、次のことが成り立つ。 '''定理''' 位相空間''X''がコンパクトならば、任意の位相空間''Y''に対して直積空間''X''×''Y''からの射影<math>pr_2:X \times Y \to Y</math>は閉集合を閉集合に写す。 :(証明) :''X''×''Y''の閉集合''F''を任意に取り、<math>A=Y \setminus pr_2[F]</math>とする。''A''が開集合であることを示せばよい。そのためには、任意の元<math>y \in A</math>に対し、<math>y \in V_y \subset A</math>を満たす開集合<math>V_y</math>が存在することを示せばよい。''A''の定義より<math>pr_2^{-1}[\{y\}] \subset (X \times Y) \setminus F</math>である、すなわち、<math>x \in X</math>を任意にとると、<math>(x,y) \in (X \times Y) \setminus F</math>である。ところで、<math>(X \times Y) \setminus F</math>は開集合であることから、ある開集合<math>U_{x,y} \subset X,V_{x,y} \subset Y</math>が存在して、<math>x \in U_{x,y},y \in V_{x,y},U_{x,y} \times V_{x,y} \subset (X \times Y) \setminus F</math>である。<math>\{U_{x,y}\}_{x \in X}</math>は''X''の開被覆であり、''X''はコンパクトなので、有限部分被覆<math>\{U_{x_i,y}\}_{i=1,2,\cdots,n}</math>を持つ。このとき、<math>V_y:=\bigcap_{i=1}^n V_{x_i,y}</math>は''Y''の開集合であり、<math>y \in V_y</math>である。また、<math>V_y=pr_2[X \times V_y]</math>であるが、<math>X \times V_y \subset (X \times Y) \setminus F</math>なので、<math>V_y \subset A</math>である。よって任意の<math>y \in A</math>に対してこの<math>V_y</math>は<math>y \in V_y \subset A</math>を満たす開集合であるから、''A''は開集合、すなわち<math>pr_2[F]</math>は閉集合である。// この定理は逆も成り立つ(この事実はKuratowski-Mrowkaの定理と呼ばれる)。よって、「任意の位相空間''Y''に対して直積空間''X''×''Y''からの射影<math>pr_2:X \times Y \to Y</math>は閉集合を閉集合に写す」という条件は、''X''がコンパクトであることを特徴づける条件になっている。 === Hausdorff空間 === 位相空間XがHausdorffであるとは、Xの任意の2点が開集合で分離されることである。より正確に述べると、 '''定義''' 位相空間XがHausdorffであるとは、<math>a \neq b</math>なる任意の<math>a,b \in X</math>に対し、<math>a \in U,\ b \in V,\ U \cap V = \emptyset</math>を満たす開集合U,Vが存在することである。 Euclid空間はHausdorffであり、またHausdorff空間の部分集合、直積はHausdorffであるので、初学者がすぐに思いつくような空間でHausdorffでないものは少ないが、たとえば以下のような空間は明らかにHausdorffではない。 '''例''' (密着位相)元が2つ以上ある集合''X''に密着位相を入れた空間は、任意の元に対してその元を含む開集合は''X''自身しかないので、Hausdorffではない。 '''例''' (補有限位相)無限集合に補有限位相を入れた空間は、任意の開集合の組が交わりを持つので、Hausdorffではない。 '''例''' (有限集合)有限集合に離散位相でない位相を入れると、ある点<math>a</math>に対して<math>\{a\}</math>は開集合ではない。この<math>a</math>を元として持つような開集合は有限個なのでそのすべての交わり<math>U</math>は開集合であり、ところで<math>\{a\}</math>は開集合ではないので、<math>U</math>は<math>a</math>以外の元をもつ。この元は<math>a</math>と開集合で分離できないので、この空間はHausdorffではない。 応用上扱う空間はHausdorffであることが多いので、次の2つの定理とその系は見た目以上に使い道の広い命題である。 '''定理''' Hausdorff空間のコンパクト集合は閉集合である。 :(証明)<br />XをHausdorff空間、Kをそのコンパクト部分集合とする。<math>X \setminus K</math>が開集合であることを示せばよい。そのためには、<math>X \setminus K</math>の任意の元xに対して開集合<math>U_x \ni x</math>であって<math>U_x \cap K=\emptyset</math>なるものが存在すればよい(このとき<math>X \setminus K=\bigcup_{x \in X \setminus K}U_x</math>は開集合である) 。<br />xをひとつ固定し、<math>y \in K</math>を任意にとると、<math>x \in U_y,\ y \in V_y,\ U_y \cap V_y=\emptyset</math>なる開集合<math>U_y,\ V_y</math>がある。<math>\{V_y;\ y \in K\}</math>はKの開被覆なので、有限部分被覆<math>\{ V_{y_i} \}_{i=1,\dots,n}</math>を持つ。このとき<math>U_x=U_{y_1} \cap \dots \cap U_{y_n}</math>とすると、これははじめに言った条件を満たす開集合<math>U_x</math>である。// '''定理''' コンパクト空間からHausdorff空間への連続写像は閉集合を閉集合に写す。 :(証明)<br />''X''をコンパクト空間、''Y''をHausdorff空間、<math>f \colon X \to Y</math>を連続写像とする。''F''を''X''の閉集合とする。''X''はコンパクトなので、''F''はコンパクトであり、したがって''f''[''F'']もコンパクトである。つまり''f''[''F'']はHausdorff空間''Y''のコンパクト部分集合なので、閉集合である。// '''系''' コンパクト空間からHausdorff空間への連続な全単射は同相写像である。 なおこの定理は、写像のグラフという概念を用いて次のように示すこともできる。 '''定義''' 写像<math>f:X \to Y</math>について、直積集合''X''×''Y''の部分集合<math>G:=\{(x,y) \in X \times Y|y=f(x)\}</math>を写像''f''のグラフという。 '''補題''' 写像<math>f:X \to Y</math>のグラフを''G''とする。''Y''がHausdorffならば、''G''は''X''×''Y''の閉集合である。 :(証明) :<math>(x,y) \in (X \times Y) \setminus G</math>を任意にとる。<math>(x,y) \in W \subset (X \times Y) \setminus G</math>を満たす開集合''W''が存在すればよい。<math>y \ne f(x)</math>であり、''Y''はHausdorffなので、<math>y \in V_1,f(x) \in V_2,V_1 \cap V_2=\emptyset</math>を満たす開集合<math>V_1,V_2</math>がある。開集合<math>U=f^{-1}[V_2]</math>を考えると、<math>x \in U</math>である。よって、<math>X \times Y</math>の開集合<math>W=U \times V_1</math>を考えると、<math>(x,y) \in W</math>である。また、任意の<math>(a,b) \in W</math>に対して<math>b \in V_1,f(a) \in V_2</math>であることから<math>b \ne f(a)</math>なので、<math>W \subset (X \times Y) \setminus G</math>である。すなわち、この''W''は<math>(x,y) \in W \subset (X \times Y) \setminus G</math>を満たす開集合であるから、<math>(X \times Y) \setminus G</math>は開集合であり、''G''は閉集合である。// :(定理の証明) :''F''を''X''の閉集合とすると、''f''のグラフの部分集合''G''∩(''F''×''Y'')は補題より''X''×''Y''の閉集合であるから、射影<math>pr_2:X \times Y \to Y</math>による像<math>pr_2[G \cap (F \times Y)]</math>は閉集合である。ところで、この像は''f''[''F'']に他ならない。// なおHausdorffは人名である。伝記は[[w:フェリックス・ハウスドルフ]]を参照。 == 距離空間 == === 距離の公理 === Euclid位相の開集合の定義は、次のようなものであった。 :<math>X \in \mathcal{O} :\Leftrightarrow [\forall\, x \in X,\ \exists\, \varepsilon >0 \text{ s.t. } |x-y|<\varepsilon \Rightarrow y \in X]</math> ここで、点と点の距離というものが重要な役割を果たしていることに注目してもらいたい。実は、Euclid空間に限らず、点と点の距離というものが考えられる空間であれば、Euclid空間と同様に距離を用いて位相を入れることができる。 まず、距離という概念が満たすべき公理を考えよう。 '''公理''' <math>d \colon X \times X \to \mathbb{R}</math>が距離関数(あるいは単に距離)であるとは、任意の <math>x,y,z \in X</math>について、次の4条件が成り立つことをいう: # <math>d(x,y) \ge 0</math> # <math>d(x,y)=0 \Leftrightarrow x=y</math> # <math>d(x,y)=d(y,x)</math> # <math>d(x,y)+d(y,z) \ge d(x,z)</math>(三角不等式) このとき、集合と距離関数の組(X,d)を距離空間という。 Euclid空間の通常の距離はこの公理を当然に満たしていることを確認してほしい。他にも距離の公理を満たす例は無数にある。いくつか例を挙げる。 '''例'''(離散距離)<br /> 任意の空でない集合Xに対して、<math>d \colon X \times X \to \mathbb{R}</math>を次のように定めると、距離の公理を満たしている。これを離散距離という。 :<math>d(x,y):= \begin{cases} 1, & x \ne y, \\ 0, & x = y. \end{cases} </math> '''注意'''(宮島['''1'''])この距離を使えば, いかなる集合も距離空間とみなすことができるが, 実用的とはいいがたい. このことは, 距離の定義の緩やかさを示しているに過ぎないのである. '''参考文献 '''['''1'''] 宮島静雄 著, 『関数解析』, 横浜図書. '''例'''(マンハッタン距離)<br /> <math>d \colon \mathbb{R}^2 \times \mathbb{R}^2 \to \mathbb{R}</math>を次のように定めると、これは距離の公理を満たしている。 :<math>d((x_1,y_1),(x_2,y_2)):=|x_1-x_2|+|y_1-y_2|</math> イメージとしては、マンハッタンや札幌のような、碁盤の目上に道路が配置されている街で、交差点から交差点へ移動するために通過する道路の長さのイメージである。 === 距離位相 === 最初に書いたように、距離空間には距離をもとにした位相を入れることができる。これを距離位相という。念のため、距離位相の定義を再掲しておく。 :<math>X \in \mathcal{O} \Leftrightarrow (\forall x \in X \ \exists \varepsilon >0 \ s.t. \ d(x,y)<\varepsilon \Rightarrow y \in X)</math> これが位相空間の公理を満たすことを、距離の公理を用いて確認してほしい。読者自ら確認することで、距離の公理に対する理解が深まるだろう。 距離空間は、比較的よい性質を持った位相空間である。それは、距離空間について、一般に次の命題が成り立つことからもわかるだろう。 '''命題''' 距離空間はHausdorff :(証明)<br />距離空間Xの点xと正の数<math>\varepsilon</math>に対し、<math>B(x,\varepsilon):= \{ y \in X;\ d(x,y) < \varepsilon \}</math>と書くことにする。<br /><math>x_1,x_2 \in X</math>を任意に取り、<math>d(x_1,x_2)=\delta</math>とする。このとき、<math>B\Big(x_1,\frac{\delta}{2}\Big),\ B\Big(x_2,\frac{\delta}{2}\Big)</math>は<math>x_1,x_2</math>を分離する開集合である。したがって距離空間はハウスドルフである。// '''命題''' 距離空間の部分集合はコンパクトならば有界 Hausdorff空間のコンパクト部分集合は閉集合なので、距離空間のコンパクト部分集合は有界閉集合であることがわかる。しかし、逆は一般には成り立たない。Heine-Borelの定理は、この逆がEuclid空間の場合は成り立つ、ということを主張している。 === 点列の収束と完備性 === 距離空間上の点列に対しては、Euclid空間の場合とまったく同様にして「収束」や「Cauchy列」といった概念を定義することができる。 '''定義''' 距離空間<math>(X,d)</math>上の点列<math>(a_n)</math>と点 ''a'' が :<math>\forall \varepsilon >0 \ \exists N \in \mathbb{N} \ s.t. \ n>N \Rightarrow d(a_n,a)< \varepsilon</math> を満たすとき、この点列は点 ''a'' に収束するといい、 :<math>\lim_{n \to \infty} a_n=a</math> と書く。 '''定義''' 距離空間<math>(X,d)</math>上の点列<math>(a_n)</math>が次の性質を満たすとき、この点列はCauchy列であるという。 :<math>\forall \varepsilon>0 \ \exists N \in \mathbb{N} \ s.t. \ m,n>N \Rightarrow d(a_m,a_n)<\varepsilon</math> 距離空間上の収束する点列は必ずCauchy列であることは容易に(Euclid空間の場合とまったく同様に)確かめられる。しかし、逆は必ずしも成り立たないことが次のようにわかる。よく知られているように、任意の実数に対してその数に収束する有理数列が存在するので、適当な無理数に対してこの数列を考える。この数列は、有理数の集合に通常の距離を入れた距離空間上の点列で、しかもCauchy列であるが、有理数上には収束しない。 そこで、逆の成り立つ距離空間には特別な名前を与えることにする。 '''定義''' 距離空間<math>(X,d)</math>上の任意のCauchy列が収束するとき、<math>(X,d)</math>は完備であるという。 Euclid距離を与えられた実数の集合が完備であることはよく知られている。この性質は歴史的経緯から「実数の連続性」と呼ばれるが、近代的な位相空間の用語法では「連続性」は写像に対して考えられる概念であるから、「実数の完備性」と言ったほうがより正確だろう。 == 分離公理 == === 分離公理とは === 既に述べたように、位相空間''X''がハウスドルフ空間であるとは、次の命題を満たすことであった。 :(T2):<math>a \neq b</math>なる任意の<math>a,b \in X</math>に対し、<math>a \in U,\ b \in V,\ U \cap V = \emptyset</math>を満たす開集合''U'',''V''が存在する。 この節では、この命題と類似の以下の命題たちの強弱について考察する。これらの命題は分離公理と呼ばれる。分離公理は他にも様々なものがあるが、ここでは(T2)の他に以下の3つの命題を考えることにする。 :(T1):<math>a \neq b</math>なる任意の<math>a,b \in X</math>に対し、<math>a \in U,b \notin U</math>を満たす開集合''U''が存在する。 :(T3):任意の閉集合''F''と<math>a \notin F</math>なる任意の<math>a \in X</math>に対して、<math>F \subset U, a \in V, U \cap V=\emptyset</math>を満たす開集合''U'',''V''が存在する。 :(T4):<math>F \cap G=\emptyset</math>なる任意の閉集合''F'',''G''に対して、<math>F\subset U,G \subset V,U \cap V=\emptyset</math>を満たす開集合''U'',''V''が存在する。 (T2)を満たす位相空間をハウスドルフ空間という。(T1)と(T3)を満たす位相空間を正則空間という。(T1)と(T4)を満たす位相空間を正規空間という。 === 公理間の強弱 === まず、公理(T1)について考える。(T2)を満たす空間が(T1)を満たすことは明らかである。すなわち、次が成り立つ。 '''定理''' ハウスドルフ空間は公理(T1)を満たす。 ここで(T1)は次に挙げる命題(T1)'と同値であることに注意する。 '''定理''' 位相空間''X''が公理(T1)を満たすことは、次の命題を満たすことと同値 :(T1)':任意の点<math>x \in X</math>について、<math>\{x\} \subset X</math>は''X''の閉集合である。 (証明) :''X''が(T1)を満たすとき、<math>y \ne x</math>とすると、<math>y \in U_y,x \notin U_y</math>なる開集合<math>U_y</math>が存在する。<math>\{x\}=X \setminus \bigcup_{y \ne x} U_y</math>なので、これは閉集合である。よって''X''は公理(T1)'を満たす。 :''X''が(T1)'を満たすとき、任意の<math>x \in X</math>に対して<math>U_x=X \setminus \{x\}</math>は開集合であり、<math>y \ne x</math>なる任意の''y''に対して<math>y \in U_x</math>である。よって、''X''は公理(T1)を満たす。// この定理を認めると、次のことがただちにわかる。 '''系''' 正規空間は正則空間である。 '''系''' 正則空間はハウスドルフ空間である。 つまり、正規⇒正則⇒ハウスドルフ⇒(T1)という強弱の関係があることがわかった。 === 正規空間の十分条件 === 前節では、正規であるという条件が比較的強い条件であることがわかった。この節では、位相空間が正規であるための十分条件をいくつか挙げる。 '''定理''' コンパクトハウスドルフ空間は正規空間である。 :(証明) :''X''をコンパクトハウスドルフ空間とする。ハウスドルフ空間は公理(T1)を満たすので、(T4)について確認すればよい。''F'',''G''を<math>F \cap G=\emptyset</math>を満たす''X''の閉集合とする。''F'',''G''はコンパクト空間の閉集合なのでコンパクトである。 :<math>x \in F,y \in G</math>を任意にとると、''X''はハウスドルフなので、<math>x \in U_{x,y},y \in V_{x,y},U_{x,y} \cap V_{x,y}=\emptyset</math>を満たす開集合<math>U_{x,y},V_{x,y}</math>が取れる。<math>\{V_{x,y}|y \in G \}</math>は''G''の開被覆で、''G''はコンパクトなので、有限部分被覆<math>\{V_{x,y_i}|i=1,2,\cdots,n\}</math>が取れる。このとき、<math>U_x=\bigcap_{i=1}^n U_{x,y_i},V_x=\bigcup_{i=1}^n V_{x,y_i}</math>は開集合である。 :<math>\{U_x|x \in F\}</math>は''F''の開被覆であり、''F''はコンパクトなので有限部分被覆<math>\{U_{x_j}|j=1,2,\cdots,m\}</math>が取れる。<math>U=\bigcup_{j=1}^m U_{x_j}</math>は''F''を部分集合として持つ開集合であり、<math>V=\bigcap_{j=1}^m V_{x_j}</math>は''G''を含む開集合であり、また<math>U \cap V=\emptyset</math>である。よって、''X''は公理(T4)を満たすので、正規空間である。// '''定理''' 距離空間は正規空間である。 この定理の証明のために、次のような写像を準備する。距離空間''X''の元''x''と部分集合''A''に対し、<math>d(x,A)=\inf_{y \in A} d(x,y)</math>とする。 '''補題''' <math>A \subset X</math>とするとき、写像<math>d(-,A):X \to \mathbb{R}^+ \cup \{0\}</math>を<math>x \mapsto d(x,A)</math>で定めると、この写像は連続である。また、特に''A''が閉集合ならば、<math>x \in A \Leftrightarrow d(x,A)=0</math>である。 :(証明) :(前半) :<math>\varepsilon>0</math>を任意にとり、<math>d(x,y)<\varepsilon</math>とする。<math>d(x,A) \ge d(y,A)</math>として一般性を失わない。<math>z \in A</math>を任意にとると ::<math>d(x,A) \le d(x,z) \le d(x,y)+d(y,z)</math> :なので、 ::<math>d(x,A)-d(x,y) \le d(y,z)</math> :である。任意の''z''に対してこれが成り立つことから、 ::<math>d(x,A)-d(x,y) \le d(y,A)</math> :なので、 ::<math>0 < d(x,A)-d(y,A) \le d(x,y)<\varepsilon</math> である。よって、<math>d(-,A)</math>は連続である。 :(後半) :<math>x \in A</math>のとき、<math>\inf_{y \in A} d(x,y)=d(x,x)=0</math>である。 :<math>x \notin A</math>のとき、''A''が閉集合であるとすると、ある<math>\varepsilon>0</math>が存在して<math>d(x,y)<\varepsilon</math>ならば<math>y \notin A</math>なので、<math>d(x,A) \ge \varepsilon>0</math>である。// これを用いて、距離空間の正規性を証明する。 :(距離空間は正規である証明) :''X''を距離空間とする。距離空間はハウスドルフなので公理(T1)を満たす。よって公理(T4)について確認すればよい。''F'',''G''を<math>F \cap G=\emptyset</math>なる''X''の閉集合とする。 :写像<math>f:X \to \mathbb{R}</math>を<math>f(x)=d(x,F)-d(x,G)</math>で定める。補題より''f''は連続である。また、<math>x \in F</math>ならば<math>f(x)=-d(x,G)<0</math>であり、<math>x \in G</math>ならば<math>f(x)=d(x,F)>0</math>である。よって、<math>U=f^{-1}[\mathbb{R}^-],V=f^{-1}[\mathbb{R}^+]</math>とすると''U'',''V''は開集合であり、<math>F \subset U,G \subset V,U \cap V=\emptyset</math>を満たす。すなわち、''X''は正規空間である。// === 反例 === 次に本節では、弱い公理を満たすが強い公理を満たさない反例となる位相空間を挙げてみよう。 '''命題''' 無限集合に補有限位相を入れた空間を''X''とすると、''X''は公理(T1)を満たすがハウスドルフ空間ではない。 :(証明) :異なる2点<math>a,b \in X</math>を任意にとる。<math>U=\{x \in X|x \ne b\}</math>とすると''U''は開集合であり、<math>a \in U,b \notin U</math>を満たす。よって''X''は公理(T1)を満たす。 :ところが、''X''はハウスドルフではないことが次のように示される。<math>a \in U,b \in V,U \cap V=\emptyset</math>を満たす開集合''U'',''V''が存在するとすると、<math>V \subset X \setminus U</math>であるから、''U''が開集合であることより''V''は有限集合であるが、このとき<math>X \setminus V</math>が無限集合であり、''V''が空でない開集合であることに反する。// '''命題''' 実数の集合<math>\mathbb{R}</math>に次のように通常とは異なる位相を入れた空間''X''を考える。<math>U \subset \mathbb{R}</math>が開集合であるとは、<math>\mathbb{R}</math>の通常の位相における開集合''V''と、自然数の集合のある部分集合<math>K \subset \mathbb{N}</math>を用いて、<math>U=V \setminus \left\{\frac{1}{n}|n \in K\right\}</math>と書けることであるとする。この空間''X''はハウスドルフ空間だが正則空間ではない。 :(証明) :通常の位相における開集合は''X''でも開集合であり、<math>\mathbb{R}</math>の異なる2点は通常の位相における開集合によって分離できるので、''X''はハウスドルフである。 :ところが、''X''は正則ではないことが次のように示される。点0と、閉集合<math>F=\left\{\frac{1}{n}|n \in \mathbb{N}\right\}</math>を考える。<math>0 \in U,F \subset V</math>なる開集合''U'',''V''を考える。''U''は0を元として持つ開集合なので、0を元として持つある開区間<math>(x,y)</math>と自然数の集合のある部分集合<math>K_0 \subset \mathbb{N}</math>を用いて、<math>U_0=(x,y) \setminus \left\{\frac{1}{n}|n \in K_0\right\}</math>と書ける集合<math>U_0</math>を部分集合として含む。十分大きい自然数''N''に対し、<math>\frac{1}{N}<y</math>が成り立つ。''V''は<math>F \subset V</math>なる開集合なので、定義より<math>\frac{1}{N}</math>を元として持つある開区間<math>(p,q)</math>と自然数の集合のある部分集合<math>K_N \subset \mathbb{N}</math>を用いて、<math>V_N=(p,q) \setminus \left\{\frac{1}{n}|n \in K_N\right\}</math>と書ける集合<math>V_N</math>を部分集合として含む。<math>\frac{1}{N}<\alpha<\min\{y,q\}</math>を満たす無理数<math>\alpha</math>が必ず存在することに注意すると、<math>U_0 \cap V_N \ne \emptyset</math>なので、<math>U \cap V \ne \emptyset</math>である。// これらの他に、ゾルゲンフライ平面と呼ばれる位相空間が、正則空間だが正規空間ではない位相空間の例として知られているが、ここでは詳しく触れない。 [[Category:数学|いそうくうかんろん]] [[Category:位相幾何学|*]] 6g7f0u44s41mugzu6z3knez8mpzupur SVG 0 10146 206662 204506 2022-08-16T23:38:57Z Ef3 694 /* 参考文献 */ * [https://www.w3.org/TR/2005/WD-SVG12-20050413/ Scalable Vector Graphics (SVG) 1.2 Specification](2005-04-13) wikitext text/x-wiki <!-- __NOTOC__ --> {{pathnav|メインページ|工学|情報工学|プログラミング|frame=1}} '''[[w:Scalable Vector Graphics|Scalable Vector Graphics]]'''(スケーラブル ベクタ グラフィクス、'''SVG'''、エスブイジー)とは、[[w:Extensible Markup Language|XML]]によって記述された2次元[[w:ベクターイメージ|ベクタグラフィック]]言語です。[[w:World Wide Web Consortium|W3C]]が[[w:オープン標準|オープン標準]]として勧告しています。[https://www.w3.org/Graphics/SVG/] <!-- ※ 問題点: 上記のHello World のコードは、SVGに対応してないないブラウザでも「Hello World」が表示されてしまう。 よって、初心者の誤解を防ぐため、非表示にします。 <syntaxhighlight lang="xml"> <svg:svg xmlns:svg="http://www.w3.org/2000/svg" width="100" height="100" version="1.1"> <svg:title>Hello, world!</svg:title> </svg:svg> </syntaxhighlight> --> == 目次 == 「※」がついている単元はサブページ未作成。 (編集者へ: サブページが出来たら、更新して「※」を除去してください。) * [[SVG/はじめに]] (動作確認の方法、技術的背景、など) :※ * SVG/図形の描画 :※ * SVG/テキストの描画 :※ * SVG/図形の変換 * [[SVG/動画]] :※ * SVG/構造化 :※ * SVG/関連情報の記述方法 * [[#参考文献|参考文献]] == ブラウザでの外部ファイル表示 == SVGは規格と実装との間に差があり、 外部ファイルとしてSVGファイルを読み込ませる場合のプログラミングがやや面倒です。(JavaScriptのよう簡単にはいきません。) ウェブブラウザに外部ファイルとしてSVGファイルを読み込ませたい場合、Firefoxの場合なら、その外部SVGファイルに冒頭に、下記コードのように :名前空間を <code> xmlns="http://www.w3.org/2000/svg" </code> というふうに設定する必要と、 :キャンバスサイズをwidthやheight属性などで設定する必要というように、 こういった必要があります。(Windows版のFirefoxの場合、キャンバスサイズをGoogle Chrome と同様に省略できるが(標準設定のサイズになる)、Linuxなど他OSの場合ではキャンバスサイズが必要になる場合もある。ブラウザが同じ「Firefox」でもOSごとに実装が微妙に違う。) Google Chrome および Microsoft Edge の場合も同様に、名前空間 <code> xmlns="http://www.w3.org/2000/svg" </code> の指定が必要です。(なお Google Chrome および Microsoft Edge の場合、キャンバスサイズの指定がなくても自動でキャンバスサイズの設定が行われる。) この様に、名前空間などを記述が欠落するとSVGファイルであることがブラウザに伝わらず。希望通り表示できなかったりエラーメッセージを伴う結果と成る。 ;外部ファイル側のコード例 :たとえばファイル名を "test.svg" とする。 <syntaxhighlight lang="xml"> <svg xmlns="http://www.w3.org/2000/svg" width="300" height="200"> <rect x="150" y="40" width="100" height="500" fill="lightblue" stroke="black" stroke-width=" 5" /> </svg> </syntaxhighlight> なお、キャンバスサイズを図形より地位いさい場合にはハミだしている部分は非表示になります(上記コードでは意図的にハミ出しています)。上記コードは縦長の長方形を表示するコードですがキャンバスサイズをハミ出た下半分は非表示になります。 ;HTMLファイル側 上記の外部SVGファイルを呼び出すHTMLファイル側は使う要素によって下記のようにマークアップが異なる。 * IMAGE要素 <syntaxhighlight lang="html5" highlight=8 line> <!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>外部SVG読み込みテスト</title> </head> <body> <image src="test.svg" type="image/svg+xml"> </body> </html> </syntaxhighlight> SVGファイルは画像ファイルなので、IMAGE要素で読み込めます。IMAGE要素ではsrc属性で外部ファイルを指定します。 もしWinodowsで、上記コードを実行した場合にブラウザの要素などのタイトルが文字化けする場合、<code><meta charset="utf-8"></code>を除去してください(Windowsではバージョンによっては文字コードがUTF-8ではなくShift_JISなので)。以下のOBJECT要素などでも同様です。 * OBJECT要素 <syntaxhighlight lang="html5" highlight=8 line> <!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>外部SVG読み込みテスト</title> </head> <body> <object data="test.svg" type="image/svg+xml"> </body> </html> </syntaxhighlight> OBJECT要素は、オブジェクトデータを記述するためのHTML要素です。 OBJECT要素ではsrc属性に代わってdata属性で外部ファイル指定します。<ref>https://html.spec.whatwg.org/multipage/iframe-embed-object.html#htmlobjectelement HTML Living Standard — HTMLObjectElement</ref>。 * EMBED要素 このほか、EMBED要素を使う方法もある。 <syntaxhighlight lang="html5" highlight=8 line> <!DOCTYPE html> <html> <head lang="2"> <meta charset="utf-8"> <title>外部SVG読み込みテスト</title> </head> <body> <embed src="test.svg" type="image/svg+xml"> </body> </html> </syntaxhighlight> EMBED要素は、埋め込み外部コンテンツ要素を記述するためのHTML要素である。 EMBED要素ではsrc属性で外部ファイル指定します。 == 画像そのものの記法 == === 四角形 === ==== 基本 ==== '''rect'''要素で表します。<ref name="mdn:svg:rect">https://developer.mozilla.org/ja/docs/Web/SVG/Element/rect</ref> <syntaxhighlight lang="xml"> <svg> <rect x="1" y="1" width="100" height="100" fill="#FFFFFF" stroke="#000000" stroke-width="5"/> </svg> </syntaxhighlight> 改行をする必要はありませんが、上記コードでは見やすさを重視してfill属性の手前で改行してあります。 rect要素で最低限必要なのは、位置と幅を指定するための次の4要素です。 ;x :x座標 ;y :y座標 ;width :横幅 ;height :縦幅 rectの不等号のペア(<code><rect … ></code>)の最後に、下記のように<code>/</code>が必要です。(下記コードの場合、 stroke-width="5" の次の部分。 ) <syntaxhighlight lang="xml"> <rect x="1" y="1" width="100" height="100" fill="#FFFFFF" stroke="#000000" stroke-width="5" /> </syntaxhighlight> もし、この<code>/</code>が終わりに無いと、ファイルの終端まで<code></rect></code>を探すことになります。(長方形以外の、円や線分など他の静止図形のタグでも同様、最後に「/」が必要です。) なお、下記のように、付随的な要素をstyleでまとめても良い。なお、下記のようにstyleでまとめる記法は[[CSS]]に由来するものであり、インラインCSSという記法です。(fillの次の点々はセミコロン、#FFFFFFの次の点々はコロンです。混同しないよう、注意しましょう。) <syntaxhighlight lang="xml"> <svg> <rect x="1" y="1" width="100" height="100" style="fill: #FFFFFF; stroke: #000000; stroke-width: 5; "/> </svg> </syntaxhighlight> なお、fillは閉じた領域の塗りつぶしの色です。strokeは、境界線など線分の色です。 <code>fill="#FFFFFF;</code>のFFは16進数です(十進数の255に相当)。 fillを指定しない場合、noneと書いても良いです。 <syntaxhighlight lang="xml"> <svg> <rect x="1" y="1" width="100" height="100" style="fill: none; stroke: #000000; stroke-width: 5; "/> </svg> </syntaxhighlight> なお、noneの代わりにblueやredと書くと、それぞれの色になります(つまり、HTMLカラーが使えます)。たとえば青色に内側を塗りつぶすなら <syntaxhighlight lang="xml"> <svg> <rect x="1" y="1" width="100" height="100" style="fill: blue; stroke: #000000; stroke-width: 5; "/> </svg> </syntaxhighlight> とも書けます。 ==== 色の指定方法 ==== 色については <code>rgb(11,11,11)</code>のように0~255の十進数の数値指定で書いてもよいでしょう。つまり、 <syntaxhighlight lang="xml"> <svg> <rect x="1" y="1" width="100" height="100" fill="rgb(220,220,255)" stroke="rgb(0,0,0)" stroke-width="5 "/> </svg> </syntaxhighlight> とも書ける。この場合、水色(うすめの青)で塗りつぶしています。 rectに限らず、円や線分など他の図形でも同様に、styleやrgbを使うことができます。 ;百分率も可能 色の指定は%単位でも可能ですが、rgbの3色すべてに%をつける必要があります。 <syntaxhighlight lang="xml"> <svg> <rect x="1" y="1" width="100" height="100" fill="rgb(0%,0%,100%)" stroke="rgb(0,0,0)" stroke-width="5 "/> </svg> </syntaxhighlight> ==== 透明化 ==== ;不透明度アルファ 色はさらに、不透明度アルファを追加した{{code|rgba()}}を使える。ただし、不透明度の値の指定は 0.0 ~ 1.0 の間の数値で行わなければならない。SVGの不透明度は 0 で完全に不透明であり、1 で完全に透明である。 <syntaxhighlight lang="xml"> <svg> <rect x="50" y="50" width="100" height="100" fill="rgba(255,0,0,1)" stroke="rgba(0,0,0,1)" stroke-width="5 "/> <rect x="1" y="1" width="100" height="100" fill="rgba(220,220,255,0.7)" stroke="rgba(0,0,0,1)" stroke-width="5 "/> </svg> </syntaxhighlight> {{code|rgba}}の第4引数は'''不'''透明度である。0から1の間で指定する。不透明にしたい場合には値を1にする。この不透明の数値の指定方法は、CSSに由来する方法である。(Inkscapeなどのドローソフトでは不透明度を0~255の数値で指定するものもあるが、ブラウザ版SVGの仕様とは異なるので注意。) rgba()関数は、0~255までの定義域と、0~1までの定義域とが混在しているので、あまりメンテナンスがしやすくないかもしれません。 ;透明の属性 rgb()関数でも透明の処理もできるように、属性で fill-opacity という塗りつぶし領域の不透明度を 0.0 ~ 1.0 で指定できる属性がありますので、メンテナンスのしやすさから、不透明度の指定には fill-opacity を使うほうがいいかもしれません。 fill-opacity は 0 で完全に不透明であり、1 で完全に透明である。 <syntaxhighlight lang="xml"> <svg> <rect x="50" y="50" width="100" height="100" fill-opacity="1.0" fill="rgb(255,0,0 )" stroke="rgb(0,0,0)" stroke-width="5 "/> <rect x="1" y="1" width="100" height="100" fill-opacity="0.7" fill="rgb(220,220,255)" stroke="rgb(0,0,255)" stroke-width="3 " /> </svg> </syntaxhighlight> なお、ストロークの不透明度を指定できる stroke-opacity という属性もあるのですが、あまり実装の性能がよくありません。ハードウェアの事情により、太いストロークを描画する場合に、微妙に表示が崩れてしまう場合があります。<!-- WindowsだけでなくFedora Linux 32 でも同様に表示くずれが確認できたので、OSの問題でなくハードウェアの問題。 --> ==== 図形の加工 ==== ;フィレット 図形のカドを丸まらせたい場合(製図の用語で言う「フィレット」)、rxおよびryで丸めの半径を指定できる。 <syntaxhighlight lang="xml"> <svg> <rect x="1" y="1" width="100" height="100" fill="rgb(255,255,1)" stroke="rgba(0,0,0,1)" stroke-width="5 " rx="10" ry="10" /> </svg> </syntaxhighlight> この他、transfrom属性とrotate()関数を使って、斜めに傾いた長方形などの図形を書けます。長方形以外の図形や文字列もrotate()関数に対応しています。 詳しくは、回転の単元で説明します。 === 円 === '''circle'''要素で表します。<ref name="mdn:svg:circle">https://developer.mozilla.org/ja/docs/Web/SVG/Element/circle</ref>circleでは、円の形を中心点の座標位置と半径のペアで表します。 <syntaxhighlight lang="xml"> <svg> <circle cx="1" cy="1" r="100" style="fill: #FFFFFF; stroke: #000000; "/> </svg> </syntaxhighlight> ;cx :円の中心点のx座標 ;cy :円の中心点のy座標 ;r :半径 === 多角形 === '''polygon'''要素で表します。<ref name="mdn:svg:polygon">https://developer.mozilla.org/ja/docs/Web/SVG/Element/polygon</ref>英語の polygon ポリゴンとは、日本語で「多角形」を意味します。 下記のコード例では座標 (0,100)、(50,0)、(100,100) を結んだ三角形を表示します。 <syntaxhighlight lang="xml"> <svg> <title>正三角形</title> <polygon points="0,100 50,0 100,100"/> </svg> </syntaxhighlight> ;points :各点の座標 :隣りあう点が結ばれる事と、および、始点と終点が結ばれます。 <nowiki><polygon points="第1点のx座標,y座標 第2点のx座標,y座標 第3点のx座標,y座標"/> </nowiki> の書式です。 なお、閉じていない単なる折れ線を描画したい場合には、polygon 要素ではなく polyline (ポリライン)要素を使います。 === 折れ線 === polyline (ポリライン)要素で折れ線を書けますが、fill属性およびstroke属性が必要です。 どのブラウザでも、fillの指定が無いと、塗りつぶしをしてしまいます。 また、fillをnoneにしたあとは、strokeが設定の無い限りストローク色も無しになってしまい描画されない状態なので、strokeも再設定する必要があります。 <syntaxhighlight lang="xml"> <svg> <polyline points="0,100 50,0 100,100" fill="none" stroke="black" /> </svg> </syntaxhighlight> ;曲がり具合の指定 折れ線の内部の、それぞれの曲がりのある角の箇所での描画方法を指定できます。 線の太さ(stroke-width)の範囲内で、角を丸めるか(round)、尖らすか(miter)、面取り(bevel)をするかを指定できます。 何も指定ない場合には、miterで描画するように設定されています。 SVGのこれらの機能は、あくまで線の太さの範囲内でしか、処理を行えません。(つまり、たとえば製図ソフト AutoCAD のような面取り・フィレットは、SVGのこれらの指定では出来ないです。) また、その折れ線の内部のすべての曲がり箇所で、同様の曲がり具合(あるいは尖り具合)で描画します。 <syntaxhighlight lang="xml"> <svg> <polyline points="10,100 50,10 100,100" fill="none" stroke="black" stroke-width="20" stroke-linejoin="round" /> </svg> </syntaxhighlight> stroke-linejoin属性によって、"round"または"miter"または"bevel"を指定します。 ;破線など stroke-dasharray(ストローク・ダッシュ アレイ)属性を使って、破線などを描くことができます。 書式は <pre> stroke-dasharray="描く部分の長さ1 描かない部分の長さ1 描く部分の長さ2 描かない部分の長さ2 " </pre> といったふうに、描く部分と描かない部分との繰り返しです。 <syntaxhighlight lang="xml"> <svg> <!-- 一点鎖線 --> <polyline points="50,40 300,40" fill="none" stroke="black" stroke-dasharray="20 4 4 4 " /> <!-- 破線 --> <polyline points="50,80 300,80" fill="none" stroke="black" stroke-dasharray="6 3" /> </svg> </syntaxhighlight> == 文章の描画 == HTMLでwebページを作るだけなら不要ですが、規格上は<code><nowiki><text></nowiki></code>タグで囲むことによりSVGファイルでも文字列を表示させる事ができます。 HTMLとは違い、textタグでは座標の位置を指定して文字列を表示できます。 <syntaxhighlight lang="xml"> <svg> <text x="100" y="60"> テスト </text> </svg> </syntaxhighlight> ;x :文字列の開始位置(左下)のx座標 ;y :文字列の開始位置(左下)のy座標 文字列の開始位置は、左'''下'''です。左上ではないので、注意してください。 追加の属性として、 :font-size でフォントの大きさ、 :text-decoration="underline" で下線の追加、 など、設定できます。 ;例 <syntaxhighlight lang="xml"> <svg> <text x="100" y="60" font-size="30" text-decoration="underline" > テスト </text> </svg> </syntaxhighlight> == 回転 == まず、基準の図形として、回転していない図形の描画をしましょう。 <syntaxhighlight lang="xml"> <svg> <rect x="150" y="80" width="100" height="50" fill="lightblue" stroke="black" stroke-width=" 5" /> </svg> </syntaxhighlight> この図形をたとえば斜めに傾かせたい場合、回転させる図形のタグの属性において transform="rotate(回転角, 回転中心のx座標, y座標)" の書式で属性を追記することで、回転を指定できます。 角度の単位は、直角を90度とする「度」単位です。(日本なら、小学校で習う角度の単位と同じです。) なお、座標を指定しない場合、原点を中心として回転します。 <syntaxhighlight lang="xml"> <svg> <rect id="some" x="150" y="80" width="100" height="50" fill="lightblue" stroke="black" stroke-width=" 5" transform="rotate(-10,100,100)" /> </svg> </syntaxhighlight> たとえば上記コードなら、長方形の右上が10度持ちあがった図形になります。 長方形だけでなく、楕円や折れ線や多角形など他の図形でも、この方法で回転が可能です。 また、textタグの文字列も同様に、この方法で回転が可能です。 == 構造化 == === グループ化 === g タグを用いて、gタグ内のオブジェクトに共通する属性を一括で記述できます。このような仕組みをSVG用語では一般に「グループ化」といいます。 <syntaxhighlight lang="xml"> <svg> <g stroke="blue" fill="white" > <rect x="1" y="1" width="100" height="100" stroke-width="5" /> <circle cx="30" cy="30" r="10" stroke-width="3" /> </g> </svg> </syntaxhighlight> たとえば上のコードの場合、長方形と円との両方に、ストロ-ク色を青に指定し、内側の塗りつぶし色を白に指定と、一括で指定しています。 ;各オブジェクトとグループ内要素に矛盾のある場合 なお、各オブジェクトにgタグの指定内容と矛盾する属性がある場合、普通は各オブジェクト側の指定が優先されます。たとえばcircleタグで <code> stroke="red"</code> という指定と、gタグの開始タグで <code> stroke="blue"</code> があれば、円のストローク色は赤色で表示されます。(Firefox, google Chrome, Microsoft Edge どれも結果は同じく、円ストロークだけ赤色の結果です。WindowsだけでなくLinuxでも同様の結果です。 ) === CSSとの組み合わせ === SVGのgタグを使わなくても、CSSとHTMLのクラスclassを使っても、共通する属性を一括で記述することができます。ただし、各オブジェクトごとに、クラスを指定する必要があります。 <syntaxhighlight lang="xml"> <style type="text/css"> .test { stroke: red; fill: white; } </style> <svg> <rect x="1" y="1" width="100" height="100" stroke-width="5" class="test" /> <circle cx="30" cy="30" r="10" stroke-width="3" class="test" /> </svg> </syntaxhighlight> 上のコードは、長方形と円をともに、ストロークだけ赤色で図形を表示します。 class 属性で、指定したスタイルを呼び出すのを忘れないようにしてください。 ;各オブジェクトとスタイルに矛盾のある場合 なお、CSS側とsvgオブジェクト側の属性で矛盾する内容がある場合(たとえばストローク色が違う場合など)、CSS側の指定が優先されます。(Firefox, google Chrome, Microsoft Edge どれも結果は同じで、CSS側のスタイルが優先されます。WindowsだけでなくLinuxでも同様の結果です。 ) 属性の記述を順序を <code> class="test" stroke="blue" </code>と書こうが、<code> stroke="blue" class="test" </code>と書こうが、2020年7月の時点ではCSS側のスタイルがどのブラウザでも優先されます。 == 関連情報の記述方法 == SVGでは下記のように、タイトルなどの付加情報を記述することもできます。 記述の位置はどこでも可能ですが、一般的には、svg開始タグの直後に記載するのが慣例です。 <syntaxhighlight lang="xml"> <svg> <title> 題名 </title> <desc> 解説 </desc> <rect x="150" y="80" width="100" height="50" fill="lightblue" stroke="black" stroke-width=" 5" /> </svg> </syntaxhighlight> title や desc は省略も可能です。 === 説明 === '''desc'''要素で表します。 === タイトル=== '''title'''要素で、タイトルを表します。 HTMLファイルに組み込んだ場合、規格の想定などではブラウザなどでtitleの内容を表示する予定なのかもしれないのですが、しかし現状2020年の時点では、FirefoxでもGoogle Chromeでもブラウザではsvgタグ内部のtitleタグの内容は表示されません。(HTMLタグのtitleとは、仕様の実装が違っています。) また、拡張子を.svgに変えてもInkscapeで調べても同様に、titleタグの内容ではなくファイル名そのものがInkscapeのファイル名に表示されます。 === 非表示タグ === HTMLファイルにコメントを書く非表示タグ <nowiki><!-- ここにコメントを書く --> </nowiki> はSVGでも同様に使えますので、ブラウザ画面に表示の不用なプログラマー向けの説明書きなどは、非表示タグで説明するという方法も可能です。 Inkscapeなどのドローソフトでも同様に、タグ<nowiki><!-- --> </nowiki> とその中身は非表示になります。 == 参考文献 == * [http://www.w3.org/Graphics/SVG/ W3CのSVGサイト] * [https://www.w3.org/TR/2018/CR-SVG2-20181004/ Scalable Vector Graphics (SVG) 2(C.R.)](2018-10-04) ** [https://github.com/w3c/svgwg/ SVG Working Group specifications リポジトリー(Github)] * [https://www.w3.org/TR/2005/WD-SVG12-20050413/ Scalable Vector Graphics (SVG) 1.2 Specification](2005-04-13) ** [https://www.w3.org/TR/2008/REC-SVGTiny12-20081222/ Scalable Vector Graphics (SVG) Tiny 1.2 Specification](2008-12-22) * [https://www.w3.org/TR/2011/REC-SVG11-20110816/ Scalable Vector Graphics (SVG) 1.1 Specification](2011-08-16)([http://www.hcn.zaq.ne.jp/___/REC-SVG11-20030114/ 日本語訳](2003-01-14)) * [https://www.w3.org/TR/2001/REC-SVG-20010904/ Scalable Vector Graphics (SVG) 1.0 Specification](2001-09-04) * [http://www.adobe.com/jp/svg/ AdobeのSVGサイト] * [https://developer.mozilla.org/ja/Mozilla_SVG_Project Mozilla SVG Project - MDC] == 脚注 == {{stub}} {{NDC|007.64}} [[Category:World Wide Web]] [[Category:マークアップ言語]] oainskbmdqrqb1qbwycw9io1l16fmpl 国家賠償法第3条 0 10585 206661 165114 2022-08-16T21:25:34Z Rhkmk 66092 wikitext text/x-wiki [[法学]]>[[コンメンタール国家賠償法]] ==条文== ;第3条 # 前二条の規定によつて国又は公共団体が損害を賠償する責に任ずる場合において、公務員の選任若しくは監督又は公の営造物の設置若しくは管理に当る者と公務員の俸給、給与その他の費用又は公の営造物の設置若しくは管理の費用を負担する者とが異なるときは、費用を負担する者もまた、その損害を賠償する責に任ずる。 # 前項の場合において、損害を賠償した者は、内部関係でその損害を賠償する責任ある者に対して求償権を有する。 ==解説== ==参照条文== ==判例== ;1項 *[http://www.courts.go.jp/search/jhsp0030?hanreiid=52088&hanreiKbn=02 損害賠償請求](最高裁判例 昭和50年07月25日)[[国家賠償法第2条]]1項,[[道路法第13条]]1項,[[道路法第42条]]1項 *[http://www.courts.go.jp/search/jhsp0030?hanreiid=54207&hanreiKbn=02 損害賠償請求](最高裁判例 昭和50年11月28日)[[自然公園法第14条]]2項,[[自然公園法第25条]],[[自然公園法第26条]],[[地方財政法第16条]] *[http://www.courts.go.jp/search/jhsp0030?hanreiid=52719&hanreiKbn=02 損害賠償](最高裁判例 平成1年10月26日)[[自然公園法第14条]]2項,[[自然公園法第25条]],[[自然公園法第26条]],[[地方財政法第16条]] ---- {{前後 |[[コンメンタール国家賠償法|国家賠償法]] | |[[国家賠償法第2条]]<br> |[[国家賠償法第4条]]<br> }} {{stub}} [[category:国家賠償法|3]] llcp7bb4cqobguzfgwzcy65trt4e16y オペレーティングシステム 0 13844 206669 204507 2022-08-17T03:02:36Z Ef3 694 /* 発展的な話題 */ 2022年現在のx86プロセッサは、x86命令セットをマイクロ命令に分解し、マイクロ命令の組合せによっては複合的なマイクロ命令に合成し実行しています。ところが、lodsbの様な複雑な命令はマイクロ命令に翻訳されず固定的なマイクロコードにより実行されます。このため、かつて命令読込みのオーバーヘッドがなくせるという理由で「最適化」の代表だった複雑な命令を使うことは、現在は実行速度を低下させることになります。 wikitext text/x-wiki {{stub}} ;予備知識 本書を読むには予備知識としてアセンブラの知識と、X86系CPUのレジスタなどのアーキテクチャの知識が必要である。 一般的にプログラミングにおいて、ハードウェアの制御は、コンパイラが対応していない命令(特権命令やIO命令など)はアセンブリ言語で記述する事になる。 もし知らなければwikibooks記事『[[X86アセンブラ]]』などで解説してある。特に『[[X86アセンブラ/GASでの文法]]』『[[X86アセンブラ/x86アーキテクチャ]]』『[[X86アセンブラ/x86アセンブラ]]』では初心者むけに説明してある。 本書では触れてないが「カーネル」とか「ユーザランド」とかの用語についてはwikibooks『[[高等学校工業/ソフトウェア技術]]』などで触れてある。 本書はタイトルが今のところは「オペレーティングシステム」だが、実際はコンピュータアーキテクチャ理論やデジタル回路理論など低レイヤーの理論や実務的知識が混在したものになっている(あとで整理する)。大学の科目の分類が縦割りのタコツボ・時代おくれで、全体像が分かりづらいので、予定では、今後の構成でも、意識的にコンピュータアーキテクチャなど関連分野の説明を、整理後にも、ある程度は残しておく予定。 なのでOSと言うタイトルなのにマイコンCPU(Z80など)にも触れているという状況である。 == 総論 == === 学習の方向性 === ==== 概要 ==== オペレーティングシステムは一般に、ユーザーにハードウェアレベルのプログラミングをさせる手間を減らし(ほぼ無くして)、パソコンを使いやすくするためのものです。 なので、オペレーティングシステムの中身は、そういったものになっているハズです。 具体的に言うと、市販のOSなどは、まず起動時にハードディスクとBIOSを作動させ(いわゆる「ブートローダー」 Boot Loader)、つづいてデバイスドライバなどを起動させる仕組みになっています。 私たちが自分でOSを作る場合、BIOSの機能の呼出し命令などは自分で書く必要がありますが、CPUメーカーなどが必要な命令を(int命令など)用意してくれているので、それを使うことで、手間を減らせます。 デバイスドライバなどは、OS制作では、自分で書く必要があります。 さて、ブートの仕組みは、もとになった規格である、ハードディスクの規格が古いため、まずMBR(マスター ブートレコード, Master Boot Record)またはMBRを経由してPBR(パーティション ブートレコード)というのを起動してから、 そのあとにハードディスクの指定された第1セクタをコピーして、そのコピーをメモリ番地の0x7C00 番地に配置して実行する。 ただし、当面は、この番地(0x7C00 )は知らなくても、アセンブラなどを用いて機械語に翻訳する際に、アセンブラが自動的に適切な番地に割り当ててくれます(※ のちの節で後述するコード例でも、当面がこの番地を入力する必要が無い)。 なので、このメモリ上へとコピーされるプログラムが、BIOS以降に最初にOSの起動するプログラムです。 もし「プログラム・カウンタ」という用語を知っていれば(高校の『情報』教科で習う用語です)、プログラムカウンタが最初に指し示すアドレスは、メモリ番地の0x7C00 番地ということになります。 ==== ブートの概要 ==== MBR(Master Boot Record)には、どのPBRを起動するのかの情報や、また、そのPBRはハード上のどの位置に存在しているかの ありか の場所を記述することになります。 このようなブートの経緯の仕組み(ブートプロセス boot process)のため、内蔵ハードディスクのようなブート用の記録メディアの先端○○バイトはどう書くのかが決まっています(ブートセクタ)。このブートセクタの先端領域がMBRの占有する領域であり、そのMBRのなかに情報としてPBRを起動するためのブート情報を書きます。 しかし、私たちが最終的に作りたいのは、あくまでもOSです。ブートローダーではないのです。 このため、OSをもし自分で作ろうとするなら、最終的には、ある程度はBIOSや内蔵機器のシステムなど、ハードウェア側のシステムの仕組みを知る必要があるでしょう。 しかし、ある程度は規格で決まっています。たとえばディスプレイについては『VESA』という団体が規格化を行っており、このためBIOSでのディスプレイの扱いも、ある程度は規格的に整理されています。 一般的なBIOSには、起動時にハードディスクに書かれたプログラムを実行する仕組みがあります(でないと、ブートローダーとして役立たない)。 また、一般的なCPUやアセンブラには、メモリの最初から何番目のアドレスに、どの機械語命令を書き込むか、という、メモリアドレスを指定してメモリに書き込む機能(org疑似命令)があります。 つまり、これらの機能を合わせて、(ブートデバイスの)メモリへとコピーされる領域に、パソコン電源投入直後の初期状態のメモリをどう変更したいかを書けばいいわけです。 それぞれのBIOSメーカーやCPUメーカーなどがデータシートなどを公開しているハズなので、余裕があればネットで確認しましょう。 :(しかし市販の『BIOSの設定が分かる!』みたいなタイトルの書籍は、OSの仕組みの勉強には、まったく使い物になりません。) :(また、「Windows10の使い方が分かる」みたいな書籍も、使い物になりません。) 一般にどのパソコンも、電源ボタンを入れた起動時に、内蔵ハードディスク(または内蔵SSD)とCPUとメモリとディスプレイが起動するようになっています。 そして、ディスプレイの表示内容は、(いわゆるビデオチップなどの)VRAM(ビデオRAM)または、メモリ(差し込める奴)から読み読み取るようになっています。 しかし、一般的なBIOSは、アセンブラのINT 0x10命令でディスプレイに割り込みをかけられるようになっていますので、あまりハードの内情を知る必要はありません(アセンブラのINT とは、割り込み interrupt のことです。C言語の整数型変数宣言 integer とは違うので、混同しないように。)。 :※ なお、割り込み信号の発生のさいのチャタリングの除去は、たとえばシュミット・トリガ回路で除去できる<ref>『H8マイコン入門』、堀桂太郎、東京電機大学出版局、2003年12月20日 第1版 第2刷、162ページ</ref>。 また、BIOSあたりのレベルで、ディスプレイが、メモリにASCIIコードにもとづくデーターバイトを入れるだけで、その文字を順番に表示するサポートなどをしています。(ディスプレイ用のメモリに機械語のdb命令で文字を書き込むだけで、その文字をアセンブラが自動的にバイト文字に変換し、さらにBIOSとハードが連携して自動的に該当する文字を画面に表示するプログラムにしてくれる。) 実際、日本の書店で市販の「OS自作」などを謳っている書籍を読むと、「メモリマップ」 memory map というハードウェア業者の用意した仕様にしたがって、該当するメモリの書き換えをする作業を機械語などで書いて、それでGUIを作っています。 けっしてOS自作界隈だけが言ってる用語ではなく、電子工作の界隈でも『メモリマップド I/O』という用語が、同じような意味であります<ref>『H8マイコン入門』、堀桂太郎、東京電機大学出版局、2003年12月20日 第1版 第2刷、54ページ</ref>。 原理的には、VRAMのメモリマップを書きかえる事と、(C言語でいうif文のような)条件分岐などの制御構造などの実装により、GUI画面が作れます(ディスプレイの画像はピクセル単位の点の画像の集積なので)。 ==== メモリマップ ==== さて、一般的に、メモリの一部の領域は、メーカーごとに使い方が決まっており、「最初の何バイトはハードディスクの起動用に使う」、「△△バイト目から□□バイト目からは、ディスプレイとのやり取りの制御に使う」とか、ハードウェア(基盤やBIOSなど)のメーカーごとにメモリの使い方が決まっています。 一般的なパソコンではグラフィック描画用のVRAMアドレスは 0xa0000 から 0xaffffの領域が割り当てられています。 なお、このようなメモリの用途の割り当てのことを「メモリマップ」memory map といいます。 (MBRなどとは違います。MBRはハードディスクの話題です。メモリマップはDRAMなどの話題です。) もし、一般的でない特殊なハードウェアの場合は、メモリマップを調べる必要があります。 なので、OSを作るには、世間に流通しているハードウェアのメモリマップを探りあて、C言語やアセンブラなどで、メモリ上のデータを書き換えるようにプログラムを書いて、それをブート時にブートローダーから起動させる用に命令すれば、デバイスなどを操作できると考えられます。 現在の市販に流通しているパソコンのアーキテクチャの多くは、1900年代の昔のIBMやインテルなどの発表したアーキテクチャである 「X86」系というのが元になっているので、まずはそれに詳しくなる必要があります。 CPUメーカーのAMD系のハードウェアであっても、パソコンのアーキテクチャの多くはX86系ですので、まずはX86系を勉強する必要があります(しかし、組み込み系とか、スーパーコンピュータ、その他の携帯モバイル機器などは、アーキエクチャの違う場合があるので、別途、アーキを調べる必要がある)。 なお、「メモリマップ」という概念があるのは、パソコン用CPUアーキテクチャだけでなく、組み込みマイコンCPU(Z80やH8など)などでも同様です(とはいえ、組み込みマイコンにブートローダやディスプレイなどは一般に無いのが普通なので、そこは誤解しないように)。 ==== 割り込み ==== キーボードや内蔵タイマなどの周辺ハードは、「割り込みコントローラ」(PIC)というものを経由して、CPUやメモリは、これらの周辺ハード(キーボードや内蔵タイマなど)を制御しています。 :※ 割り込みとは、何が何に割り込んでいるかというと、いま実行している命令と次の命令のあいだに、それ以外のデバイスの要求が割り込むイメージである。 X86系における割り込みハンドラとは、イメージ的には、下図のような感じです。 <pre> CPU ━━ 割り込みハンドラ━━━━┳━キーボード                  ┃                 ┣━タイマ                 ┃                 ┣━(※ 以下略)                 ┃ (※ 以下略) </pre> なお、マイコンボードのPICマイコンと「割り込みハンドラ」('''PIC''')は名前が似ていますが、まったくの別物ですので、混同しないように。 キーボードの制御は、PICから、さらにキーボードコントローラー(KBC)というのを経由して、通信方式は一般的にシリアル通信で、制御が行われます。 上図はつまり、さらに下図のようにキーボードの部分が修正されます。 <pre> CPU ━━ 割り込みハンドラ━━━━┳━キーボードコントローラー ━━キーボード                  ┃                 ┣━タイマ                 ┃                 ┣━(※ 以下略)                 ┃ (※ 以下略) </pre> ;余談 当面は覚える必要は無いですが、 一般的なパソコン/BIOSでは、割り込みに使える番号の数は、0番から255番までの合計256個です<ref>白崎博生 著『Linuxのブートプロセスをみる』、株式会社KADOKAWA(発行)、アスキー・メディアワークス(プロデュース)、2014年10月2日 初版、53ページ</ref> <ref>内田公太・上川大介 著『自作エミュレータで学ぶX86アーキテクチャ』、株式会社マイナビ (※出版社名)、2015年8月30日 初版 第1刷 発行、160ページ</ref>。このうち、0番~31番まではインテル(CPUメーカー)仕様などの規格などにより用途が既に決められております。なので、ユーザーが自由に定義できるのは32番~255番の領域だけです。 また、割り込みが発生する直前のCPUの状態の保存の方法は、単にスタックにプッシュすることで保存しているだけです。割り込みが発生すると、スタックにフラグレジスタやPCレジスタなど(主に CSレジスタ(コードセグメント)とIPレジスタ(命令ポインタ)とFLAGSレジスタ)の値が(スタックに)プッシュされて保存され、そしてハンドラに制御が移ります <ref>白崎博生 著『Linuxのブートプロセスをみる』、株式会社KADOKAWA(発行)、アスキー・メディアワークス(プロデュース)、2014年10月2日 初版、55ページ</ref> <ref>内田公太・上川大介 著『自作エミュレータで学ぶX86アーキテクチャ』、株式会社マイナビ (※出版社名)、2015年8月30日 初版 第1刷 発行、160ページ</ref>。 割り込みが終わるなどして戻るときに、スタックに保存しておいたフラグなどのデータを取り出します。 ;Linuxのコマンド LinuxのFedora31ではターミナル端末のコマンドで <code> cat /proc/interrupts </code> とすれば、そのハードウェアでの割り込みコントローラの割り当ての構成を見られる。 「proc」の前にスラッシュ記号(/)をつけるのをコマンド入力時には忘れないように。 なお、表示結果は、コンピュータのハードウェア構成によって異なる。 一例として、富士通の2010年頃のノートパソコン FMV-BIBLO NF/B70 を Fedora31 上で <code> cat /proc/interrupts </code> してみると、下記のように表示される。 <pre> [ユーザー名@localhost ~]$ cat /proc/interrupts CPU0 CPU1 0: 143681 0 IO-APIC 2-edge timer 1: 110 0 IO-APIC 1-edge i8042 8: 0 1 IO-APIC 8-edge rtc0 9: 0 76 IO-APIC 9-fasteoi acpi 12: 0 728 IO-APIC 12-edge i8042 16: 18138 0 IO-APIC 16-fasteoi uhci_hcd:usb3, i915 17: 0 9 IO-APIC 17-fasteoi uhci_hcd:usb4, firewire_ohci, yenta, mmc0 18: 17109 0 IO-APIC 18-fasteoi ehci_hcd:usb1, uhci_hcd:usb5, uhci_hcd:usb8, ath 19: 0 0 IO-APIC 19-fasteoi uhci_hcd:usb7, i801_smbus 23: 0 30 IO-APIC 23-fasteoi ehci_hcd:usb2, uhci_hcd:usb6 27: 0 68728 PCI-MSI 512000-edge ahci[0000:00:1f.2] 28: 16891 0 PCI-MSI 4194304-edge enp8s0 29: 0 922 PCI-MSI 442368-edge snd_hda_intel:card0 NMI: 133 125 Non-maskable interrupts LOC: 154414 216397 Local timer interrupts SPU: 0 0 Spurious interrupts PMI: 133 125 Performance monitoring interrupts IWI: 28932 26837 IRQ work interrupts RTR: 0 0 APIC ICR read retries RES: 41828 40626 Rescheduling interrupts CAL: 18459 15141 Function call interrupts TLB: 38258 37058 TLB shootdowns TRM: 0 0 Thermal event interrupts THR: 0 0 Threshold APIC interrupts DFR: 0 0 Deferred Error APIC interrupts MCE: 0 0 Machine check exceptions MCP: 2 2 Machine check polls HYP: 0 0 Hypervisor callback interrupts HRE: 0 0 Hyper-V reenlightenment interrupts HVS: 0 0 Hyper-V stimer0 interrupts ERR: 0 MIS: 0 PIN: 0 0 Posted-interrupt notification event NPI: 0 0 Nested posted-interrupt event PIW: 0 0 Posted-interrupt wakeup event [ユーザー名@localhost ~]$ </pre> なお、cat コマンドは単に、引数で指定されたファイルを表示するだけである。また、「 /proc/interrupts 」とは、単に proc ディレクトリーの中にある interrupts ファイルを指定しているだけである。なお、マウスで探すときは、ホームディレクトリーの中には proc ディレクトリーはなく、「コンピュータ」アイコンから、たどって行くと見つかる。 なので、別にコマンド端末からの捜査でなくとも構わず、マウス操作で直接、procディレクトリーを探して interruptsを見ても、かまわない。 なお、番号の呼び方で 「 0: 143681 0 IO-APIC 2-edge timer」 の端子は「 IRQ 0 」と呼ぶ。 「 1: 110 0 IO-APIC 1-edge i8042」 は「IRG 1」 と呼ぶ。 「 8: 0 1 IO-APIC 8-edge rtc0」 は「IRQ 8」と呼ぶ。 「IRQ」とは、割り込み要求 Interrupts ReQuest のことである。 「APIC」というのは、単に、インテル製の割り込みコントローラーの製品名で、そういう製品がある。インテルの古い割り込みコントローラで「8259A」というのがあって、それを(Windows2000やペンティアムが出始めた)1990年代〜2001年頃に後継したのが「APIC」である。 さらに2010年代の原題では、その「APIC」を拡張した「xAPIC」になっているが、便宜的に「APIC」と呼ばれているママのことも多い。 なお、メーカーなどによって異なる可能性はあるが、だいたい、どこのメーカーのパソコンでも、割り込み IRQ のハードウェア構成は :0番(IRQ 0)はタイマー、 :1番(IRQ 1)はキーボード、 i8042 とはインテル製のキーボードコントローラの型番 :12番(IRQ 12)はマウス、 i8042 とキーボードコントローラの型番がある理由は、マウスのセンシングでもキーボードコントローラを流用しているから、 などの共通的な傾向がある。 から8番あたりまでの構成は、表示結果からも 「 CPU0 CPU1 」と2つCPUなんとかが表示されるのは、単にこのパソコンのCPUが2コアだから(インテル Core2Duo 採用品)。 CPU0 CPU1 0: 143681 0 IO-APIC 2-edge timer などの「143681」は、単に合計の割り込み回数だと言われている(要 確認)。Fedora では、この /proc/interrupts ファイル内に、割り込みの統計が保管されている。 ちなみに proc ディレクトリーおよびproc配下のほとんどのファイルは、実は(DRAMなどの)メモリ上に置かれた設定情報である。実は物理的にはハードディスクには proc ディレクトリー/ファイルは無い。ユーザーがアクセスしやすいように、わざと、あたかも proc 関連ファイルが(まるで)ハードディスクにあるかのように擬態されて表示される仕組みに Linux などが なっている。そもそも proc 関連の項目が「ファイル」かどうかも本来は疑わしい。 なお、ポートアドレスで指定したIOポートにデータを送信できます<ref> 白崎博生『新装改訂版 Linuxのブートプロセスをみる』、株式会社 KADOKAWA、2014年10月2日 初版発行、55ページおよび66~67ページ</ref>。 <syntaxhighlight lang="asm"> out 0x21, ax </syntaxhighlight> のように書きます。 つまり、 <syntaxhighlight lang="asm"> out ポートアドレス, ax </syntaxhighlight> の書式になります。 ポートアドレスをイミディエイトウィンドウで与えた場合、IO空間の $0000 .. $FFFF のうち最下位の $0000 ... $00FF にしかアクセスできません。 ポートアドレスの一覧については下の表を参照。」 {| class="wikitable" |- ! !! PIC1 <br>(マスター) !! PIC2 <br>(スレーブ) |- | コマンド || 0x20 || 0xA0 |- | データ || 0x21 || 0xA1 |} 0x11 の部分は、コマンドで、この場合は初期化コマンド。 メーカーによって違う可能性はありますが、よくあるポートアドレスとして、 0x20 から 0x3F 割り込みコントローラ(PIC) 0x40 あたり タイマ 0x60 あたり キーボード関係 の割り当てがあります。(※ 参考文献『作って理解するOS』、276ページ。 ) その他、割り込みコントローラー(PIC)について、 0x20 マスターPICのコマンドレジスタ。 0x21 マスタPICの割り込みマスク(interruput mask)レジスタ。 0xA0 はスレーブPICのコマンドレジスタ。 0xA1 はスレーブPICの割り込みマスク(interruput mask)レジスタ。 などに割り当てられている場合もある。 あらかじめ直前に move 命令で、axレジスタに送信したいデータを入れておく必要があります。 つまり、 <syntaxhighlight lang="asm"> mov ax, 送信したいデータ out ポートアドレス, ax </syntaxhighlight> の書式になります。 ポートアドレスをレジスタに代入する場合は、 <syntaxhighlight lang="asm"> out dx, ax </syntaxhighlight> のように dx レジスタ間接でIOポートを指定します(dxレジスタ以外はポートアドレスの修飾に使えません)。 dx レジスタ間接を使うと、IO空間の $0000 .. $FFFF 全てにアクセスできます。 さらに、データサイズが何ビットかにしたがってmovやoutの末尾に b (1バイトの場合)または w (2バイトの場合)がつくので、 <syntaxhighlight lang="asm"> movb al 、 送信したいデータ outb ポートアドレス 、 al </syntaxhighlight> のようになります。 なお一部のC言語のライブラリで提供されている標準外の関数 {{code|outb()}} は、上述のようなアセンブリ言語のoutb命令に相当するものです<ref>ダニエル・P・ボベットおよびマルコ・サセティ著『詳解Linuxカーネル 第3版』、高橋浩和監訳、2011年5月20日 初版 第5刷、244ページ </ref>。 {{コラム|シリアル通信とパラレル通信| なお、一般に電子機器ケーブルが信号を送受信をするとき、複数本の信号線で送受信する方式をパラレル通信といい、いっぽう、1本だけの信号線で送受信する方式をシリアル通信という。 ただし、パラレル通信は、速度が遅い。 一見すると、パラレル通信のほうが、線路が多いぶん多くの情報を送れそうだが、信号の到達タイミングにばらつきが生じるので、高速化は困難である。 なお、Z80系マイコンCPUにはパラレル通信インターフェースの端子が存在する<ref>堀桂太郎『Z80アセンブラ入門』、東京電機大学出版局、2007年5月20日 第1版 第2刷、143ページ</ref>。Z80は最大クロック数が12MHzの製品がある<ref>堀桂太郎『Z80アセンブラ入門』、東京電機大学出版局、2007年5月20日 第1版 第2刷、134ページ(「143」の誤記ではない)</ref>。12メガもの高周波でどうやってパラレル通信をしてるか(そもそも12メガでもパラレルできるのか)、気になるところである。 いっぽう、H8マイコンはシリアル通信を内蔵している<ref>白土義男『H8ビギナーズガイド』、東京電機大学出版局、2008年2月20日 第1版 第9刷、16ページ</ref>。 こういう言い方をすると、なんとなくパラレル通信では符号化が不要な感じかもしれないが、そんなことはなくて、単にシリアル通信のほうが符号が長くなりやすいだけで、シリアル通信でもパラレル通信でもともに符号であるし、そもそもデジタル信号は基本的に符号化して情報伝達をするので、シリアル通信もパラレル通信もともにデジタル信号なので符号化が必要である。 よく変換コネクタで、シリアル通信とパラレル通信の変換コネクタなどが業者むけに販売されているが(はたして家電量販店で市販してるかどうかは知らない)、これは、符号を別方式の符号に変換してるのである。けっしてアナログ信号をデジタル信号に変換してるわけではない(つまり、ADコンバーター(アナログ/デジタル変換器のこと)とは違う。)。 なお現代でも、産業用機械などにおいて(装置と別の装置との)送受信の場合などは、(USBシリアル接続でなくて)パラレル通信用の端子ケーブル(たとえば RS232C ケーブルなど )が使われる。 なお、RS232Cケーブル(これはパラレル端子)やPS/2ケーブル(これはシリアル通信端子)は、イメージ的に何となく古いイメージなので、てっきりアナログ通信かと誤解しがちだが、RS232CケーブルとPS/2ケーブルはそれぞれデジタル通信である。 RS232Cは、現代でも産業機器などで使われる。工場など企業の労働現場は、かならずしも空調などが快適とは言えず、また、機械工作の切削クズなどが発生しやすい環境もあったりするので、頑強な過去の時代のケーブルなどが好まれる場合もある。 過去には、古いパソコンで、外部との接続端子にRS232Cがよく使われていた。 PS/2 は、やや古いキーボード接続に使われた端子およびケーブルである。 これらの古いケーブルおよび端子は、接続先の機器がアナログ的な機器である場合も多いので(特に RS232C)、てっきり端子も「アナログ端子だろう」(×)と誤解しがちであるが、しかし、RS232CもPS/2も端子じたいはデジタル端子なので混同しないように。 なお、パソコンのハードディスクの接続は現代では一般にシリアル通信であり、シリアルATAと言われる。ケーブルが太そうに見えるので何となくパラレルっぽく見えるかもしれないが、しかし、シリアルATAはその名のとおりレッキとしたシリアル通信である。 また、拡張カード端子とパソコン内部コントローラなどの接続に使われるPCIバスおよびその発展系の各種規格もシリアル通信である。 さて、シリアル通信では、8B/10Bという符号化がある。(ウィキペディア『[[w:8b/10b]]』) もしCPUがシリアル通信なら、とうぜん、これを行ったうえで、さらにそれぞれの端子の通信内容を重ねているのだろう。 この8b/10bは、もし同じビットが長時間連続すると、電子回路の電磁気的な都合により入力ビットが反転しても出力の立ち上がりが不完全になって出力エラーになるという回路特性があるので、同じビットが絶対に連続しないように、8ビットの入力信号を、ビットが4個以上は連続しない10個のビット符号に置き換えるという、符号方式である。 置き換えの符号は、規格で決められているが、数学的な規則性は無いので、覚えなくていい(実務では、規格表で確認する)。 また、4B/5Bなど、同じ原理の符号方式もある(4B/5Bは4ビット入力を連続しない5ビット入力に置き換えている)。 :※ 資格本などで「電気通信設備工事担任者」(いわゆる「工事担任者」)などの資格本を読むと、ここら辺の話題が説明されている。 さて、シリアル信号とパラレル信号の変換技術でSerDes(サーデス)という方式がある。原理は単純で、たとえばパラレル入力でA=1, B=0,C=0,D=1なら、 シリアル変換のために1本の送信ケーブルで1秒後に1, 2秒後に0、3秒後に0、4秒後に1を送信というように送信するようにする原理。(もちろん実際には「1秒」という長時間ではなく、もっと短い周期。) 簡単にいうと、このserdesの原理では、入力ピン数が増えると、そのぶん周期が長くなる。 8B/10B などの符号化と、このserdesを組み合わせて、8B/10B SerDes などとして、コンピュータ内部では使われている。 このようにパラレル伝送は現代では評判が悪いが、しかしGPUではパラレル的な伝送が使われている(原理的に、GPUの各プロセッサに伝送するために伝送をどこかでパラレル化せざるを得ない)。 コンピュータアーキテクチャの専門書でもGPUについて『パラレル』という用語が用いられている(しかし『パラレル伝送』とは専門書では言ってないが)。 他にもスーパーコンピュータの並列コンピューティングも同様に、専門書では『パラレル』という用語が用いられている。 このGPUや並列コンピュータのように、チップ1個上のハードウェア内部的にはシリアル伝送だが、そのチップまたはマザーボードをいくつも配置して並列計算するという、新型のパラレル処理のようなものが現代ではスーパーコンピュータなどの大型計算では行われている。 スパコン開発者・GPU開発者などは特にノウハウを公言していないが、パラレル伝送には上記のような同期化のさいの困難性などの問題もあるので、もしも精度の高く要求される計算をする場合には、伝送のズレなどによる誤差のぶんを考慮しなければならないハズなので、対策として例えば計算の確認のための多重化など(同じ計算を複数回計算して、誤差が無いかを確かめるなど)、慎重な処理をしなければならないだろう。 あるいは、多数決モジュールあるいは多数決回路というのがあり、これは複数の回路からの計算結果の一致やズレを相互検証するものだが、これもパラレル伝送の問題があるので、なので対策が必要である。 パラレルはタイミングがズレるが、しかしタイミング以外の波形パターンはまずズレないのだろうから、だったら最初からズレを見込んで、た余計に伝送をすればイイ。 たとえばもし「110」というデータを送りたいなら、その前後に「0000」をつけて「0000 110 0000」と送れば、 もし「0」一個ぶんだけタイミングが遅れても、「 000 110 0000」と、送りたい「110」のデータは残る。 「0000」1個だけなら不安なら、たとえば「0000」を3回繰り返して「0000 0000 0000」とか追加する仕様にすればいいだろう。そうすれば「000 0000 0000 110 0000 0000 0000」となるので、「0000」が2回繰り返すので、それから、「0000」が保護材として追加されたデータだと分かる。 実際には、4b/5b の導入の経緯のように、0がいくつも「0000」のように続くと立ち上がりが悪くなるので、 4b/5bなどの符号を保護材側データを追加する必要があろうが。 }} {{コラム|原始的なコンピュータのアーキテクチャ| よく、情報科学の入門的な理論では、「コンピュータの基本的な仕組みとしてCPU内にはレジスタがあって、基盤にはメモリがあって、」(以下略)・・・ などと習うが、 それだけでは実は不十分。 まず、CPUに、作業内容の切り替えスイッチが必要である。 なぜなら、アセンブリ言語で色々な命令があるが、その命令にもとづいて、CPUは回路を切り替えなければいけないからだ。 [[File:2to4demux.svg|thumb|500px|デマルチプレクサの原理]] スイッチの実装としては、デジタル回路の技術で「デマルチプレクサ」という切り替えスイッチ回路が有名であるので、単にこれを使えばいい。 右図がデマルチプレクサの原理図であり、右図の場合は2ビット用なので2の2乗ぶんの4個のスイッチを切り替えられる。 [[File:Multoplexor1.svg|thumb|マルチプレクサの原理図]] なお、(頭文字に「デ」のついていない)マルチプレクサというものは、デマルチプレクサの出力側の終端すべてにOR回路を1個つなげて、まとめただけである。 用語だけ見ると、てっきり、1文字ぶん短いマルチプレクサのほうが(デマルチプレクサよりも)中枢的な部品のように思えるが、しかし実際はデマルチプレクサこそが中枢的であり、デマルチプレクサによる回線切り替えこそが重要技術である。 [[File:OR-gate of diodes.svg|thumb|230px|left|ダイオードによるOR回路の等価回路の概略図<br>※ 実際にはパソコン内のOR回路はMOSトランジスタなどによる回路であり、ダイオードではない。]] さらにいうなら、そのOR回路は逆流を防止するためにつけられただけである。このように、マルチプレクサでの出力端子のOR回路に、あまり意味は無い。 私たちは、けっして用語に惑わされるのでなくて、回路図と照らし合わせて本質を学ぼう。(※ なお、パターソン&ヘネシー『コンピュータの構成と設計』だと、マルチプレクサのほうを中心に考えている<ref> David A. Ratterson, John L.Hennessy『コンピュータの論理と設計 第5版[上] ~コンピュータのハードウェアとインターフェース~』、2019年9月5日 第5版 第7刷 発行、238ページなど</ref>。しかし、彼らの考えは不十分だろう。デマルチプレクサこそが中心的な部品である。もっともパタヘネ本の初版は1996年4月9日であり、この時代で、ここまで調べたあげているパタヘネはすごい。) なお、理工書の東京電機大学出版局『コンピュータ工学の基礎』を読むと、最初にマルチプレクサとデマルチプレクサを教えてから、あとから加算回路を教えるという書籍の構成である<ref>淺川毅『コンピュータ工学の基礎』、東京電機大学出版局、2018年9月10日 第1版 第1刷 発行、100ページおよび101ページ </ref>。 さらに、電機大の同文献ではマルチプレクサの説の直前で2進-10進デコーダを紹介しており<ref>淺川毅『コンピュータ工学の基礎』、東京電機大学出版局、2018年9月10日 第1版 第1刷 発行、98ページ </ref>、まるで「きっとマルチプレクサの正体は2進デコーダなんだろうな」とでも言いたげな構成である。 :※ パタヘネ本では、論理回路の中身まで、あまり言及していない。 デジタル電子回路でよく、2進-10進デコーダという、4本の入力端子の2進数の入力を、出力10本の回路に切り替える回路がある。(2の4乗は16なので、最大16本の出力に切り替えできる。) さて、パタヘネ本によると、X86系CPUの命令数は約1000個らしい<ref> David A. Ratterson, John L.Hennessy『コンピュータの論理と設計 第5版[上] ~コンピュータのハードウェアとインターフェース~』、2019年9月5日 第5版 第7刷 発行、157ページの図2.43など</ref>。なので、CPU用のデマルチプレクサを作りたい私たちは、単に2進-1000進デコーダを作ればいいだけであろう。パタヘネ本によるとX86系の命令数は2012年の時点で900個である。 なお「デコーダ」という用語について、一般に情報科学でも、CPUが命令を解釈して実行させるために各装置に信号を送るための「命令デコーダ」とは、このデマルチプレクサのことであると考えられる(※ パタヘン本ではマルチプレクサの前段階のシステムが「命令デコード」だとしている<ref> David A. Ratterson, John L.Hennessy『コンピュータの論理と設計 第5版[上] ~コンピュータのハードウェアとインターフェース~』、2019年9月5日 第5版 第7刷 発行、276ページおよび277ページ図4.33など</ref>)。 なお、マルチプレクサのことは、「データセレクタ」という<ref> David A. Ratterson, John L.Hennessy『コンピュータの論理と設計 第5版[上] ~コンピュータのハードウェアとインターフェース~』、2019年9月5日 第5版 第7刷 発行、238</ref>。字面だけみると「命令デコーダ」と「データセレクタ」とは別物のように見えるが、ようするにデマルチプレクサによる回路出力の切り替えと、その付属システムにすぎない。私たちは本質を学ぼう。 さて、私たちに必要なスイッチ個数はアセンブラの命令によって切り替えるので、最低でも数百個もの切り替えが必要だろうが(ひょっとしたら数千個や数万個)、 ここで2の16乗は65536なので、16ビット分のデマルチプレクサの配線をすると、回路を切り替えられる。 数万本もの導線というと、人間の手作業ではムリだが、しかし半導体リソグラフィーを使えば可能であろう。というか、たとい困難だろうが、それをやった企業が半導体チップ産業の覇者になっているのだろう。 半導体の製造では紫外線照射や近年の研究開発ではX線照射をするが、照射の回数を、私たちの目標ではなんとか16回~32回程度に抑えたい。 では、何にしたがって回路を切り替えるかというと、(上述したように)アセンブラのプログラムにしたがって回路を切り替えればいいのである。そのため、アセンブリ言語は、スイッチ切り替えに対応可能なような命令体系になってなけれればらない。 さて、そのアセンブラのプログラムの読み取りのためには、現在の命令の位置を示す「プログラムカウンタ」も作る必要がある。 では、そのプログラムカウンタをどうやって作ればいいか? ヒントは、昔の紙テープ式コンピュータで、要するにあれと同じことを電子データで実現すればいいのである。 まず、紙テープコンピュータがどういう仕組みになってるか考えよう。 紙テープのうち、一定の読み取り面だけを読み取るわけで、その紙テープにデータに対応する穴が開いていて、その穴の位置や大きさなどの組み合わせで、プログラムデータを区別しているわけである。 そして、紙テープ読み取りコンピュータがプログラムデータを読み取り終わって、そのプログラムを実行し終えたら、テープを一定幅だけ進めるわけである。 そして、また、テープを読み取り、プログラムを実行することの繰り返し。 これを電子回路的に実現すればいい。 まず、プログラム実行時のデータ保存領域が必要だが、これはメモリで代用できる。 ハードディスクは低速なので、ハードディスクからメモリに読み出す仕組みになっている。 現代のパソコンでは、狭義の命令プログラム保管用のDRAMメモリと、プログラム以外の画像データや音声データやテキストデータなどのDRAMメモリは、同じメモリ基盤上にある。だが原理的には、必ずしも同じ基板上にする必要は無く、そういう構造の場合をハーバード・アーキテクチャという。つまり、命令用メモリと、データメモリとが別々の部品であるのが、ハーバード・アーキテクチャである<ref name="H8">『H8マイコン入門』、堀桂太郎、東京電機大学出版局、2003年12月20日 第1版 第2刷、6ページ</ref>。かつてハーバード・マークワンで採用されていたアーキテクチャが、そういう(命令とその他データの分離された)アーキテクチャだった)。1990年以降でもAtmel社のAVRシリーズの8bitマイコン用CPUが、ハーバード・アーキテクチャを採用している。Arduino という2005年以降に普及したイタリアのマイコンボードで8bit用ボードにAVRシリーズを採用している。ハーバード型(ハーバード・アーキテクチャ)は欠点として回路構造が複雑になるものの、長所として高速化しやすいという利点もある<ref name="H8" />。そのため、一部の制御用マイコンでもハーバード型が活用されているという<ref name="H8" />>。 さて、演算回路などでプログラムの実行が終わったら、なんらかのフィードバックをプログラムカウンタに返して、前に送ったプログラムが終了したことをカウンタに知らせる必要がある。つまり、どんなプログラム命令でも、命令1個につき、かならず終了後に、命令実行を確認するためのフィードバックを返す必要がある(ただし、デジタルのフィードバック信号)。命令実行ずみ検出フィードバックが帰ってくるまで、プログラムカウンタを進めない仕組みにする必要がある。 電子回路の本を読めばフィードバックなんて、どこの本でも書いてある。 演算回路の出力に、フィードバック回路もつければいいだろう。 あとは、プログラムをそもそもどうやって入力するかだが、コレは単にキーボードから入力すればいい。キーボードは、人間が手作業でボタンを押して入力するので、単に、そのボタンの押された内容にもとづいて、メモリに機械語を保存すればいい。 メモリそのものは、SRAMのようにフリップフロップ回路で作ることができる。 電源を切った後にも保存したければ、磁気テープならぬ磁気ハードディスクにでも保存しとけばいい。黎明期のコンピュータだって、紙テープに保存していたわけだ。 コンピュータはこんな仕組みらしい。 }} ==== IN命令とOUT命令 ==== 上述のように、キーボードやタイマなどのメモリ以外のデバイスとの送受信は、IN命令または OUT命令で、ポート番号を仲介して制御する仕組みである。 INやOUTの方向は、CPUから見た方向である。 CPUからみて、デバイスに送る方向の場合に OUT 命令である。 デバイスからの情報を、CPUのレジスタが受け取る場合に IN 命令である。 IN命令やOUT命令の引数で、引数でI/Oポートアドレスを指定することで、どのアクセスの読み書きをするかを指定する。 また、キーボードコントローラーも、ポートアドレスが割り当てられている。 {{x86-inst-2|in}} {{x86-inst-2|out}} 実例として一般に、キーボードコントローラーのポートアドレスは 0x60 と 0x64 である。0x60がデータ用、0x64がコマンドやステータス用。<ref name="making_os:447"> (※ 参考文献『作って理解するOS』、初版第1刷、447ページ ) </ref>。 なので out 0x60, al のような命令により、読み書きが可能である<ref name="making_os:448"> (※ 参考文献『作って理解するOS』、初版第1刷、448ページ ) </ref>。 しかし、コンピュータ黎明期からある、いくつかのデバイスの制御では、IN命令やOUT命令を使わずとも、ソフトウェア割り込みを発生させる INT 命令が用意されている(IN 命令とは異なる)。BIOSによって、 INT 命令に対応したハンドラが用意される。 具体的に言うと、仕様上は、ディスプレイやフロッピーディスクやハードディスク、キーボードなどは、割り込み INT 命令によってBIOSの機能を呼び出せる仕様であり、int 0x10 はディスプレイとの割り込み、int 0x13 はディスクアクセスとの割り込み、などの仕様がある。 本書では、とりあえず、80年代あたりの古いアーキテクチャを前提とする(資料が入手しやすいので)。そのため、最近のアーキテクチャでは動作しない可能性がある。 === 実験の手段 === 一般に、エミューレーターを使って実験します。 無料のフリーソフトでも、[[w:QEMU]]などのエミュレータを使えるので、アセンブラの[[w:Netwide Assembler|w:NASM]](無料ソフト)などで(アセンブリコード入力を経由して)機械語を入力していきます。 ※ 次の節で、qemuの使い方を大まかに説明する。 原理的には、アセンブラを経由せずともバイナリエディタ(Hex editor)といわれるもので機械語を直接に書いてプログラムするのも、原理的には可能です。そもそもアセンブラ自体どうやって開発されたかを想像すれば、おそらくバイナリエディタを、流通しているCPU用のアセンブラ命令にあわせて特化してプログラミング用に作られたソフトウェア(がアセンブラ)なのでしょう。 :※ なお、日本語ではバイナリ(2進数)エディタといいますが、しかし英語では16進数(hex)で「ヘックス エディタ」Hex editor といいます。なので Linux などで対応の機械語エディタを探す場合は、16進エディタような名前のソフトを探すことになります。 原理の理解としてはバイナリエディタの存在に気づくことも重要ですが、しかしバイナリエディタによるプログラミングではコード記述が覚えづらく非現実的ですし、一目では内容が分かりづらいです。なので、一般にアセンブラで入力していくのが、OS製作では現実的でしょう。 さて、NASMは、あくまでエミュレーター上での仮想化なので、完全には仕組みを再現していませんが、しかし個人の学習では、止む(やむ)を得ません。 もしもエミュレータを使わずに、BIOSのブート設定を 毎回 書き換えて実機のパソコンでブートの実験などを毎回したとしたら、とてもメンドウです。なので、エミュレータを使って、手間を省きます。 なお、一般的なLinuxなどでは、リリース直前の開発の後半などで、確認のために最終的に開発者たちはDVDなどに書き込んでブートしてみたりするなどして、実験します(いわゆる「ベータテスト」などで、DVDのISOを無料配布している)。 なお余談ですが、OS自作でなくCPU自作をしたい場合、[[w:GNU Binutils]]などの無料のクロスアセンブラがありますので、そういうのを活用します。半導体製造工場などを個人は持ってないので、ソフト的にエミュレートするしかありません。 === 備考: エミュレータの種類 === エミュレータにも種類や方式が色々とあります。 方式のひとつとして、ホストOSのインストールされているパソコンのCPUを間借りする方式があります。 別の方式として、ホスト側のCPUは間借りせずソフトウェア内に仮想のCPUを制作する方式のものなどもあります。 コミュニティ ベース の qemuやBochs というエミュレータは、(ホストCPUをあまり)間借りしないで、ソフト的に仮想のCPUを作る方式のものである<ref>内田公太・上川大介 著『自作エミュレータで学ぶX86アーキテクチャ』、株式会社マイナビ (※出版社名)、2015年8月30日 初版 第1刷 発行、6ページ</ref> いっぽう、オラクル社のVirtual Box やヴイエムウェア社のVMWare というエミュレータは、ホストPCのCPUを間借りする方式のものである。 私たちの学習の目的には、VirtualBox 的に複数のCPUが混ざり合うと学習的に分かりづらくなるので、qemuのようなソフト的にCPUの機能を再現するほうが分かりやすいと考え、qemuを優先して紹介することにする。 また、qemu はオープンソースである。 なお、Virtual Box は昔は非オープンソースだったが、現在はオープンソース版のVirtual Box がある。 なお、オラクル社のようなホストCPUを間借りする方式にも長所はあり、仮想化の中では処理速度を速くしやすいという長所もある。 本書では、とりあえず qemu を前提として説明する。 == qemuの設定方法と使用方法 == === 設定方法(Windowsの場合) === 前提として、ダウンロードとインストールは既に終わっていると仮定する。 qemuは、コマンドプロンプトから使うソフトウェアである。 なので、まずパス(Path)を通さないといけない。 具体的には、環境変数PATHにqemuのあるフォルダーを追加する。 :デスクトップで「システムのプロパティ」を検索し、システムのプロパティを開く :[詳細設定]タブの右下にある[環境変数]ボタンをクリック :[環境変数]画面を開く :'''システム環境変数'''の設定の先頭に、<code>C:\Program Files\qemu</code><code>;</code>を追加する。 さて、パスが追加し終わったら、はたして本当にパスが通ってるの確認のため、Windwosのコマンド プロンプトを起動して C:\Users\ユーザー名>qemu-img というふうに、コマンド「qemu-img」でも入力してみよう。 なお、「qemu」というコマンドは無いので、「qemu」とコマンド入力しても。 'qemu' は、内部コマンドまたは外部コマンド、 操作可能なプログラムまたはバッチ ファイルとして認識されていません。 さて qemu-imgコマンドは引数を指定して使用するコマンドなので、上記コマンド「qemu-img」を実行すれば、端末上で引数が足りないことをqemuから警告されるハズである。 C:\Users\ユーザー名>qemu-img qemu-img: Not enough arguments Try 'qemu-img --help' for more information のように、qemuから警告されれば、ひとまずqemuのインストールは成功である。 === 使い方 === あらかじめ、起動したいファイルを機械語で作っておき、たとえば、testos.img とかの名前をつけて、ホームディレクトリーなどコマンド端末の認識できる場所に保存しておく。 そしてコマンド端末で <pre> qemu-system-i386 testos.img </pre> のようにコマンド<code> qemu-system-i386 </code> を使えばいい。 では、そのOSイメージをどうやって作るか。 原理は、 まず、アセンブラの nasm で書く。(nasm は Netwide Assembler ともいう。) :※ (gccだと難しくなるので、OS制作ではgccは使わないほうがイイ。gccによる出力は、標準設定では、Windowsの実行ファイル(PEフォーマットなど)に自動変換して、OSそのものの自作には余計な情報を負荷してしまう。そうしないためには、引数であれこれと設定する必要がある。gccでアセンブリコードをそのまま機械語にしようとすると、引数がけっこう多くなる。しかも残念なことに、日本のネットには、この操作を詳しく解説した資料が無い。) :なので、 nasm を使おう。 あらかじめアセンブラコード形式で、OSにしたいファイルをアセンブリコードで作っておいて、testos.asm などの名前で保存しておく必要がある。 nasmなら、testos.asm を(PEフォーマットでない、直訳の)機械語にするコマンドは <pre> nasm testos.asm -o testos.img </pre> だけで終わる。 そして、こうして作成したブートイメージをqemuで起動する方法は、ホームファイルに先ほど作成した testos.img を置いた上で、 <pre> C:\Users\ユーザー名>qemu-system-i386 testos.img </pre> のコマンドだけで終わる。 では、元になるアセンブリコードをどうやって調達するか? とりあえず、ネットで読者の勉強用に(彼らの)自作OSのブートローダーのアセンブリコードを公開してくれている人がチラホラといるので、彼らのコードで実験するのが良いだろう。 :※ いちおう、本書でも、初等的なブートローダのコードを記載している(※ 後述)。 == Bochs の使い方 == ネット上に Bochs の使い方の入門書がぜんぜん無いので、wikibook で教えることにする。 Bochsでは、アセンブルはできない。 Bochsの用途は、すでに別ツール(たとえば nasm んど)で作成ずみの img ファイルをBochsで起動するだけのものである。 asmファイルからimgファイルへのアセンブルは、あらかじめ nasm などで行っておく。 Bochsの利便性は、コマンドを覚えなくて言いことである。起動コマンドのBochsだけ押せばウィンドウが起動するので、あとはそのウィンドウ側でGUI的に操作してエミュレータの起動をできるという便利ツールなエミュレータが Bochs である。 さて、Boshs をインストールしてから、環境変数(パス)の設定を終えれば、 コマンドプロンプトで、コマンド <code>bochs</code> で起動する。つまり ユーザー名>bochs のように「bochs」の部分を入力する。 で、起動するとダイアログ画面が現れる。 さて、これだけでは、そもそも何のファイルを起動するかすらも設定されてない。なので、これから、このダイアログ画面で、それを設定する。 まず、真ん中の項目(中央ペイン)にある「Edit Option」 の「Disk & boot」をダブルクリックすると、画面が遷移して、 オプション画面である「Bochs Disk Options」画面になる。この項目で、何のファイルを起動するかを設定できる。 そのためには、 その「Bochs Disk Options」画面の中で、タブ「ATA Channel 0」> 子タブ「First HD/CD on Channel 0」 をクリックすると出てくる画面に、 上から2段目あたりに :Path or physical device name <span style="border-style:inset">        </span> <span style="border-style:outset">Browse</span> という項目があるので、その <span style="border-style:inset">        </span> のなかに、起動したいimgファイル名を入れる。 たとえば、「testos.img」ファイルを起動したいなら、 :Path or physical device name <span style="border-style:inset">testos.img     </span> <span style="border-style:outset">Browse</span> のようになる。 こうして、(おそらく)あとはこのオプション画面を終了して(ダイアログ・ウィンドウの右上のクローズ用の×ボタンを押せばいい)メインメニュー画面に戻り、右ペインにあるStartボタンを押せばいい。 Panic ウィンドウが表示されて Message 欄に「specified geometry doesn<nowiki>'</nowiki>t fit on disk」 と書いてあるが、このまま左下の欄にある Continue をクリックして、OKを押せばいい。 なお、Path or physical device name の設定をしてないで空欄のままにしておくと、Startの際に Message 欄に 「no bootable device」 と出る。 BochsのDtart>OKの後のエミュレート起動後の終了方法は、ウインドウの上部にあるメニューバーの右側のほうに、○印の中にタテ線「|」のある終了ボタン「(|)」があるので、これを押せばいい。(右上の×ボタンは使えない。×ボタンをクリックしても反応しない。) == 擬似命令を使ってブートローダを作ろう == === 擬似命令とは === 一般的なアセンブラには DB 命令というのがあり、これはORG命令などで指定したメモリに値を書き込む命令であるが、これで機械語も書き込みできる。 :備考: なお、DB命令やORG命令は、(CPUに対する命令でなく)アセンブラに対する命令なので「擬似命令」(ぎじ めいれい、pseudo-instruction)という。コンパイラなどにより機械語に翻訳する際、擬似命令は翻訳されない。というか、そもそも翻訳の指示に関する命令なので、翻訳内容ではないので、擬似命令は 機械語にならない のは当然である。 :※ 擬似命令とは、たとえるなら(C言語などの)高級言語でいう、いわゆる「マクロ」のようなものである。 もし、機械語を書き込む先を、メモリではなく、ハードディスクやUSBメモリやフロッピーディスクなどのブート可能なメディアにすれば、原理的には、これでブートローダを作れる。 :※ たとえばマイナビ出版の『OS自作入門』(川合秀美 著)では、まさにこの方法でブートローダやそれから起動するGUIつきOSを作っている。 なお、DB とは data byte の略だと言われている。 さて、では、OSを作るためには、まず、ブートセクタを書き込めばいいのですが、では、どういう内容のことを書き込めばいいのでしょうか。 === ブートローダ === まず、ブートローダを書き込むわけですが、 規格により、 :MBRのサイズは512バイトと決まっており、 また、 :ブートローダと認識させるために必要な署名は、512バイト目の最後の2バイトに16進数で「aa55」と書き込まなければならない(※ 511バイト目が「aa」、512バイト目に「55」である)、 と決まっている。 なので、このために <syntaxhighlight lang="asm"> times 510 - ($ - $$ ) db 0 db 0x55 , 0xaa </syntaxhighlight> をどこかに書き込む必要があります。 <code> times </code>とは、nasm の擬似命令のひとつで、繰り返し命令のことです。 「aa55」の署名を書き込まずにQemu上で機械語を起動しても、いくつかのメッセージのあとに「No Bootable device」などと表示されるだけです。 さて、上記コードの場合は :510 - ($ -$$) 回数だけ、db 0 (つまり「0を書き込め」)を繰り返せ、 という命令です。 $ は、そのtimes命令が出されたときの現在のアドレスです。 $$ は、現在のセクションの最初のアドレスです。 [[File:Little-Endian-ja.svg|thumb|リトルエンディアンの仕組み]] 間違えて、「55aa」(マチガイ!)を書き込まないようにしてください。詳しくは『[[w:エンディアン|w:リトルエンディアン]]』で調べてください。 MBRのサイズは512バイトと決まっており、その末尾2バイトに「aa55」と書き込むので、times 繰り返し命令 では「510」と2バイトぶん、余らせています。 なので、とりあえず下記のように書き込みましょう。 ;コード例 :(※ 実際に動く。 windows7 上の qemu で動作を確認。) <syntaxhighlight lang="asm"> mov ah, 0x0e ; 1文字出力 mov al, 'H' int 0x10 times 510 - ($ - $$ ) db 0 db 0x55 , 0xaa </syntaxhighlight> 成功すれば、 qemu上で、「H」と表示されます。 <code>int 0x10</code> とは、ディスプレイへの割り込み命令のひとつです。int でBIOSにより割り込み命令を指示しています。intの引数で、どんな割り込みをするかを指示しており、<code>int 0x10</code> はビデオサービスの割り込みです。 ですが、<code>int 0x10</code> だけでは、ディスプレイに文字も画像も表示できません。 <code>int 0x10</code>に加えて、さらに、何を割り込ませるかの指定を行う必要があり、<code> mov ah, 0x0e </code> で文字割り込みを指定しています。(※ 詳しくは『[[:en:w:INT 10H]]』(英語版ウィキペディア)などを参照してください。) :ah は、アキュムレータ レジスタ の上位ビットの部分です。 :al は、アキュムレータ レジスタ の下位ビットの部分です。 <code>int 0x10</code> の命令は、上記の手本コードのように、 アキュムレータ レジスタで指示しなければなりません。 なお、学校などで、もしかしたら、情報科学・計算機科学の教育では「アキュムレータ」とは「加減乗除などのためのレジスタ」とか習うかもしれませんが、しかし実際のCPUでは、(上記コード例のように)設定などの一時保存にもアキュムレータが流用されています。 :(※ 要確認)また、電源の投入直後(いわゆる「ブート」の直後)に使用できるレジスタは、まず16ビットCPU時代のレジスタだけです。32ビットCPUや64ビットCPU時代に追加されたレジスタは、初期状態では使用できないです。つまりraxやeaxは、16ビットCPU時代のモードでは使用できないです。axなどは16ビットCPU時代のモードで使用できます。 :16ビットCPU時代のモードを「リアルモード」といいます。32ビットCPU時代以降のモードを「プロテクトモード」といいます。 :2010年代の現代のパソコンでもリアルモードは、下位互換性(かい ごかんせい)などのために残されています。下位互換性とは、古いバージョンのプログラムが動くようにするという事です。 :一般的名パソコンでは、ブート直後(電源の投入直後)はリアルモードになっています。言い換えれば、ブート直後はプロテクトモードではないです。 :なおモードの切り替え方法は、CR0レジスタ(というのがある)の最下位ビットの値が1ならプロテクトモードになります<ref>林高勲 著『X86系コンピュータを動かす理論と実装 作って理解するOS』、技術評論社、2019年10月9日、235ページ</ref> <ref>Igor Zhirkov 著、古川邦夫 監訳『低レベルプログラミング』、翔泳社、2018年01月19日 初版 第1刷 発行、53ページ</ref>。CR0の最下位ビットのが0ならリアルモードです。実際には、プロテクトモードの移行のためには、さらに グローバル デスクリプタ テーブル(GDT)というものを作成する必要があるが、初学者には当面は知らなくていいので、もうプロテウトモードの説明は後回しにする(※ 現時点では未記述)。 さて、この場合での int 0x10 は、alレジスタにある文字を表示できます。 「Hello 」と表示させたければ、「H」だけでなく、同様の操作を繰り返し、「e」「l」「l」「o」を追加で表示させればいいだけなので、 ;コード例 『基本』 :(※ 実際に動きます。 windows7 上の qemu で動作を確認。) <syntaxhighlight lang="asm"> mov ah, 0x0e ; 1文字出力 mov al, 'H' int 0x10 mov al, 'e' int 0x10 mov al, 'l' int 0x10 mov al, 'l' int 0x10 mov al, 'o' int 0x10 times 510 - ($ - $$ ) db 0 db 0x55 , 0xaa </syntaxhighlight> でブート後に「Hello」と表示できます。 === 発展的な話題 === ラベルやジャンプ命令を使うと、繰り返し命令を実装できる。 上の「Hello」のプログラムを、ラベルなどによる繰り返し処理でプログラムするとするなら、下記のようになるl ;コード例 『発展』 :(※ 実際に動きます。 windows7 上の qemu で動作を確認。) <syntaxhighlight lang="asm"> org 0x7c00 mov ah, 0x0e mov bx, aisatu kurikaesi: mov al, [bx] int 0x10 add bx, 1 ; 使い終わったので 1文字ぶん、進める cmp al, 0 ; 0に等しければ je owari ; (0に等しければ)owariにジャンプしろ jmp kurikaesi ; (条件に関わらず)kurikaesi を実行しろ ; ここまでラベル kurikaesi の内容 aisatu: db "Hello aisatu", 0x00 ;文字の終わりとして 0x00 を使用した times 510 - ($ - $$ ) db 0 db 0x55 , 0xaa owari: </syntaxhighlight> ;org 0x7c00 org 0x7c00 とは、このようなテキスト処理をするのにBIOSに予約されている領域が7c00 なので、そこから書き始める必要がある。 org は擬似命令であり、これからの書き込みのメモリ位置を指定する命令である。 実際、実験してみると、上記コードの冒頭に org 0x7c00 を削除してみて実行しても、文字が出力されない(実験すれば分かる)。qemuの実装はそうなっている。 コード例『基本』ではorg0x7c00が無くても文字出力できたのに、コード例『発展』では0rg0x7c00が無いと文字出力できないのは奇妙かもしれないが、ともかく qemu の実装がそうなっている(そして、おそらく市販のパソコンのBIOSも同様の仕様だろう。 ;<code> mov bx, aisatu </code> また、 <code> mov bx, aisatu </code> は形式的には、あたかもラベルaisatuの内容を代入するかのような表現ですが、 実際は、単にaisatu ラベルの先頭のメモリを代入するだけです。 なお、aisatuラベル先にある <code> db "Hello aisatu", 0x00 </code>も、単に、aisatuラベルの先頭の位置から順番に「H」「e」「l」「l」「o」 (以下略)に対応するアスキーコードを代入しているだけです。 bx とは、単なるbxレジスタ(ベースレジスタ)。siレジスタ(ソースインデックス)で書いてもいい。 というか、ソースシンデックスで書くほうが、お行儀がいいだろう。 本書wikibooksでは単にアルファベット順で「A」の次は「B」なので、ソースインデックスを紹介するのがメンドウなので、BXで代用した。 また、ラベル(たとえば aisatu ラベル)の中身を定義する前に、<code>mov bx, aisatu </code>のように、先にラベルを代入するなどの指示をする必要がある。 C言語になれていると宣言の順序が逆なので奇妙だが、ともかくアセンブラでは、こうである。(おそらくだが、(文法の形式ではコピー・代入だが、)実際はマシン内部では作業用メモリの確保の処理や、それらの複数のメモリ領域どうしの間の関連づけの作業をしているだけなのだろう。(そして、その結果をBIOS作業用メモリのどこかに保存しているのだろう) ) <code> mov al, [bx] </code>について。 仮に、bxに角カッコ<code>[ ] </code>をつけずに <code> mov al, bx </code> と書いても、まずalレジスタとbxレジスタのサイズが合わないのでアセンブル時にエラーになり、「 error: invalid combination of opcode and operands」と表示されるだけである。si(ソースインデックス)レジスタの場合でも同様である。サイズをあわせたいなら「bx」でなく「bl」にする必要がある。 かといってbxからblに書き換えて、 <code> mov bl, aisatu </code> とか<code> mov al, bx </code> とか <code> add bl, 1 </code> とか入力して実行しても、出力結果はワケのわからない文字列のあとに <pre><nowiki> (※ わけのわからない文字列がここら辺にズラズラと並んでから)0123456789:;<=>ABCDEFGHIJKLMNOPQRSTUVWXYZ[_]^`?@abcdefghijklmnopqrstuvwxyz{ (※ このあと、記号やギリシャ語のアルファベットなどの何かの文字列が並ぶ) </nowiki></pre> とか、途中にアスキーコード表の順序どおりのような文字列が表示されるだけである。 なぜこうなるかというと、 mov bl, aisatu のあとに <code> mov al, bl </code> をすると、あたかもalに aisatu ラベルを入力するかのように見えますが、そうではなくalに代入されるのは、aisatuラベルの最初のアドレスの番号です。 なので<code> add bx, 1 </code> で1文字ぶんを進めることができるわけです。 私たちは、アドレス番号ではなくて、そのアドレス番号のメモリにあるデータの中身(内容は文字のアスキー)を表示したいわけですので、<code> [ ] </code> でククる必要があります。 C言語になれていると、ついつい、何の記号もない「変数っぽい?」何かは(勘違い→)「きっとアドレス番号ではない」と思い勝ちですが、しかしアセンブラではむしろ逆で、movm命令の2番目の引数は、記号のついてないほうがアドレス番号の解釈になります。 また、代入される側(上記の例では al )は、代入された数値の由来は不明であり、数値の由来がはたしてアドレス番号に由来なのか、あるいは、電卓みたいな加減算をしたいのか、なんにも知りません。 たとえば、もし bl レジスタに保管されている(メモリの)アドレス番号が200番だとして、 <code> mov al, bl </code>をしたら、alに200が保存されますが、しかしalはその「200」が何なのか知りません。200円の価格の商品の計算なのか、全校生徒が200人の小学校なのか、アドレス200番なのか、alには、知るよしが無いのです。 ;int 0x10 int 0x10 は、繰り返し命令の中で、毎回、使用する必要がある。 さて、もし上記コード中の int 0x10 の位置を移動して、繰り返しの終了後に移動して「owari」ラベルで int 0x10 をまとめて実行しようとしても、文字出力はされない(実験すれば、そうなる)。 このことから、int 0x10 は、単にディスプレイ出力をするだけの命令ではなく、文字出力に必要なメモリ処理をしていることが分かる(※ もし、単にディスオプレイの画面後進をするだけなら、あとでマトメて処理してもいいハズになる)。おそらく org 0x7c00 で宣言したメモリ領域以降に、情報を書き込んでいるのだろう。 「cmp」とは比較命令で、等しいかどうかを調べて報告する命令で、出力は「真」か「偽」のどちらかであり、等しければ真、等しくなければ偽である。 そして、「je」とは条件つきジャンプで、直前の条件判定が「真」なら、指定したラベルにジャンプする命令である。 ;その他の例 次のようlodsb 命令とsiレジスタを使っても良い。lodsbは[ds:si]からalに1バイト読込む(ロード load)命令であり、さらに使用後に自動的にsiレジスタの指し示す位置を1バイトぶんだけインクリメント(DF=0の場合、DF=1の場合はデクリメント)してくれるので、手間が省ける。 ※ 2022年現在のx86プロセッサは、x86命令セットをマイクロ命令に分解し、マイクロ命令の組合せによっては複合的なマイクロ命令に合成し実行しています。ところが、lodsbの様な複雑な命令はマイクロ命令に翻訳されず固定的なマイクロコードにより実行されます。このため、かつて命令読込みのオーバーヘッドがなくせるという理由で「最適化」の代表だった複雑な命令を使うことは、現在は実行速度を低下させることになります。 ;コード例1 <syntaxhighlight lang="asm"> org 0x7c00 mov ah, 0x0e ; 1文字出力を設定 mov si, msg LOOP: lodsb cmp al, 0x00 je Loop_break int 0x10 jmp LOOP Loop_break: msg: db 'Hello, World!', 13, 10, 0 times 510 - ($ - $$ ) db 0 db 0x55 , 0xaa </syntaxhighlight> 解説 lodsb の内容は <syntaxhighlight lang="asm"> mov al, [si] inc si </syntaxhighlight> と等価である(DF=0の場合、また OF, SF, ZF, AF, PF は inc si の結果により修飾されるので厳密には異なる)。 ;その他の例2 cmp al, 0x00 je Loop_break の代わりに test al, al jz Loop_break でも良い。 また test の代わりに or al, al jz Loop_break でも良い。 ※ かつては、定数とレジスタの比較はレジスタファイルの読出しハザードがありストールの原因になりましたが、[[W:Sandy Bridgeマイクロアーキテクチャ|Sandy Bridgeマイクロアーキテクチャ]]以降のプロセッサであればマイクロフュージョンの対象となり、test命令やor命令を使うメリットはなく、專ら可読性を損なうだけです。 ;コード例2 <syntaxhighlight lang="asm"> org 0x7c00 mov ah, 0x0e ; 1文字出力を設定 mov si, msg LOOP: lodsb test al, al jz Loop_break int 0x10 jmp LOOP Loop_break: msg: db 'Hello, World!', 13, 10, 0 times 510 - ($ - $$ ) db 0 db 0x55 , 0xaa </syntaxhighlight> === メモリ直書き === ==== グラフィックのVRAM直書き ==== まず、設定として、 <syntaxhighlight lang="asm"> mov al, 0x13 mov ah,0x00 int 0x10 </syntaxhighlight> というコードが必要です。 int 0x10 はグラフィック割り込みです。 グラフィック割り込みの場合、ahは0に固定するように規格で決まっています。 alによって、ビデオモードを指定しています。 alが0x13なら、320 x 200ドット x 16色モード(8bitカラー) という意味です。 一般的なパソコンではグラフィック描画用のVRAMアドレスは 0xa0000 から 0xaffffの領域が割り当てられています。 なので、mov命令で、このアドレスに書き込むと、VRAMに直書きできます。 で、問題は、通常の16ビットCPUモードのmov命令では、 メモリ番号は4ケタまでしかアクセスできない。「a0000」や「affff」は5ケタであることに注目。 で、しかも、ブートローダ起動中のリアルモードでは、この16ビットCPUのモードである(らしい) なので、ともかく、通常の方法ではアクセスできない。 5ケタのメモリ番号にアクセスするためには、 「セグメント方式」という手法を使う。 簡単に言うと、 :物理アドレス番号 = セグメントベース値×16 + オフセット値 なお、上式の数は十進数である。 16進数になおすと、単にセグメントベース×16は、末尾に0をつけたすだけである。 :※ セグメントベース値の1の違いはオフセット値に換算すれば たった16 なので、よって、もし2つの物理アドレス番号があって、それらのセグメントベースの値が違っていても、オフセット値でそのぶんの差を補う加減があれば、2つの物理アドレス番号が重なることがあるし、用途によっては重なっていても構わない<ref>白崎博生 著『Linuxのブートプロセスをみる』、株式会社KADOKAWA(発行)、アスキー・メディアワークス(プロデュース)、2014年10月2日 初版、20ページ</ref>。 :また、2つのアドレス番号があって、セグメントベース値とオフセット値がそれぞれ異なっていても、「セグメントベース値×16 + オフセット値」の合計値が同じなら、それは同じアドレスを指し示す処理になる<ref>白崎博生 著『Linuxのブートプロセスをみる』、株式会社KADOKAWA(発行)、アスキー・メディアワークス(プロデュース)、2014年10月2日 初版、25ページ</ref>。たとえば 0000:1000 と 0100:0000 は同じアドレスを指し示す(※ 文献『Linuxのブートプロセスをみる』での例)。 これらのセグメントベースを格納するために「セグメントレジスタ」と言う専用のレジスタを使う。 16ビットCPUのセグメントレジスタには :CS (コード セグメント)、 :DS (データ セグメント)、 :ES (エクストラ セグメント)、 :SS (スタック セグメント)、 の4つがある。 なおFSとGSは32ビットCPU以降のセグメントレジスタである。 CSは、CPUが実行するプログラムを格納するためのセグメントとして、CPUに使用させる。 DSは、メモリの読み書きといったデータ関係の手段のセグメントとして、CPUに使用させる。 SSはスタック関係のセグメントで使用。 「エクストラ」とは、「その他」とか「追加の」のような意味。 よく分からなければ「セグメントベース」でググると、詳しく紹介してくれている親切なITブロガー日本人さんが何人かネットにいるので、それらのページを参照してください。 で、書式は、<code>[セグメントベース:オフセット]</code>の書式である。 下記のようなコードで、ブート直後の画面の任意の場所にピクセル単位で色をぬれる。 ;コード例 1 <syntaxhighlight lang="asm"> mov AL, 0x13 ; ビデオモード0x13 mov AH, 0x00 int 0x10 mov BX, 1111 ; ピクセルで書き込みたいアドレスの計算用 mov AX, 0xa000 ; VRAMアクセスのためのセグメント処理で使用 mov DS, AX mov AL, 0x01 ; 色の設定 mov byte [DS:BX], AL ; VRAMに書き込み mov BX, 1112 ; 次に書き込みたいアドレスの計算用 mov byte [DS:BX], AL ; VRAMに書き込み(以下、同様) mov BX, 1113 mov byte [DS:BX], AL mov BX, 1114 mov byte [DS:BX], AL mov AL, 0x031 ; 色の変更 mov BX, 1115 mov byte [DS:BX], AL mov BX, 1116 mov byte [DS:BX], AL mov BX, 1117 mov byte [DS:BX], AL mov BX, 1118 mov byte [DS:BX], AL mov BX, 1119 mov byte [DS:BX], AL mov BX, 1120 mov byte [DS:BX], AL mov BX, 1121 mov byte [DS:BX], AL times 510 - ($-$$) db 0 dw 0xAA55 </syntaxhighlight> ;予備知識 :: mov命令によるメモリへの書き込み  さて、mov 命令でメモリに書き込むには <code>mov BYTE [123], 0x4567 </code> の書式で書き込みます。 この場合、メモリの123番地に、数値(16進数で)4567を書き込むわけです。 <code>[ ]</code> をつけると、メモリへの指示だとアセンブラなどが認識します。 ここでの「BYTE」 は1バイト長で書き込め、という命令です。 2バイト長なら(BYTE でなく) WORD になります。 4バイト長さなら DWORD になります。 :※ なお、WORDやDWORDを使う場合、リトルエンディアンの順序で書き込まれます。 なお :<code>mov al, BYTE [123] </code> のように書いた場合は、メモリ123番地にある内容をレジスタalに書き込め、という命令になります。 このように、(書き込みだけでなく)メモリからの読み込みにも <code>[ ]</code> は使えます。 つまり、 <code>[ ]</code> をつけると、メモリへの指示だとアセンブラなどが認識します。 ;コードの解説 0xa0000は画面の左上だが、そこに色を塗っても見づらいので、 上記コードでは 0xa1111 から色を塗り始めることにした。 なお 0xaffff は画面の右下である。 画面の真ん中の上のほうに、なんか緑色っぽい線が5ミリくらいの長さで水平に引かれている結果が表示されると思う。 上記のコードでは、分かりやすさを重視して、あえて繰り返し命令(ラベルやジャンプ命令で実装できる)を使わなかったが、実際に図形を書きたい場合は、ラベルを活用して繰り返し命令で処理するのが効率的だろう。 なお、上記コード例1で <syntaxhighlight lang="asm"> mov AX, 0xa000 mov DS, AX </syntaxhighlight> とあるが、 これを、(下記はエラーになる) <syntaxhighlight lang="asm"> mov DS, 0xa000 </syntaxhighlight> とまとめても、なぜかエラーになる。 なので、手本のコードのように、レジスタを経由する必要がある。 ==== テキスト直書き ==== :※ 調査中 一般的名パソコンでは、英数字などのテキスト出力も、ブート直後の段階では、専用のメモリ領域が用意されるので、このメモリを書き換えることで、テキスト文字を出力できます。(ただし、漢字や平仮名・カタカナなどは無理。) ブートプログラムの確認作業などに、便利な機能でしょう。 また、 int 命令によって、1文字ずつ書いていく方法は、原理は単純ですが、実装では、処理速度があまり速くないという問題があります。 ラベル命令やジャンプ命令などを使ってコードの行数を減らしても、int命令で書き込みをするよりも、テキスト用メモリを直に書き換えするほうが処理速度が速くなります。 一般的なパソコンでは 0xb800 からの領域がテキスト用メモリに割り当てられています。 なので、まず <syntaxhighlight lang="asm"> mov ax, 0xb800 </syntaxhighlight> と指定します。 === BIOSに予約されたメモリ領域 === メモリ領域のうち、0xa0000 から0xfffff までの領域は通常のパソコンでは、BIOSがハードウェアを管理するために使用することになっています<ref>白崎博生 著『Linuxのブートプロセスをみる』、株式会社KADOKAWA(発行)、アスキー・メディアワークス(プロデュース)、2014年10月2日 初版、70ページ</ref>。 このため、それらハード管理以外のソフトウェア的な処理をするためにメモリ使用したい場合は、この領域を避けてメモリを使用する必要があります。 こういった用途には Linuxなどの現代のオープンソースOSでは、 メモリを使用する際には 0x100000 以降の領域を使うのが一般的です。 原理的には 0xa0000 未満の領域も使用可能ですが、使いすぎ等のミスによって0xa0000以降にハミ出る恐れがあるので、なるべく 0x100000 以降の領域だけを使うほうが安全でしょう。 == ハードディスクなどへのアクセス == まず、フロッピーディスクやハードディスクなどに読み書きのできる割り込み命令で、 int 0x13 というのがあります。 2000年代の現代では、これを大容量デバイス用に拡張した拡張 int 0x13 というのがあります。 どちらの int 0x13 とも、ドライブ番号は、DLレジスタ(データレジスタの下位(Low)の部分)で指定します。 このように、int 0x13 では、割り込み時におけるレジスタの役割が決められています。 ;拡張 int 0x13 さて、拡張 int 0x13 を使って、フロッピーディスクやハードディスクなどの記憶媒体に割り込みをできます。(USB対応については今後の見通しは不明。書き込みできるものもあるようだが、) int 13h は、レジスタなどの数値で 書き込みの方式や対象を指定します。拡張 int 13h と、非格調 int 13h では、レジスタの解釈が違っております。 格調 int 0x13 のほうの方式を LBA方式といいます。 {| class="wikitable" |+ 格調 int 0x13 (LBA方式)の仕様 |- | AH || 読み込みは 42h で固定 |- | AL || 読み込むセクタ数 |- | DL || ドライブ番号 |- | DS:SI || Disk Address Packet のアドレス |- |} 格調 int 0x13 では、レジスタに収まりきらない様々な情報を、任にの Disk Addres Packet (DAP)という場所に配置しており、その形式も決まっています。 ※ 調査中 ;非拡張の int 0x13 なお、拡張されてない int 0x13 は、ハードディスク容量などの小さい時代の古い規格のものであり、現代では、読み書きに時間が掛かったり、あるいは不可能です。 非拡張の int 0x13 では、ドライブ番号は、DLレジスタ(データレジスタの下位(Low)の部分)で指定します。 AHレジスタが 0x02 なら 読込み、AHレジスタが 0x03 なら 書込み です。 {| class="wikitable" |+ 仕様 |- | AH || 読み込みは 0x02 で固定 |- | AL || 読み込むセクタ数 |- | CH || トラック番号(下位8ビット) |- | CL || |- | DH || ヘッド番号 |- | DH || ヘッド番号 |- | DL || ドライブ番号 |- | ES:BX または ES:EBX || 読み込みたい先のアドレス |- |} ;参考サイト :[http://caspar.hazymoon.jp/OpenBSD/misc/hdd.html ディスクBIOS] :[http://jou4.hateblo.jp/entry/2012/12/15/120611 INT 13h - jou4のブログ] {{code|int 13h}}ともいう。 ;参考文献 :林高勲『作って理解するOS』 328ページで、非拡張 int 13h のCHS方式について解説あり。 == キーボードサービス == === int による割り込み === まず、int命令で、キーボードサービスの割りこみがあり、 int 0x16 がキーボードサービスである。 ;コード例 <syntaxhighlight lang="asm"> mov ah, 0x0e ; 1文字出力 mov al, 'p' ; 「pushしろ」・・・のつもり int 0x10 mov al, ' ' int 0x10 mov al, 's' ; 「space」・・・のつもり int 0x10 mov al, ' ' int 0x10 mov al, ' ' int 0x10 .LOOP: mov ah,0x00 ; キーボード入力待ち. 0x10 でもいい int 0x16 cmp al, ' ' ; 空白なのでスペース jne .LOOP ; 直前の比較cmpの結果が偽(否定)だったらループする mov ah, 0x0e ; 1文字出力 mov al, 'f' ; 「finish 終わったよ」・・・のつもり int 0x10 times 510 - ($ - $$ ) db 0 db 0x55 , 0xaa </syntaxhighlight> さてint 0x16 を呼び出す際、 mov ah,0x00 ; キーボード入力待ち. 0x10 でもいい なら、ah = 0x00 は、キーボードのキー入力待ちである。ah = 0x10 だと拡張キーボード対応らしい[http://softwaretechnique.jp/OS_Development/Tips/Bios_Services/keyboard_services.html] 。 === in または out命令による処理 === 実は一般的なパソコンでは、アセンブリ言語の命令で、いくつかのハードウェアに読み書きのアクセスするための、専用の命令がある。 <code>IN</code> 命令と、 <code>OUT</code>命令である。 そして、キーボードなど、昔のどこのパソコンにも存在したハードウェアは、実はハードウェア番号が決められている(「I/Oポートアドレス」などという)。 たとえば、キーボードはハードウェア番号(I/Oポートアドレス)が十六進数で0x60 番である。(メモリマップとは別。メモリアドレスの0x0060などにdb命令で書き込んでも、目的のハードにはアクセスできない。 ) IN命令で、引数で指定したレジスタ(普通はALレジスタやAXレジスタを指定する)に、もうひとつの引数で指定した目的デバイスから送られた値が保存されます。(引数の順序はアセンブラの種類などによって異なるので、説明を除外。) また、OUT命令で、引数で指定したレジスタ(普通はALレジスタやAXレジスタを指定する)に格納されている値が、もうひとつの引数で目的デバイスに送られます。 たとえば、下記のようなコードで、キーボードの文字「E」または前後のWかRを押すと、1行ぶん下の位置に文字「G」が表示される。 ;コード例 <syntaxhighlight lang="asm"> mov al, 'p' ; 「push e」と表示の予定 int 0x10 mov al, 'u' int 0x10 mov al, 's' int 0x10 mov al, 'h' int 0x10 mov al, ' ' int 0x10 mov al, 'E' int 0x10 mov al, 0x0a ;改行の指示 int 0x10 .LOOP: in al, 0x60 ; in al, 0x0060 でもよい cmp al, 18 ; 値が文字 'E' かどうか判定のつもり jne .LOOP ; 偽なら LOOP 冒頭にジャンプ mov ah, 0x0e ; 1文字出力 mov al, 'G' int 0x10 times 510 - ($ - $$ ) db 0 db 0x55 , 0xaa </syntaxhighlight> ;解説 <code> in al, 0x60 </code> を使えば、キーボードコントローラーから送られてきたキーも al に入力されます。 <code>in al, 0x60 </code> とは、けっして「レジスタ al に 60 を代入しろ!」(×、マチガイ)という意味ではなく(そもそも定数の代入だけなら mov 命令だけで可能である)、「ポートアドレス 0x60番 のポートから送信されてきたデータを、レジスタalに代入しろ」という意味です。勘違いしないでください。 そして、キーボードコントローラーのポートアドレスが 0x60 なので、めでたく、上記コードでキーボードから押されたボタンの情報を受け取れます。 さて、キーボードを押したとき、押したボタンに対応するスキャンコードが、パソコン内部にあるキーボードコントローラー(KBC)という装置に送信される仕組みになっています。 このスキャンコードは、アスキーコードとは異なります。 上記コード例にある cmp al, 18 の数値「18」とは、スキャンコードでの番号です。だいたいスキャンコードで18番のあたりが文字 W,E,R のどれかのあたりです。 また、アスキーでは「2」と「"」とは別の文字ですが、しかし日本語キーボードの場合、「2」と「"」はボタンが同じなので、スキャンコードでは同一になります。 このように、物理的に同じ位置にあるかどうかで、スキャンコードは決まります(なお、JIS配列キーボードやUS配列キーボードのように言語が違うキーボードでも、位置が同じなら、ほとんどのボタンのスキャンコードの内容も同じ場合が多い)。 また、スキャンコードは、押されている時に送信されるコード(「メイク コード」という)と、離した瞬間に送信されるコード(「ブレイク コード」という)とが、それぞれ違うコードです。 日本語キーボードは OADG という規格にほぼ統一されています。 ですが、世界的にスキャンコードの規格は、古いものでも3種類くらいあり、さらにUSBキーボードの規格は別です。このため、日本語 OADG のスキャンコードも、現在でも3種類くらいあります。 下記のリンクが詳しいです。 [http://www3.airnet.ne.jp/saka/hardware/keyboard/109scode.html ] なお、一般的に「メイクコード/ブレイクコード」の書式です。 たとえば、ボタン「1」(「!」と同じ)のスキャンコードが「16 / F0 16」とかかれていれば、メイクコードが「16」であり、ブレイクコードが「FD 16」という意味です。(ある規格では、ブレイクコードは、メイクコードの先頭にF0がついたものになっている。) なお、キーボードコントローラーもインテルなどが製造していました。かつて Intel i8042 というキーボードコントローラーが有名でした。 より正確な仕組みとしては、シリアル通信(PS 2 信号)などで送られた信号をKBCあたりでスキャンコードに変換しているわけですが、CPUから見ればスキャンコードしか見えないので、あまり気にしなくていいでしょう。 ;参考サイト [http://softwaretechnique.jp/OS_Development/kernel_loader3.html 0から作るOS開発 カーネルローダその3 プロテクティッドモードへの移行とA20 ] ※ 本wikibooksの当ページが完成するまでの間、上記の参考サイトが分かりやすくて役立つと思いますので勉強してください。 === 出力例? === 次のようなコードを使えばledが点滅するらしいのだが、しかしエミュレータでの実験では分からなかった(Windows起動により、すでにLEDが点灯しているので、区別しづらい)。 <syntaxhighlight lang="asm"> mov al, 0xED out 0x60, al </syntaxhighlight> 0xED というのは、LED点灯に関する命令の番号。 === BPB === 一般的なブートローダのいくつかには、ブートセクタに BIOS Parameter Block (BPB)というものが書かれており、これは BIOS への指示や設定を出すブロックです。 パソコンの電源を投入して、まず最初に起動するのは BIOS なのですから、このブロックが必要です。少なくとも Windows系OSのブートローダーでは、そうなっていると言われています。 このように、ブートセクタは、書式がほぼ決まっています。 <pre> 冒頭でJMP命令で ブートローダ(IPL: Initial Program Loader)へジャンプ BPB IPL 位置0x01FE に 0x55AA と書いて「ここまでがブートローダ」だとBIOSに認識させる </pre> という構成になっています。 ジャンプしてしまうので、BPB はプログラムカウンタでは読み取れず、BPBはBIOSしか読み取れないことに注目しましょう。 市販のOS自作本にある、DB命令で書き込む冒頭の 「DB 0xeb」 と言うのも、このJMP命令のことです。 JMP命令はX86系CPUの機械語では <code>eb</code> です。 [https://www.intel.co.jp/content/dam/www/public/ijkk/jp/ja/documents/developer/IA32_Arh_Dev_Man_Vol2A_i.pdf 『IA-32 インテル®アーキテクチャソフトウェア・デベロッパーズ・マニュアル』『中巻A:命令セット・リファレンスA-M』3-411] == プロテクトモード == プロテクトモードとは、CPUの32ビットモード(および32ビット以上のモード)のこと。 32ビットモードには、アクセス権の無い状態からのアクセスを禁止するという、特権レベルによる保護機能などがあるので、プロテクトモードという。 プロテクトモードにいこうするためのコードの一部を抜粋すると、おおむね書きのような感じになる<ref>白崎博生 著『Linuxのブートプロセスをみる』、株式会社KADOKAWA(発行)、アスキー・メディアワークス(プロデュース)、2014年10月2日 初版、98ページ </ref>。 ;コード例 <syntaxhighlight lang="asm"> mov eax, cr0 ; or ax, 1 ; mov cr0, eax ; 最下位ビットに1を設定 jmp ジャンプ先のラベル ジャンプ先のラベル: mov ax, ここに何か ; mov ax, 0x10 mov ds, ax mov es, ax mov fs, ax mov gs, ax </syntaxhighlight> ;解説 cr0レジスタの最下位ビット(PEビットという)が1だとプロテクトモードである、という仕様である。 <syntaxhighlight lang="asm"> mov eax, cr0 or ax, 1 mov cr0, eax </syntaxhighlight> の3行の処理で、cr0レジスタの最下位ビットを1に設定している。なお、このcr0の最下位ビットのことをプロテクト・エネーブルド pr0tect enebled という意味でPEビットという。 設定後にわざわざジャンプ命令 jmp を通す理由は、CPUの先読みした命令を破棄するためである<ref>白崎博生 著『Linuxのブートプロセスをみる』、株式会社KADOKAWA(発行)、アスキー・メディアワークス(プロデュース)、2014年10月2日 初版、98ページ </ref><ref>林高勲 著『X86系コンピュータを動かす理論と実装 作って理解するOS』、技術評論社、2019年10月9日 初版 第1刷 発行、471ページ</ref> 。ジャンプ命令には、先読みを破棄する機能がある。 なお、パイプラインという仕組みにより、CPUは先読みしている。このパイプラインの先読みを破棄することをフラッシュという。 実はCPUは、いくつか先の命令をすでに先読みしている(これがパイプライン)。プロテクトモード以降では、それが不具合の原因になるので、いったんフラッシュする(カラにする)必要がある。 なので、CPUのパイプラインをフラッシュするためにジャンプ命令を使っている。 ;全体像 さて、一般にWindowsやLinuxなどのOSには、パーティションという、インストール時にハードディスクの使用領域を決める機能がある。 実はCPU側に、メモリに関する機能だが、似たような動作を機能がある。 GDT(グローバル ディスクリプタ テーブル Global Descriptor Table)といって、メモリのアドレスのどこからどこまでがそのCPUで使える領域を定義する機能がある。 で、プロテクトモードでは、あらかじめ、このGDTを設定しないと動作しない。そういう仕様で、むかしのインテルあたりの人が決めてしまったので、従うしかない。 で、実はCPUにGDTレジスタ(GDTR)という、GDTの場所を保管する専用レジスタがあるので、このGDTレジスタにGDTのアドレスなどの情報を入れる必要がある。 さらに、このGDTレジスタに書き込むための専用の命令 lgdt (ロードgdt)があるので、これを使う必要がある。(「書き込みだから save では?」という疑問も、わくかもしれないが、こういう名前に決まってしまってるので、従うしかない。) 同様に IDT(Interrupt Descriptor Table)というのがある。 さらに、16ビット時代の昔はCPUのアドレスバスが20本までだったので、リアルモードでは利用するアドレスバスが20本までという制限が掛かっており、A00からA19までを使用している。A20以降はマスクされている。 この制限のことを「A20のマスク」という。プロテクトモードに以降するためには、このA20のマスクを解除しないといけない。 下記の順序で作業しないといけない。そういう仕様である。 #  GDT(Global Descriptor Table)の作成 #  GDTレジスタの設定 #  IDT(Interrupt Descriptor Table)の作成 #  IDTレジスタの設定 #  A20のマスク解除 #  CPUへの割り込み禁止 #  cr0レジスタの最下位ビット(PEビット)を1に設定 #  CPUの先読み(パイプライン)を除去する(jmp命令で除去できる) #  セグメントレジスタの設定 A20マスクの解除には複数の方法がある。 * キーボードコントローラーから解除 * System Control Portから制御 * BIOSの割り込み命令 int 15 で解除 キーボードコントローラから解除できる理由は、単に昔のインテルかどこかの人が設計したとき、たまたまキーボードコントローラ用のアドレスバスが余ってたからだけと言う理由らしく、あまり技術的な深い意味は無い。 なお作業の順番について、A20のマスク解除の順場は多少前倒しになっても平気なようである。 == Linuxのブートローダはkernelには無い == ある程度、理解が進むと、 Linux など実際に活用されているオープンソースOSのブートローダを調べたいと感じるかもしれません。 まずOSの起動で最初に動くのはブートローダだからです。 しかし Linux を開発している kernel.org のサイトには、ブートローダは無いのです。 Linux で仕様されているブートローダは、Gnu(グニュー)というオープンソース・ソフトウェア団体の作っている GRUB (グラブ)というソフトウェアです。 なのでブートローダをソースコードを探す場合も、Gru Grub のウェブサイトを探す必要があります。 書籍だとアスキー出版『Linuxのブートプロセスを見る』などの題名の書籍で Grub を紹介してるので、ついつい何となく、ソースコードを読むためにリーナスの管理している kernel.org を探しがちですが、しかし、よくよく考えたら、Grub は Linux ではありません(実際、Windows版Grubもある)。 もし『'''Grub'''のブートプロセスを見る』だと売れないので、出版社が「Linuxのブートプロセスを見る」という題名にしたのでしょう。 私たちOS開発をしたい読者は、けっして出版社にマインド・コントロールされたままでは、イケません。真実「Grub は Linux ではない」に気がつきましょう。 Grub のソースコードのダウンロードにgitコマンド(git clone などのコマンド)が必要なので、あらかじめインストールしておくか、Gitコマンドが最初から使える Ubuntu か Fedora などのLinuxをパソコンにインスト-ルしておきましょう。 Git コマンドのインストールと、Git Hub などのウェブサイトとは別物ですので、混同しないようにしましょう。 '''外部リンク''': [https://git-scm.com/ Gitの公式サイト] なお Windows版のGitはVimエディターにしか対応してないとの情報がインストール時に出ますが、しかしわざわざvimを別途インストールしなくても、Win版GitをインストールすればWindwowsコマンドプロンプトでGitコマンドを使えるようになります。 == 参考文献 == === 書籍出版物 === * 白崎博生 著『Linuxのブートプロセスをみる』、株式会社KADOKAWA(発行)、アスキー・メディアワークス(プロデュース)、2014年10月2日 初版 * 内田公太・上川大介 著『自作エミュレータで学ぶX86アーキテクチャ』、株式会社マイナビ (※出版社名)、2015年8月30日 初版 第1刷 発行、 * 林高勲 著『X86系コンピュータを動かす理論と実装 作って理解するOS』、技術評論社、2019年10月9日 初版 第1刷 発行、 * Igor Zhirkov 著、古川邦夫 監訳『低レベルプログラミング』、翔泳社、2018年01月19日 初版 第1刷 発行、 * このほか、マイナビ出版の『OS自作入門』(川合秀美 著)を参考にしたが(同じ出版社の『自作エミュレータで学ぶX86アーキテクチャ』でも川合氏の文献をところどころ引用的に出して技術解説している)、しかし本書 wikibooks では残念ながら技術内容の確認作業には使えなかった(著者の川合氏が技術内容の正確さよりも初心者の取っ付きやすさを優先しているため。また、ところどころ説明が不十分(アセンブリ言語による各論の理解よりも、読者がC言語でコードを作って動かせることや、全体像の把握を重視している、川合氏の方針のため)。)技術内容の確認作業には、上記一覧の別文献を参考にした。あと、川合氏の文献は2005年の出版物という事もあり、古いので、現代の動向の確認には別文献に当たることになった。 なお、上記文献一覧にある林高勲 著『X86系コンピュータを動かす理論と実装 作って理解するOS』(技術評論社)を、川合氏が監修している。 ただし、直接にこそ川合氏の文献を本wikiは参考にしてないものの、しかし川合氏の文献は日本でのOS自作解説書の草分け的な存在なので、間接的には本wikiも影響を大きく受けているだろう。だからこそ、2019年代の現代でも増刷・再版され続けている(絶版になってない)。 他の著者(名誉のため名前は伏せる)のOS自作本の中には、絶版になってしまったものもある。 == 脚注 == <references/> == 関連項目 == * [[詳細Linux|Linux]] * [[詳細Minix|Minix]] * [[詳細FreBSD|FreeBSD]] * [[IA-32入門|IA-32入門]] == 外部リンク == # [http://softwaretechnique.jp/OS_Development/Tips/Bios_Services/video_services.html 『Tips BIOSサービス割り込み ビデオサービス』] # [https://wiki.osdev.org/Main_Page 『Expanded Main Page - OSDev Wiki』](英語) # [http://elm-chan.org/docs/fat.html#notes FATファイルシステムのしくみと操作法] # [https://www.cqpub.co.jp/column/books/2001a/34331PC_Legacy/default.htm パソコンのレガシィI/O活用大全 ] m1o99euicepmw9hpo9krysjotqjw0td 206670 206669 2022-08-17T03:14:14Z Ef3 694 /* 発展的な話題 */ cleanup; 「であろう」で始まる嘘を削除 wikitext text/x-wiki {{stub}} ;予備知識 本書を読むには予備知識としてアセンブラの知識と、X86系CPUのレジスタなどのアーキテクチャの知識が必要である。 一般的にプログラミングにおいて、ハードウェアの制御は、コンパイラが対応していない命令(特権命令やIO命令など)はアセンブリ言語で記述する事になる。 もし知らなければwikibooks記事『[[X86アセンブラ]]』などで解説してある。特に『[[X86アセンブラ/GASでの文法]]』『[[X86アセンブラ/x86アーキテクチャ]]』『[[X86アセンブラ/x86アセンブラ]]』では初心者むけに説明してある。 本書では触れてないが「カーネル」とか「ユーザランド」とかの用語についてはwikibooks『[[高等学校工業/ソフトウェア技術]]』などで触れてある。 本書はタイトルが今のところは「オペレーティングシステム」だが、実際はコンピュータアーキテクチャ理論やデジタル回路理論など低レイヤーの理論や実務的知識が混在したものになっている(あとで整理する)。大学の科目の分類が縦割りのタコツボ・時代おくれで、全体像が分かりづらいので、予定では、今後の構成でも、意識的にコンピュータアーキテクチャなど関連分野の説明を、整理後にも、ある程度は残しておく予定。 なのでOSと言うタイトルなのにマイコンCPU(Z80など)にも触れているという状況である。 == 総論 == === 学習の方向性 === ==== 概要 ==== オペレーティングシステムは一般に、ユーザーにハードウェアレベルのプログラミングをさせる手間を減らし(ほぼ無くして)、パソコンを使いやすくするためのものです。 なので、オペレーティングシステムの中身は、そういったものになっているハズです。 具体的に言うと、市販のOSなどは、まず起動時にハードディスクとBIOSを作動させ(いわゆる「ブートローダー」 Boot Loader)、つづいてデバイスドライバなどを起動させる仕組みになっています。 私たちが自分でOSを作る場合、BIOSの機能の呼出し命令などは自分で書く必要がありますが、CPUメーカーなどが必要な命令を(int命令など)用意してくれているので、それを使うことで、手間を減らせます。 デバイスドライバなどは、OS制作では、自分で書く必要があります。 さて、ブートの仕組みは、もとになった規格である、ハードディスクの規格が古いため、まずMBR(マスター ブートレコード, Master Boot Record)またはMBRを経由してPBR(パーティション ブートレコード)というのを起動してから、 そのあとにハードディスクの指定された第1セクタをコピーして、そのコピーをメモリ番地の0x7C00 番地に配置して実行する。 ただし、当面は、この番地(0x7C00 )は知らなくても、アセンブラなどを用いて機械語に翻訳する際に、アセンブラが自動的に適切な番地に割り当ててくれます(※ のちの節で後述するコード例でも、当面がこの番地を入力する必要が無い)。 なので、このメモリ上へとコピーされるプログラムが、BIOS以降に最初にOSの起動するプログラムです。 もし「プログラム・カウンタ」という用語を知っていれば(高校の『情報』教科で習う用語です)、プログラムカウンタが最初に指し示すアドレスは、メモリ番地の0x7C00 番地ということになります。 ==== ブートの概要 ==== MBR(Master Boot Record)には、どのPBRを起動するのかの情報や、また、そのPBRはハード上のどの位置に存在しているかの ありか の場所を記述することになります。 このようなブートの経緯の仕組み(ブートプロセス boot process)のため、内蔵ハードディスクのようなブート用の記録メディアの先端○○バイトはどう書くのかが決まっています(ブートセクタ)。このブートセクタの先端領域がMBRの占有する領域であり、そのMBRのなかに情報としてPBRを起動するためのブート情報を書きます。 しかし、私たちが最終的に作りたいのは、あくまでもOSです。ブートローダーではないのです。 このため、OSをもし自分で作ろうとするなら、最終的には、ある程度はBIOSや内蔵機器のシステムなど、ハードウェア側のシステムの仕組みを知る必要があるでしょう。 しかし、ある程度は規格で決まっています。たとえばディスプレイについては『VESA』という団体が規格化を行っており、このためBIOSでのディスプレイの扱いも、ある程度は規格的に整理されています。 一般的なBIOSには、起動時にハードディスクに書かれたプログラムを実行する仕組みがあります(でないと、ブートローダーとして役立たない)。 また、一般的なCPUやアセンブラには、メモリの最初から何番目のアドレスに、どの機械語命令を書き込むか、という、メモリアドレスを指定してメモリに書き込む機能(org疑似命令)があります。 つまり、これらの機能を合わせて、(ブートデバイスの)メモリへとコピーされる領域に、パソコン電源投入直後の初期状態のメモリをどう変更したいかを書けばいいわけです。 それぞれのBIOSメーカーやCPUメーカーなどがデータシートなどを公開しているハズなので、余裕があればネットで確認しましょう。 :(しかし市販の『BIOSの設定が分かる!』みたいなタイトルの書籍は、OSの仕組みの勉強には、まったく使い物になりません。) :(また、「Windows10の使い方が分かる」みたいな書籍も、使い物になりません。) 一般にどのパソコンも、電源ボタンを入れた起動時に、内蔵ハードディスク(または内蔵SSD)とCPUとメモリとディスプレイが起動するようになっています。 そして、ディスプレイの表示内容は、(いわゆるビデオチップなどの)VRAM(ビデオRAM)または、メモリ(差し込める奴)から読み読み取るようになっています。 しかし、一般的なBIOSは、アセンブラのINT 0x10命令でディスプレイに割り込みをかけられるようになっていますので、あまりハードの内情を知る必要はありません(アセンブラのINT とは、割り込み interrupt のことです。C言語の整数型変数宣言 integer とは違うので、混同しないように。)。 :※ なお、割り込み信号の発生のさいのチャタリングの除去は、たとえばシュミット・トリガ回路で除去できる<ref>『H8マイコン入門』、堀桂太郎、東京電機大学出版局、2003年12月20日 第1版 第2刷、162ページ</ref>。 また、BIOSあたりのレベルで、ディスプレイが、メモリにASCIIコードにもとづくデーターバイトを入れるだけで、その文字を順番に表示するサポートなどをしています。(ディスプレイ用のメモリに機械語のdb命令で文字を書き込むだけで、その文字をアセンブラが自動的にバイト文字に変換し、さらにBIOSとハードが連携して自動的に該当する文字を画面に表示するプログラムにしてくれる。) 実際、日本の書店で市販の「OS自作」などを謳っている書籍を読むと、「メモリマップ」 memory map というハードウェア業者の用意した仕様にしたがって、該当するメモリの書き換えをする作業を機械語などで書いて、それでGUIを作っています。 けっしてOS自作界隈だけが言ってる用語ではなく、電子工作の界隈でも『メモリマップド I/O』という用語が、同じような意味であります<ref>『H8マイコン入門』、堀桂太郎、東京電機大学出版局、2003年12月20日 第1版 第2刷、54ページ</ref>。 原理的には、VRAMのメモリマップを書きかえる事と、(C言語でいうif文のような)条件分岐などの制御構造などの実装により、GUI画面が作れます(ディスプレイの画像はピクセル単位の点の画像の集積なので)。 ==== メモリマップ ==== さて、一般的に、メモリの一部の領域は、メーカーごとに使い方が決まっており、「最初の何バイトはハードディスクの起動用に使う」、「△△バイト目から□□バイト目からは、ディスプレイとのやり取りの制御に使う」とか、ハードウェア(基盤やBIOSなど)のメーカーごとにメモリの使い方が決まっています。 一般的なパソコンではグラフィック描画用のVRAMアドレスは 0xa0000 から 0xaffffの領域が割り当てられています。 なお、このようなメモリの用途の割り当てのことを「メモリマップ」memory map といいます。 (MBRなどとは違います。MBRはハードディスクの話題です。メモリマップはDRAMなどの話題です。) もし、一般的でない特殊なハードウェアの場合は、メモリマップを調べる必要があります。 なので、OSを作るには、世間に流通しているハードウェアのメモリマップを探りあて、C言語やアセンブラなどで、メモリ上のデータを書き換えるようにプログラムを書いて、それをブート時にブートローダーから起動させる用に命令すれば、デバイスなどを操作できると考えられます。 現在の市販に流通しているパソコンのアーキテクチャの多くは、1900年代の昔のIBMやインテルなどの発表したアーキテクチャである 「X86」系というのが元になっているので、まずはそれに詳しくなる必要があります。 CPUメーカーのAMD系のハードウェアであっても、パソコンのアーキテクチャの多くはX86系ですので、まずはX86系を勉強する必要があります(しかし、組み込み系とか、スーパーコンピュータ、その他の携帯モバイル機器などは、アーキエクチャの違う場合があるので、別途、アーキを調べる必要がある)。 なお、「メモリマップ」という概念があるのは、パソコン用CPUアーキテクチャだけでなく、組み込みマイコンCPU(Z80やH8など)などでも同様です(とはいえ、組み込みマイコンにブートローダやディスプレイなどは一般に無いのが普通なので、そこは誤解しないように)。 ==== 割り込み ==== キーボードや内蔵タイマなどの周辺ハードは、「割り込みコントローラ」(PIC)というものを経由して、CPUやメモリは、これらの周辺ハード(キーボードや内蔵タイマなど)を制御しています。 :※ 割り込みとは、何が何に割り込んでいるかというと、いま実行している命令と次の命令のあいだに、それ以外のデバイスの要求が割り込むイメージである。 X86系における割り込みハンドラとは、イメージ的には、下図のような感じです。 <pre> CPU ━━ 割り込みハンドラ━━━━┳━キーボード                  ┃                 ┣━タイマ                 ┃                 ┣━(※ 以下略)                 ┃ (※ 以下略) </pre> なお、マイコンボードのPICマイコンと「割り込みハンドラ」('''PIC''')は名前が似ていますが、まったくの別物ですので、混同しないように。 キーボードの制御は、PICから、さらにキーボードコントローラー(KBC)というのを経由して、通信方式は一般的にシリアル通信で、制御が行われます。 上図はつまり、さらに下図のようにキーボードの部分が修正されます。 <pre> CPU ━━ 割り込みハンドラ━━━━┳━キーボードコントローラー ━━キーボード                  ┃                 ┣━タイマ                 ┃                 ┣━(※ 以下略)                 ┃ (※ 以下略) </pre> ;余談 当面は覚える必要は無いですが、 一般的なパソコン/BIOSでは、割り込みに使える番号の数は、0番から255番までの合計256個です<ref>白崎博生 著『Linuxのブートプロセスをみる』、株式会社KADOKAWA(発行)、アスキー・メディアワークス(プロデュース)、2014年10月2日 初版、53ページ</ref> <ref>内田公太・上川大介 著『自作エミュレータで学ぶX86アーキテクチャ』、株式会社マイナビ (※出版社名)、2015年8月30日 初版 第1刷 発行、160ページ</ref>。このうち、0番~31番まではインテル(CPUメーカー)仕様などの規格などにより用途が既に決められております。なので、ユーザーが自由に定義できるのは32番~255番の領域だけです。 また、割り込みが発生する直前のCPUの状態の保存の方法は、単にスタックにプッシュすることで保存しているだけです。割り込みが発生すると、スタックにフラグレジスタやPCレジスタなど(主に CSレジスタ(コードセグメント)とIPレジスタ(命令ポインタ)とFLAGSレジスタ)の値が(スタックに)プッシュされて保存され、そしてハンドラに制御が移ります <ref>白崎博生 著『Linuxのブートプロセスをみる』、株式会社KADOKAWA(発行)、アスキー・メディアワークス(プロデュース)、2014年10月2日 初版、55ページ</ref> <ref>内田公太・上川大介 著『自作エミュレータで学ぶX86アーキテクチャ』、株式会社マイナビ (※出版社名)、2015年8月30日 初版 第1刷 発行、160ページ</ref>。 割り込みが終わるなどして戻るときに、スタックに保存しておいたフラグなどのデータを取り出します。 ;Linuxのコマンド LinuxのFedora31ではターミナル端末のコマンドで <code> cat /proc/interrupts </code> とすれば、そのハードウェアでの割り込みコントローラの割り当ての構成を見られる。 「proc」の前にスラッシュ記号(/)をつけるのをコマンド入力時には忘れないように。 なお、表示結果は、コンピュータのハードウェア構成によって異なる。 一例として、富士通の2010年頃のノートパソコン FMV-BIBLO NF/B70 を Fedora31 上で <code> cat /proc/interrupts </code> してみると、下記のように表示される。 <pre> [ユーザー名@localhost ~]$ cat /proc/interrupts CPU0 CPU1 0: 143681 0 IO-APIC 2-edge timer 1: 110 0 IO-APIC 1-edge i8042 8: 0 1 IO-APIC 8-edge rtc0 9: 0 76 IO-APIC 9-fasteoi acpi 12: 0 728 IO-APIC 12-edge i8042 16: 18138 0 IO-APIC 16-fasteoi uhci_hcd:usb3, i915 17: 0 9 IO-APIC 17-fasteoi uhci_hcd:usb4, firewire_ohci, yenta, mmc0 18: 17109 0 IO-APIC 18-fasteoi ehci_hcd:usb1, uhci_hcd:usb5, uhci_hcd:usb8, ath 19: 0 0 IO-APIC 19-fasteoi uhci_hcd:usb7, i801_smbus 23: 0 30 IO-APIC 23-fasteoi ehci_hcd:usb2, uhci_hcd:usb6 27: 0 68728 PCI-MSI 512000-edge ahci[0000:00:1f.2] 28: 16891 0 PCI-MSI 4194304-edge enp8s0 29: 0 922 PCI-MSI 442368-edge snd_hda_intel:card0 NMI: 133 125 Non-maskable interrupts LOC: 154414 216397 Local timer interrupts SPU: 0 0 Spurious interrupts PMI: 133 125 Performance monitoring interrupts IWI: 28932 26837 IRQ work interrupts RTR: 0 0 APIC ICR read retries RES: 41828 40626 Rescheduling interrupts CAL: 18459 15141 Function call interrupts TLB: 38258 37058 TLB shootdowns TRM: 0 0 Thermal event interrupts THR: 0 0 Threshold APIC interrupts DFR: 0 0 Deferred Error APIC interrupts MCE: 0 0 Machine check exceptions MCP: 2 2 Machine check polls HYP: 0 0 Hypervisor callback interrupts HRE: 0 0 Hyper-V reenlightenment interrupts HVS: 0 0 Hyper-V stimer0 interrupts ERR: 0 MIS: 0 PIN: 0 0 Posted-interrupt notification event NPI: 0 0 Nested posted-interrupt event PIW: 0 0 Posted-interrupt wakeup event [ユーザー名@localhost ~]$ </pre> なお、cat コマンドは単に、引数で指定されたファイルを表示するだけである。また、「 /proc/interrupts 」とは、単に proc ディレクトリーの中にある interrupts ファイルを指定しているだけである。なお、マウスで探すときは、ホームディレクトリーの中には proc ディレクトリーはなく、「コンピュータ」アイコンから、たどって行くと見つかる。 なので、別にコマンド端末からの捜査でなくとも構わず、マウス操作で直接、procディレクトリーを探して interruptsを見ても、かまわない。 なお、番号の呼び方で 「 0: 143681 0 IO-APIC 2-edge timer」 の端子は「 IRQ 0 」と呼ぶ。 「 1: 110 0 IO-APIC 1-edge i8042」 は「IRG 1」 と呼ぶ。 「 8: 0 1 IO-APIC 8-edge rtc0」 は「IRQ 8」と呼ぶ。 「IRQ」とは、割り込み要求 Interrupts ReQuest のことである。 「APIC」というのは、単に、インテル製の割り込みコントローラーの製品名で、そういう製品がある。インテルの古い割り込みコントローラで「8259A」というのがあって、それを(Windows2000やペンティアムが出始めた)1990年代〜2001年頃に後継したのが「APIC」である。 さらに2010年代の原題では、その「APIC」を拡張した「xAPIC」になっているが、便宜的に「APIC」と呼ばれているママのことも多い。 なお、メーカーなどによって異なる可能性はあるが、だいたい、どこのメーカーのパソコンでも、割り込み IRQ のハードウェア構成は :0番(IRQ 0)はタイマー、 :1番(IRQ 1)はキーボード、 i8042 とはインテル製のキーボードコントローラの型番 :12番(IRQ 12)はマウス、 i8042 とキーボードコントローラの型番がある理由は、マウスのセンシングでもキーボードコントローラを流用しているから、 などの共通的な傾向がある。 から8番あたりまでの構成は、表示結果からも 「 CPU0 CPU1 」と2つCPUなんとかが表示されるのは、単にこのパソコンのCPUが2コアだから(インテル Core2Duo 採用品)。 CPU0 CPU1 0: 143681 0 IO-APIC 2-edge timer などの「143681」は、単に合計の割り込み回数だと言われている(要 確認)。Fedora では、この /proc/interrupts ファイル内に、割り込みの統計が保管されている。 ちなみに proc ディレクトリーおよびproc配下のほとんどのファイルは、実は(DRAMなどの)メモリ上に置かれた設定情報である。実は物理的にはハードディスクには proc ディレクトリー/ファイルは無い。ユーザーがアクセスしやすいように、わざと、あたかも proc 関連ファイルが(まるで)ハードディスクにあるかのように擬態されて表示される仕組みに Linux などが なっている。そもそも proc 関連の項目が「ファイル」かどうかも本来は疑わしい。 なお、ポートアドレスで指定したIOポートにデータを送信できます<ref> 白崎博生『新装改訂版 Linuxのブートプロセスをみる』、株式会社 KADOKAWA、2014年10月2日 初版発行、55ページおよび66~67ページ</ref>。 <syntaxhighlight lang="asm"> out 0x21, ax </syntaxhighlight> のように書きます。 つまり、 <syntaxhighlight lang="asm"> out ポートアドレス, ax </syntaxhighlight> の書式になります。 ポートアドレスをイミディエイトウィンドウで与えた場合、IO空間の $0000 .. $FFFF のうち最下位の $0000 ... $00FF にしかアクセスできません。 ポートアドレスの一覧については下の表を参照。」 {| class="wikitable" |- ! !! PIC1 <br>(マスター) !! PIC2 <br>(スレーブ) |- | コマンド || 0x20 || 0xA0 |- | データ || 0x21 || 0xA1 |} 0x11 の部分は、コマンドで、この場合は初期化コマンド。 メーカーによって違う可能性はありますが、よくあるポートアドレスとして、 0x20 から 0x3F 割り込みコントローラ(PIC) 0x40 あたり タイマ 0x60 あたり キーボード関係 の割り当てがあります。(※ 参考文献『作って理解するOS』、276ページ。 ) その他、割り込みコントローラー(PIC)について、 0x20 マスターPICのコマンドレジスタ。 0x21 マスタPICの割り込みマスク(interruput mask)レジスタ。 0xA0 はスレーブPICのコマンドレジスタ。 0xA1 はスレーブPICの割り込みマスク(interruput mask)レジスタ。 などに割り当てられている場合もある。 あらかじめ直前に move 命令で、axレジスタに送信したいデータを入れておく必要があります。 つまり、 <syntaxhighlight lang="asm"> mov ax, 送信したいデータ out ポートアドレス, ax </syntaxhighlight> の書式になります。 ポートアドレスをレジスタに代入する場合は、 <syntaxhighlight lang="asm"> out dx, ax </syntaxhighlight> のように dx レジスタ間接でIOポートを指定します(dxレジスタ以外はポートアドレスの修飾に使えません)。 dx レジスタ間接を使うと、IO空間の $0000 .. $FFFF 全てにアクセスできます。 さらに、データサイズが何ビットかにしたがってmovやoutの末尾に b (1バイトの場合)または w (2バイトの場合)がつくので、 <syntaxhighlight lang="asm"> movb al 、 送信したいデータ outb ポートアドレス 、 al </syntaxhighlight> のようになります。 なお一部のC言語のライブラリで提供されている標準外の関数 {{code|outb()}} は、上述のようなアセンブリ言語のoutb命令に相当するものです<ref>ダニエル・P・ボベットおよびマルコ・サセティ著『詳解Linuxカーネル 第3版』、高橋浩和監訳、2011年5月20日 初版 第5刷、244ページ </ref>。 {{コラム|シリアル通信とパラレル通信| なお、一般に電子機器ケーブルが信号を送受信をするとき、複数本の信号線で送受信する方式をパラレル通信といい、いっぽう、1本だけの信号線で送受信する方式をシリアル通信という。 ただし、パラレル通信は、速度が遅い。 一見すると、パラレル通信のほうが、線路が多いぶん多くの情報を送れそうだが、信号の到達タイミングにばらつきが生じるので、高速化は困難である。 なお、Z80系マイコンCPUにはパラレル通信インターフェースの端子が存在する<ref>堀桂太郎『Z80アセンブラ入門』、東京電機大学出版局、2007年5月20日 第1版 第2刷、143ページ</ref>。Z80は最大クロック数が12MHzの製品がある<ref>堀桂太郎『Z80アセンブラ入門』、東京電機大学出版局、2007年5月20日 第1版 第2刷、134ページ(「143」の誤記ではない)</ref>。12メガもの高周波でどうやってパラレル通信をしてるか(そもそも12メガでもパラレルできるのか)、気になるところである。 いっぽう、H8マイコンはシリアル通信を内蔵している<ref>白土義男『H8ビギナーズガイド』、東京電機大学出版局、2008年2月20日 第1版 第9刷、16ページ</ref>。 こういう言い方をすると、なんとなくパラレル通信では符号化が不要な感じかもしれないが、そんなことはなくて、単にシリアル通信のほうが符号が長くなりやすいだけで、シリアル通信でもパラレル通信でもともに符号であるし、そもそもデジタル信号は基本的に符号化して情報伝達をするので、シリアル通信もパラレル通信もともにデジタル信号なので符号化が必要である。 よく変換コネクタで、シリアル通信とパラレル通信の変換コネクタなどが業者むけに販売されているが(はたして家電量販店で市販してるかどうかは知らない)、これは、符号を別方式の符号に変換してるのである。けっしてアナログ信号をデジタル信号に変換してるわけではない(つまり、ADコンバーター(アナログ/デジタル変換器のこと)とは違う。)。 なお現代でも、産業用機械などにおいて(装置と別の装置との)送受信の場合などは、(USBシリアル接続でなくて)パラレル通信用の端子ケーブル(たとえば RS232C ケーブルなど )が使われる。 なお、RS232Cケーブル(これはパラレル端子)やPS/2ケーブル(これはシリアル通信端子)は、イメージ的に何となく古いイメージなので、てっきりアナログ通信かと誤解しがちだが、RS232CケーブルとPS/2ケーブルはそれぞれデジタル通信である。 RS232Cは、現代でも産業機器などで使われる。工場など企業の労働現場は、かならずしも空調などが快適とは言えず、また、機械工作の切削クズなどが発生しやすい環境もあったりするので、頑強な過去の時代のケーブルなどが好まれる場合もある。 過去には、古いパソコンで、外部との接続端子にRS232Cがよく使われていた。 PS/2 は、やや古いキーボード接続に使われた端子およびケーブルである。 これらの古いケーブルおよび端子は、接続先の機器がアナログ的な機器である場合も多いので(特に RS232C)、てっきり端子も「アナログ端子だろう」(×)と誤解しがちであるが、しかし、RS232CもPS/2も端子じたいはデジタル端子なので混同しないように。 なお、パソコンのハードディスクの接続は現代では一般にシリアル通信であり、シリアルATAと言われる。ケーブルが太そうに見えるので何となくパラレルっぽく見えるかもしれないが、しかし、シリアルATAはその名のとおりレッキとしたシリアル通信である。 また、拡張カード端子とパソコン内部コントローラなどの接続に使われるPCIバスおよびその発展系の各種規格もシリアル通信である。 さて、シリアル通信では、8B/10Bという符号化がある。(ウィキペディア『[[w:8b/10b]]』) もしCPUがシリアル通信なら、とうぜん、これを行ったうえで、さらにそれぞれの端子の通信内容を重ねているのだろう。 この8b/10bは、もし同じビットが長時間連続すると、電子回路の電磁気的な都合により入力ビットが反転しても出力の立ち上がりが不完全になって出力エラーになるという回路特性があるので、同じビットが絶対に連続しないように、8ビットの入力信号を、ビットが4個以上は連続しない10個のビット符号に置き換えるという、符号方式である。 置き換えの符号は、規格で決められているが、数学的な規則性は無いので、覚えなくていい(実務では、規格表で確認する)。 また、4B/5Bなど、同じ原理の符号方式もある(4B/5Bは4ビット入力を連続しない5ビット入力に置き換えている)。 :※ 資格本などで「電気通信設備工事担任者」(いわゆる「工事担任者」)などの資格本を読むと、ここら辺の話題が説明されている。 さて、シリアル信号とパラレル信号の変換技術でSerDes(サーデス)という方式がある。原理は単純で、たとえばパラレル入力でA=1, B=0,C=0,D=1なら、 シリアル変換のために1本の送信ケーブルで1秒後に1, 2秒後に0、3秒後に0、4秒後に1を送信というように送信するようにする原理。(もちろん実際には「1秒」という長時間ではなく、もっと短い周期。) 簡単にいうと、このserdesの原理では、入力ピン数が増えると、そのぶん周期が長くなる。 8B/10B などの符号化と、このserdesを組み合わせて、8B/10B SerDes などとして、コンピュータ内部では使われている。 このようにパラレル伝送は現代では評判が悪いが、しかしGPUではパラレル的な伝送が使われている(原理的に、GPUの各プロセッサに伝送するために伝送をどこかでパラレル化せざるを得ない)。 コンピュータアーキテクチャの専門書でもGPUについて『パラレル』という用語が用いられている(しかし『パラレル伝送』とは専門書では言ってないが)。 他にもスーパーコンピュータの並列コンピューティングも同様に、専門書では『パラレル』という用語が用いられている。 このGPUや並列コンピュータのように、チップ1個上のハードウェア内部的にはシリアル伝送だが、そのチップまたはマザーボードをいくつも配置して並列計算するという、新型のパラレル処理のようなものが現代ではスーパーコンピュータなどの大型計算では行われている。 スパコン開発者・GPU開発者などは特にノウハウを公言していないが、パラレル伝送には上記のような同期化のさいの困難性などの問題もあるので、もしも精度の高く要求される計算をする場合には、伝送のズレなどによる誤差のぶんを考慮しなければならないハズなので、対策として例えば計算の確認のための多重化など(同じ計算を複数回計算して、誤差が無いかを確かめるなど)、慎重な処理をしなければならないだろう。 あるいは、多数決モジュールあるいは多数決回路というのがあり、これは複数の回路からの計算結果の一致やズレを相互検証するものだが、これもパラレル伝送の問題があるので、なので対策が必要である。 パラレルはタイミングがズレるが、しかしタイミング以外の波形パターンはまずズレないのだろうから、だったら最初からズレを見込んで、た余計に伝送をすればイイ。 たとえばもし「110」というデータを送りたいなら、その前後に「0000」をつけて「0000 110 0000」と送れば、 もし「0」一個ぶんだけタイミングが遅れても、「 000 110 0000」と、送りたい「110」のデータは残る。 「0000」1個だけなら不安なら、たとえば「0000」を3回繰り返して「0000 0000 0000」とか追加する仕様にすればいいだろう。そうすれば「000 0000 0000 110 0000 0000 0000」となるので、「0000」が2回繰り返すので、それから、「0000」が保護材として追加されたデータだと分かる。 実際には、4b/5b の導入の経緯のように、0がいくつも「0000」のように続くと立ち上がりが悪くなるので、 4b/5bなどの符号を保護材側データを追加する必要があろうが。 }} {{コラム|原始的なコンピュータのアーキテクチャ| よく、情報科学の入門的な理論では、「コンピュータの基本的な仕組みとしてCPU内にはレジスタがあって、基盤にはメモリがあって、」(以下略)・・・ などと習うが、 それだけでは実は不十分。 まず、CPUに、作業内容の切り替えスイッチが必要である。 なぜなら、アセンブリ言語で色々な命令があるが、その命令にもとづいて、CPUは回路を切り替えなければいけないからだ。 [[File:2to4demux.svg|thumb|500px|デマルチプレクサの原理]] スイッチの実装としては、デジタル回路の技術で「デマルチプレクサ」という切り替えスイッチ回路が有名であるので、単にこれを使えばいい。 右図がデマルチプレクサの原理図であり、右図の場合は2ビット用なので2の2乗ぶんの4個のスイッチを切り替えられる。 [[File:Multoplexor1.svg|thumb|マルチプレクサの原理図]] なお、(頭文字に「デ」のついていない)マルチプレクサというものは、デマルチプレクサの出力側の終端すべてにOR回路を1個つなげて、まとめただけである。 用語だけ見ると、てっきり、1文字ぶん短いマルチプレクサのほうが(デマルチプレクサよりも)中枢的な部品のように思えるが、しかし実際はデマルチプレクサこそが中枢的であり、デマルチプレクサによる回線切り替えこそが重要技術である。 [[File:OR-gate of diodes.svg|thumb|230px|left|ダイオードによるOR回路の等価回路の概略図<br>※ 実際にはパソコン内のOR回路はMOSトランジスタなどによる回路であり、ダイオードではない。]] さらにいうなら、そのOR回路は逆流を防止するためにつけられただけである。このように、マルチプレクサでの出力端子のOR回路に、あまり意味は無い。 私たちは、けっして用語に惑わされるのでなくて、回路図と照らし合わせて本質を学ぼう。(※ なお、パターソン&ヘネシー『コンピュータの構成と設計』だと、マルチプレクサのほうを中心に考えている<ref> David A. Ratterson, John L.Hennessy『コンピュータの論理と設計 第5版[上] ~コンピュータのハードウェアとインターフェース~』、2019年9月5日 第5版 第7刷 発行、238ページなど</ref>。しかし、彼らの考えは不十分だろう。デマルチプレクサこそが中心的な部品である。もっともパタヘネ本の初版は1996年4月9日であり、この時代で、ここまで調べたあげているパタヘネはすごい。) なお、理工書の東京電機大学出版局『コンピュータ工学の基礎』を読むと、最初にマルチプレクサとデマルチプレクサを教えてから、あとから加算回路を教えるという書籍の構成である<ref>淺川毅『コンピュータ工学の基礎』、東京電機大学出版局、2018年9月10日 第1版 第1刷 発行、100ページおよび101ページ </ref>。 さらに、電機大の同文献ではマルチプレクサの説の直前で2進-10進デコーダを紹介しており<ref>淺川毅『コンピュータ工学の基礎』、東京電機大学出版局、2018年9月10日 第1版 第1刷 発行、98ページ </ref>、まるで「きっとマルチプレクサの正体は2進デコーダなんだろうな」とでも言いたげな構成である。 :※ パタヘネ本では、論理回路の中身まで、あまり言及していない。 デジタル電子回路でよく、2進-10進デコーダという、4本の入力端子の2進数の入力を、出力10本の回路に切り替える回路がある。(2の4乗は16なので、最大16本の出力に切り替えできる。) さて、パタヘネ本によると、X86系CPUの命令数は約1000個らしい<ref> David A. Ratterson, John L.Hennessy『コンピュータの論理と設計 第5版[上] ~コンピュータのハードウェアとインターフェース~』、2019年9月5日 第5版 第7刷 発行、157ページの図2.43など</ref>。なので、CPU用のデマルチプレクサを作りたい私たちは、単に2進-1000進デコーダを作ればいいだけであろう。パタヘネ本によるとX86系の命令数は2012年の時点で900個である。 なお「デコーダ」という用語について、一般に情報科学でも、CPUが命令を解釈して実行させるために各装置に信号を送るための「命令デコーダ」とは、このデマルチプレクサのことであると考えられる(※ パタヘン本ではマルチプレクサの前段階のシステムが「命令デコード」だとしている<ref> David A. Ratterson, John L.Hennessy『コンピュータの論理と設計 第5版[上] ~コンピュータのハードウェアとインターフェース~』、2019年9月5日 第5版 第7刷 発行、276ページおよび277ページ図4.33など</ref>)。 なお、マルチプレクサのことは、「データセレクタ」という<ref> David A. Ratterson, John L.Hennessy『コンピュータの論理と設計 第5版[上] ~コンピュータのハードウェアとインターフェース~』、2019年9月5日 第5版 第7刷 発行、238</ref>。字面だけみると「命令デコーダ」と「データセレクタ」とは別物のように見えるが、ようするにデマルチプレクサによる回路出力の切り替えと、その付属システムにすぎない。私たちは本質を学ぼう。 さて、私たちに必要なスイッチ個数はアセンブラの命令によって切り替えるので、最低でも数百個もの切り替えが必要だろうが(ひょっとしたら数千個や数万個)、 ここで2の16乗は65536なので、16ビット分のデマルチプレクサの配線をすると、回路を切り替えられる。 数万本もの導線というと、人間の手作業ではムリだが、しかし半導体リソグラフィーを使えば可能であろう。というか、たとい困難だろうが、それをやった企業が半導体チップ産業の覇者になっているのだろう。 半導体の製造では紫外線照射や近年の研究開発ではX線照射をするが、照射の回数を、私たちの目標ではなんとか16回~32回程度に抑えたい。 では、何にしたがって回路を切り替えるかというと、(上述したように)アセンブラのプログラムにしたがって回路を切り替えればいいのである。そのため、アセンブリ言語は、スイッチ切り替えに対応可能なような命令体系になってなけれればらない。 さて、そのアセンブラのプログラムの読み取りのためには、現在の命令の位置を示す「プログラムカウンタ」も作る必要がある。 では、そのプログラムカウンタをどうやって作ればいいか? ヒントは、昔の紙テープ式コンピュータで、要するにあれと同じことを電子データで実現すればいいのである。 まず、紙テープコンピュータがどういう仕組みになってるか考えよう。 紙テープのうち、一定の読み取り面だけを読み取るわけで、その紙テープにデータに対応する穴が開いていて、その穴の位置や大きさなどの組み合わせで、プログラムデータを区別しているわけである。 そして、紙テープ読み取りコンピュータがプログラムデータを読み取り終わって、そのプログラムを実行し終えたら、テープを一定幅だけ進めるわけである。 そして、また、テープを読み取り、プログラムを実行することの繰り返し。 これを電子回路的に実現すればいい。 まず、プログラム実行時のデータ保存領域が必要だが、これはメモリで代用できる。 ハードディスクは低速なので、ハードディスクからメモリに読み出す仕組みになっている。 現代のパソコンでは、狭義の命令プログラム保管用のDRAMメモリと、プログラム以外の画像データや音声データやテキストデータなどのDRAMメモリは、同じメモリ基盤上にある。だが原理的には、必ずしも同じ基板上にする必要は無く、そういう構造の場合をハーバード・アーキテクチャという。つまり、命令用メモリと、データメモリとが別々の部品であるのが、ハーバード・アーキテクチャである<ref name="H8">『H8マイコン入門』、堀桂太郎、東京電機大学出版局、2003年12月20日 第1版 第2刷、6ページ</ref>。かつてハーバード・マークワンで採用されていたアーキテクチャが、そういう(命令とその他データの分離された)アーキテクチャだった)。1990年以降でもAtmel社のAVRシリーズの8bitマイコン用CPUが、ハーバード・アーキテクチャを採用している。Arduino という2005年以降に普及したイタリアのマイコンボードで8bit用ボードにAVRシリーズを採用している。ハーバード型(ハーバード・アーキテクチャ)は欠点として回路構造が複雑になるものの、長所として高速化しやすいという利点もある<ref name="H8" />。そのため、一部の制御用マイコンでもハーバード型が活用されているという<ref name="H8" />>。 さて、演算回路などでプログラムの実行が終わったら、なんらかのフィードバックをプログラムカウンタに返して、前に送ったプログラムが終了したことをカウンタに知らせる必要がある。つまり、どんなプログラム命令でも、命令1個につき、かならず終了後に、命令実行を確認するためのフィードバックを返す必要がある(ただし、デジタルのフィードバック信号)。命令実行ずみ検出フィードバックが帰ってくるまで、プログラムカウンタを進めない仕組みにする必要がある。 電子回路の本を読めばフィードバックなんて、どこの本でも書いてある。 演算回路の出力に、フィードバック回路もつければいいだろう。 あとは、プログラムをそもそもどうやって入力するかだが、コレは単にキーボードから入力すればいい。キーボードは、人間が手作業でボタンを押して入力するので、単に、そのボタンの押された内容にもとづいて、メモリに機械語を保存すればいい。 メモリそのものは、SRAMのようにフリップフロップ回路で作ることができる。 電源を切った後にも保存したければ、磁気テープならぬ磁気ハードディスクにでも保存しとけばいい。黎明期のコンピュータだって、紙テープに保存していたわけだ。 コンピュータはこんな仕組みらしい。 }} ==== IN命令とOUT命令 ==== 上述のように、キーボードやタイマなどのメモリ以外のデバイスとの送受信は、IN命令または OUT命令で、ポート番号を仲介して制御する仕組みである。 INやOUTの方向は、CPUから見た方向である。 CPUからみて、デバイスに送る方向の場合に OUT 命令である。 デバイスからの情報を、CPUのレジスタが受け取る場合に IN 命令である。 IN命令やOUT命令の引数で、引数でI/Oポートアドレスを指定することで、どのアクセスの読み書きをするかを指定する。 また、キーボードコントローラーも、ポートアドレスが割り当てられている。 {{x86-inst-2|in}} {{x86-inst-2|out}} 実例として一般に、キーボードコントローラーのポートアドレスは 0x60 と 0x64 である。0x60がデータ用、0x64がコマンドやステータス用。<ref name="making_os:447"> (※ 参考文献『作って理解するOS』、初版第1刷、447ページ ) </ref>。 なので out 0x60, al のような命令により、読み書きが可能である<ref name="making_os:448"> (※ 参考文献『作って理解するOS』、初版第1刷、448ページ ) </ref>。 しかし、コンピュータ黎明期からある、いくつかのデバイスの制御では、IN命令やOUT命令を使わずとも、ソフトウェア割り込みを発生させる INT 命令が用意されている(IN 命令とは異なる)。BIOSによって、 INT 命令に対応したハンドラが用意される。 具体的に言うと、仕様上は、ディスプレイやフロッピーディスクやハードディスク、キーボードなどは、割り込み INT 命令によってBIOSの機能を呼び出せる仕様であり、int 0x10 はディスプレイとの割り込み、int 0x13 はディスクアクセスとの割り込み、などの仕様がある。 本書では、とりあえず、80年代あたりの古いアーキテクチャを前提とする(資料が入手しやすいので)。そのため、最近のアーキテクチャでは動作しない可能性がある。 === 実験の手段 === 一般に、エミューレーターを使って実験します。 無料のフリーソフトでも、[[w:QEMU]]などのエミュレータを使えるので、アセンブラの[[w:Netwide Assembler|w:NASM]](無料ソフト)などで(アセンブリコード入力を経由して)機械語を入力していきます。 ※ 次の節で、qemuの使い方を大まかに説明する。 原理的には、アセンブラを経由せずともバイナリエディタ(Hex editor)といわれるもので機械語を直接に書いてプログラムするのも、原理的には可能です。そもそもアセンブラ自体どうやって開発されたかを想像すれば、おそらくバイナリエディタを、流通しているCPU用のアセンブラ命令にあわせて特化してプログラミング用に作られたソフトウェア(がアセンブラ)なのでしょう。 :※ なお、日本語ではバイナリ(2進数)エディタといいますが、しかし英語では16進数(hex)で「ヘックス エディタ」Hex editor といいます。なので Linux などで対応の機械語エディタを探す場合は、16進エディタような名前のソフトを探すことになります。 原理の理解としてはバイナリエディタの存在に気づくことも重要ですが、しかしバイナリエディタによるプログラミングではコード記述が覚えづらく非現実的ですし、一目では内容が分かりづらいです。なので、一般にアセンブラで入力していくのが、OS製作では現実的でしょう。 さて、NASMは、あくまでエミュレーター上での仮想化なので、完全には仕組みを再現していませんが、しかし個人の学習では、止む(やむ)を得ません。 もしもエミュレータを使わずに、BIOSのブート設定を 毎回 書き換えて実機のパソコンでブートの実験などを毎回したとしたら、とてもメンドウです。なので、エミュレータを使って、手間を省きます。 なお、一般的なLinuxなどでは、リリース直前の開発の後半などで、確認のために最終的に開発者たちはDVDなどに書き込んでブートしてみたりするなどして、実験します(いわゆる「ベータテスト」などで、DVDのISOを無料配布している)。 なお余談ですが、OS自作でなくCPU自作をしたい場合、[[w:GNU Binutils]]などの無料のクロスアセンブラがありますので、そういうのを活用します。半導体製造工場などを個人は持ってないので、ソフト的にエミュレートするしかありません。 === 備考: エミュレータの種類 === エミュレータにも種類や方式が色々とあります。 方式のひとつとして、ホストOSのインストールされているパソコンのCPUを間借りする方式があります。 別の方式として、ホスト側のCPUは間借りせずソフトウェア内に仮想のCPUを制作する方式のものなどもあります。 コミュニティ ベース の qemuやBochs というエミュレータは、(ホストCPUをあまり)間借りしないで、ソフト的に仮想のCPUを作る方式のものである<ref>内田公太・上川大介 著『自作エミュレータで学ぶX86アーキテクチャ』、株式会社マイナビ (※出版社名)、2015年8月30日 初版 第1刷 発行、6ページ</ref> いっぽう、オラクル社のVirtual Box やヴイエムウェア社のVMWare というエミュレータは、ホストPCのCPUを間借りする方式のものである。 私たちの学習の目的には、VirtualBox 的に複数のCPUが混ざり合うと学習的に分かりづらくなるので、qemuのようなソフト的にCPUの機能を再現するほうが分かりやすいと考え、qemuを優先して紹介することにする。 また、qemu はオープンソースである。 なお、Virtual Box は昔は非オープンソースだったが、現在はオープンソース版のVirtual Box がある。 なお、オラクル社のようなホストCPUを間借りする方式にも長所はあり、仮想化の中では処理速度を速くしやすいという長所もある。 本書では、とりあえず qemu を前提として説明する。 == qemuの設定方法と使用方法 == === 設定方法(Windowsの場合) === 前提として、ダウンロードとインストールは既に終わっていると仮定する。 qemuは、コマンドプロンプトから使うソフトウェアである。 なので、まずパス(Path)を通さないといけない。 具体的には、環境変数PATHにqemuのあるフォルダーを追加する。 :デスクトップで「システムのプロパティ」を検索し、システムのプロパティを開く :[詳細設定]タブの右下にある[環境変数]ボタンをクリック :[環境変数]画面を開く :'''システム環境変数'''の設定の先頭に、<code>C:\Program Files\qemu</code><code>;</code>を追加する。 さて、パスが追加し終わったら、はたして本当にパスが通ってるの確認のため、Windwosのコマンド プロンプトを起動して C:\Users\ユーザー名>qemu-img というふうに、コマンド「qemu-img」でも入力してみよう。 なお、「qemu」というコマンドは無いので、「qemu」とコマンド入力しても。 'qemu' は、内部コマンドまたは外部コマンド、 操作可能なプログラムまたはバッチ ファイルとして認識されていません。 さて qemu-imgコマンドは引数を指定して使用するコマンドなので、上記コマンド「qemu-img」を実行すれば、端末上で引数が足りないことをqemuから警告されるハズである。 C:\Users\ユーザー名>qemu-img qemu-img: Not enough arguments Try 'qemu-img --help' for more information のように、qemuから警告されれば、ひとまずqemuのインストールは成功である。 === 使い方 === あらかじめ、起動したいファイルを機械語で作っておき、たとえば、testos.img とかの名前をつけて、ホームディレクトリーなどコマンド端末の認識できる場所に保存しておく。 そしてコマンド端末で <pre> qemu-system-i386 testos.img </pre> のようにコマンド<code> qemu-system-i386 </code> を使えばいい。 では、そのOSイメージをどうやって作るか。 原理は、 まず、アセンブラの nasm で書く。(nasm は Netwide Assembler ともいう。) :※ (gccだと難しくなるので、OS制作ではgccは使わないほうがイイ。gccによる出力は、標準設定では、Windowsの実行ファイル(PEフォーマットなど)に自動変換して、OSそのものの自作には余計な情報を負荷してしまう。そうしないためには、引数であれこれと設定する必要がある。gccでアセンブリコードをそのまま機械語にしようとすると、引数がけっこう多くなる。しかも残念なことに、日本のネットには、この操作を詳しく解説した資料が無い。) :なので、 nasm を使おう。 あらかじめアセンブラコード形式で、OSにしたいファイルをアセンブリコードで作っておいて、testos.asm などの名前で保存しておく必要がある。 nasmなら、testos.asm を(PEフォーマットでない、直訳の)機械語にするコマンドは <pre> nasm testos.asm -o testos.img </pre> だけで終わる。 そして、こうして作成したブートイメージをqemuで起動する方法は、ホームファイルに先ほど作成した testos.img を置いた上で、 <pre> C:\Users\ユーザー名>qemu-system-i386 testos.img </pre> のコマンドだけで終わる。 では、元になるアセンブリコードをどうやって調達するか? とりあえず、ネットで読者の勉強用に(彼らの)自作OSのブートローダーのアセンブリコードを公開してくれている人がチラホラといるので、彼らのコードで実験するのが良いだろう。 :※ いちおう、本書でも、初等的なブートローダのコードを記載している(※ 後述)。 == Bochs の使い方 == ネット上に Bochs の使い方の入門書がぜんぜん無いので、wikibook で教えることにする。 Bochsでは、アセンブルはできない。 Bochsの用途は、すでに別ツール(たとえば nasm んど)で作成ずみの img ファイルをBochsで起動するだけのものである。 asmファイルからimgファイルへのアセンブルは、あらかじめ nasm などで行っておく。 Bochsの利便性は、コマンドを覚えなくて言いことである。起動コマンドのBochsだけ押せばウィンドウが起動するので、あとはそのウィンドウ側でGUI的に操作してエミュレータの起動をできるという便利ツールなエミュレータが Bochs である。 さて、Boshs をインストールしてから、環境変数(パス)の設定を終えれば、 コマンドプロンプトで、コマンド <code>bochs</code> で起動する。つまり ユーザー名>bochs のように「bochs」の部分を入力する。 で、起動するとダイアログ画面が現れる。 さて、これだけでは、そもそも何のファイルを起動するかすらも設定されてない。なので、これから、このダイアログ画面で、それを設定する。 まず、真ん中の項目(中央ペイン)にある「Edit Option」 の「Disk & boot」をダブルクリックすると、画面が遷移して、 オプション画面である「Bochs Disk Options」画面になる。この項目で、何のファイルを起動するかを設定できる。 そのためには、 その「Bochs Disk Options」画面の中で、タブ「ATA Channel 0」> 子タブ「First HD/CD on Channel 0」 をクリックすると出てくる画面に、 上から2段目あたりに :Path or physical device name <span style="border-style:inset">        </span> <span style="border-style:outset">Browse</span> という項目があるので、その <span style="border-style:inset">        </span> のなかに、起動したいimgファイル名を入れる。 たとえば、「testos.img」ファイルを起動したいなら、 :Path or physical device name <span style="border-style:inset">testos.img     </span> <span style="border-style:outset">Browse</span> のようになる。 こうして、(おそらく)あとはこのオプション画面を終了して(ダイアログ・ウィンドウの右上のクローズ用の×ボタンを押せばいい)メインメニュー画面に戻り、右ペインにあるStartボタンを押せばいい。 Panic ウィンドウが表示されて Message 欄に「specified geometry doesn<nowiki>'</nowiki>t fit on disk」 と書いてあるが、このまま左下の欄にある Continue をクリックして、OKを押せばいい。 なお、Path or physical device name の設定をしてないで空欄のままにしておくと、Startの際に Message 欄に 「no bootable device」 と出る。 BochsのDtart>OKの後のエミュレート起動後の終了方法は、ウインドウの上部にあるメニューバーの右側のほうに、○印の中にタテ線「|」のある終了ボタン「(|)」があるので、これを押せばいい。(右上の×ボタンは使えない。×ボタンをクリックしても反応しない。) == 擬似命令を使ってブートローダを作ろう == === 擬似命令とは === 一般的なアセンブラには DB 命令というのがあり、これはORG命令などで指定したメモリに値を書き込む命令であるが、これで機械語も書き込みできる。 :備考: なお、DB命令やORG命令は、(CPUに対する命令でなく)アセンブラに対する命令なので「擬似命令」(ぎじ めいれい、pseudo-instruction)という。コンパイラなどにより機械語に翻訳する際、擬似命令は翻訳されない。というか、そもそも翻訳の指示に関する命令なので、翻訳内容ではないので、擬似命令は 機械語にならない のは当然である。 :※ 擬似命令とは、たとえるなら(C言語などの)高級言語でいう、いわゆる「マクロ」のようなものである。 もし、機械語を書き込む先を、メモリではなく、ハードディスクやUSBメモリやフロッピーディスクなどのブート可能なメディアにすれば、原理的には、これでブートローダを作れる。 :※ たとえばマイナビ出版の『OS自作入門』(川合秀美 著)では、まさにこの方法でブートローダやそれから起動するGUIつきOSを作っている。 なお、DB とは data byte の略だと言われている。 さて、では、OSを作るためには、まず、ブートセクタを書き込めばいいのですが、では、どういう内容のことを書き込めばいいのでしょうか。 === ブートローダ === まず、ブートローダを書き込むわけですが、 規格により、 :MBRのサイズは512バイトと決まっており、 また、 :ブートローダと認識させるために必要な署名は、512バイト目の最後の2バイトに16進数で「aa55」と書き込まなければならない(※ 511バイト目が「aa」、512バイト目に「55」である)、 と決まっている。 なので、このために <syntaxhighlight lang="asm"> times 510 - ($ - $$ ) db 0 db 0x55 , 0xaa </syntaxhighlight> をどこかに書き込む必要があります。 <code> times </code>とは、nasm の擬似命令のひとつで、繰り返し命令のことです。 「aa55」の署名を書き込まずにQemu上で機械語を起動しても、いくつかのメッセージのあとに「No Bootable device」などと表示されるだけです。 さて、上記コードの場合は :510 - ($ -$$) 回数だけ、db 0 (つまり「0を書き込め」)を繰り返せ、 という命令です。 $ は、そのtimes命令が出されたときの現在のアドレスです。 $$ は、現在のセクションの最初のアドレスです。 [[File:Little-Endian-ja.svg|thumb|リトルエンディアンの仕組み]] 間違えて、「55aa」(マチガイ!)を書き込まないようにしてください。詳しくは『[[w:エンディアン|w:リトルエンディアン]]』で調べてください。 MBRのサイズは512バイトと決まっており、その末尾2バイトに「aa55」と書き込むので、times 繰り返し命令 では「510」と2バイトぶん、余らせています。 なので、とりあえず下記のように書き込みましょう。 ;コード例 :(※ 実際に動く。 windows7 上の qemu で動作を確認。) <syntaxhighlight lang="asm"> mov ah, 0x0e ; 1文字出力 mov al, 'H' int 0x10 times 510 - ($ - $$ ) db 0 db 0x55 , 0xaa </syntaxhighlight> 成功すれば、 qemu上で、「H」と表示されます。 <code>int 0x10</code> とは、ディスプレイへの割り込み命令のひとつです。int でBIOSにより割り込み命令を指示しています。intの引数で、どんな割り込みをするかを指示しており、<code>int 0x10</code> はビデオサービスの割り込みです。 ですが、<code>int 0x10</code> だけでは、ディスプレイに文字も画像も表示できません。 <code>int 0x10</code>に加えて、さらに、何を割り込ませるかの指定を行う必要があり、<code> mov ah, 0x0e </code> で文字割り込みを指定しています。(※ 詳しくは『[[:en:w:INT 10H]]』(英語版ウィキペディア)などを参照してください。) :ah は、アキュムレータ レジスタ の上位ビットの部分です。 :al は、アキュムレータ レジスタ の下位ビットの部分です。 <code>int 0x10</code> の命令は、上記の手本コードのように、 アキュムレータ レジスタで指示しなければなりません。 なお、学校などで、もしかしたら、情報科学・計算機科学の教育では「アキュムレータ」とは「加減乗除などのためのレジスタ」とか習うかもしれませんが、しかし実際のCPUでは、(上記コード例のように)設定などの一時保存にもアキュムレータが流用されています。 :(※ 要確認)また、電源の投入直後(いわゆる「ブート」の直後)に使用できるレジスタは、まず16ビットCPU時代のレジスタだけです。32ビットCPUや64ビットCPU時代に追加されたレジスタは、初期状態では使用できないです。つまりraxやeaxは、16ビットCPU時代のモードでは使用できないです。axなどは16ビットCPU時代のモードで使用できます。 :16ビットCPU時代のモードを「リアルモード」といいます。32ビットCPU時代以降のモードを「プロテクトモード」といいます。 :2010年代の現代のパソコンでもリアルモードは、下位互換性(かい ごかんせい)などのために残されています。下位互換性とは、古いバージョンのプログラムが動くようにするという事です。 :一般的名パソコンでは、ブート直後(電源の投入直後)はリアルモードになっています。言い換えれば、ブート直後はプロテクトモードではないです。 :なおモードの切り替え方法は、CR0レジスタ(というのがある)の最下位ビットの値が1ならプロテクトモードになります<ref>林高勲 著『X86系コンピュータを動かす理論と実装 作って理解するOS』、技術評論社、2019年10月9日、235ページ</ref> <ref>Igor Zhirkov 著、古川邦夫 監訳『低レベルプログラミング』、翔泳社、2018年01月19日 初版 第1刷 発行、53ページ</ref>。CR0の最下位ビットのが0ならリアルモードです。実際には、プロテクトモードの移行のためには、さらに グローバル デスクリプタ テーブル(GDT)というものを作成する必要があるが、初学者には当面は知らなくていいので、もうプロテウトモードの説明は後回しにする(※ 現時点では未記述)。 さて、この場合での int 0x10 は、alレジスタにある文字を表示できます。 「Hello 」と表示させたければ、「H」だけでなく、同様の操作を繰り返し、「e」「l」「l」「o」を追加で表示させればいいだけなので、 ;コード例 『基本』 :(※ 実際に動きます。 windows7 上の qemu で動作を確認。) <syntaxhighlight lang="asm"> mov ah, 0x0e ; 1文字出力 mov al, 'H' int 0x10 mov al, 'e' int 0x10 mov al, 'l' int 0x10 mov al, 'l' int 0x10 mov al, 'o' int 0x10 times 510 - ($ - $$ ) db 0 db 0x55 , 0xaa </syntaxhighlight> でブート後に「Hello」と表示できます。 === 発展的な話題 === ラベルやジャンプ命令を使うと、繰り返し命令を実装できる。 上の「Hello」のプログラムを、ラベルなどによる繰り返し処理でプログラムするとするなら、下記のようになるl ;コード例 『発展』 <syntaxhighlight lang="asm"> org 0x7c00 mov ah, 0x0e mov si, greet loop_top: mov al, [si] cmp al, 0 ; 0と比較 je done ; 等しければ doneにジャンプ int 0x10 inc si ; 1文字進める jmp loop_top greet: db "Hello greet", 0x00 ;文字の終わりとして 0x00 を使用した times 510 - ($ - $$ ) db 0 db 0x55 , 0xaa done: </syntaxhighlight> ;org 0x7c00 org 0x7c00 とは、このようなテキスト処理をするのにBIOSに予約されている領域が7c00 なので、そこから書き始める必要がある。 org は擬似命令であり、これからの書き込みのメモリ位置を指定する命令である。 ;<code> mov si, greet </code> また、 <code> mov si, greet </code> は形式的には、あたかもラベルgreetの内容を代入するかのような表現ですが、 実際は、単にgreet ラベルの先頭のメモリを代入するだけです。 ;int 0x10 int 0x10 は、繰返し命令の中で、毎回、使用する必要がある。 ;その他の例 次のようlodsb 命令とsiレジスタを使っても良い。lodsbは[ds:si]からalに1バイト読込む(ロード load)命令であり、さらに使用後に自動的にsiレジスタの指し示す位置を1バイトぶんだけインクリメント(DF=0の場合、DF=1の場合はデクリメント)してくれるので、手間が省ける。 ※ 2022年現在のx86プロセッサは、x86命令セットをマイクロ命令に分解し、マイクロ命令の組合せによっては複合的なマイクロ命令に合成し実行しています。ところが、lodsbの様な複雑な命令はマイクロ命令に翻訳されず固定的なマイクロコードにより実行されます。このため、かつて命令読込みのオーバーヘッドがなくせるという理由で「最適化」の代表だった複雑な命令を使うことは、現在は実行速度を低下させることになります。 ;コード例1 <syntaxhighlight lang="asm"> org 0x7c00 mov ah, 0x0e ; 1文字出力を設定 mov si, msg LOOP: lodsb cmp al, 0x00 je Loop_break int 0x10 jmp LOOP Loop_break: msg: db 'Hello, World!', 13, 10, 0 times 510 - ($ - $$ ) db 0 db 0x55 , 0xaa </syntaxhighlight> 解説 lodsb の内容は <syntaxhighlight lang="asm"> mov al, [si] inc si </syntaxhighlight> と等価である(DF=0の場合、また OF, SF, ZF, AF, PF は inc si の結果により修飾されるので厳密には異なる)。 ;その他の例2 cmp al, 0x00 je Loop_break の代わりに test al, al jz Loop_break でも良い。 また test の代わりに or al, al jz Loop_break でも良い。 ※ かつては、定数とレジスタの比較はレジスタファイルの読出しハザードがありストールの原因になりましたが、[[W:Sandy Bridgeマイクロアーキテクチャ|Sandy Bridgeマイクロアーキテクチャ]]以降のプロセッサであればマイクロフュージョンの対象となり、test命令やor命令を使うメリットはなく、專ら可読性を損なうだけです。 ;コード例2 <syntaxhighlight lang="asm"> org 0x7c00 mov ah, 0x0e ; 1文字出力を設定 mov si, msg LOOP: lodsb test al, al jz Loop_break int 0x10 jmp LOOP Loop_break: msg: db 'Hello, World!', 13, 10, 0 times 510 - ($ - $$ ) db 0 db 0x55 , 0xaa </syntaxhighlight> === メモリ直書き === ==== グラフィックのVRAM直書き ==== まず、設定として、 <syntaxhighlight lang="asm"> mov al, 0x13 mov ah,0x00 int 0x10 </syntaxhighlight> というコードが必要です。 int 0x10 はグラフィック割り込みです。 グラフィック割り込みの場合、ahは0に固定するように規格で決まっています。 alによって、ビデオモードを指定しています。 alが0x13なら、320 x 200ドット x 16色モード(8bitカラー) という意味です。 一般的なパソコンではグラフィック描画用のVRAMアドレスは 0xa0000 から 0xaffffの領域が割り当てられています。 なので、mov命令で、このアドレスに書き込むと、VRAMに直書きできます。 で、問題は、通常の16ビットCPUモードのmov命令では、 メモリ番号は4ケタまでしかアクセスできない。「a0000」や「affff」は5ケタであることに注目。 で、しかも、ブートローダ起動中のリアルモードでは、この16ビットCPUのモードである(らしい) なので、ともかく、通常の方法ではアクセスできない。 5ケタのメモリ番号にアクセスするためには、 「セグメント方式」という手法を使う。 簡単に言うと、 :物理アドレス番号 = セグメントベース値×16 + オフセット値 なお、上式の数は十進数である。 16進数になおすと、単にセグメントベース×16は、末尾に0をつけたすだけである。 :※ セグメントベース値の1の違いはオフセット値に換算すれば たった16 なので、よって、もし2つの物理アドレス番号があって、それらのセグメントベースの値が違っていても、オフセット値でそのぶんの差を補う加減があれば、2つの物理アドレス番号が重なることがあるし、用途によっては重なっていても構わない<ref>白崎博生 著『Linuxのブートプロセスをみる』、株式会社KADOKAWA(発行)、アスキー・メディアワークス(プロデュース)、2014年10月2日 初版、20ページ</ref>。 :また、2つのアドレス番号があって、セグメントベース値とオフセット値がそれぞれ異なっていても、「セグメントベース値×16 + オフセット値」の合計値が同じなら、それは同じアドレスを指し示す処理になる<ref>白崎博生 著『Linuxのブートプロセスをみる』、株式会社KADOKAWA(発行)、アスキー・メディアワークス(プロデュース)、2014年10月2日 初版、25ページ</ref>。たとえば 0000:1000 と 0100:0000 は同じアドレスを指し示す(※ 文献『Linuxのブートプロセスをみる』での例)。 これらのセグメントベースを格納するために「セグメントレジスタ」と言う専用のレジスタを使う。 16ビットCPUのセグメントレジスタには :CS (コード セグメント)、 :DS (データ セグメント)、 :ES (エクストラ セグメント)、 :SS (スタック セグメント)、 の4つがある。 なおFSとGSは32ビットCPU以降のセグメントレジスタである。 CSは、CPUが実行するプログラムを格納するためのセグメントとして、CPUに使用させる。 DSは、メモリの読み書きといったデータ関係の手段のセグメントとして、CPUに使用させる。 SSはスタック関係のセグメントで使用。 「エクストラ」とは、「その他」とか「追加の」のような意味。 よく分からなければ「セグメントベース」でググると、詳しく紹介してくれている親切なITブロガー日本人さんが何人かネットにいるので、それらのページを参照してください。 で、書式は、<code>[セグメントベース:オフセット]</code>の書式である。 下記のようなコードで、ブート直後の画面の任意の場所にピクセル単位で色をぬれる。 ;コード例 1 <syntaxhighlight lang="asm"> mov AL, 0x13 ; ビデオモード0x13 mov AH, 0x00 int 0x10 mov BX, 1111 ; ピクセルで書き込みたいアドレスの計算用 mov AX, 0xa000 ; VRAMアクセスのためのセグメント処理で使用 mov DS, AX mov AL, 0x01 ; 色の設定 mov byte [DS:BX], AL ; VRAMに書き込み mov BX, 1112 ; 次に書き込みたいアドレスの計算用 mov byte [DS:BX], AL ; VRAMに書き込み(以下、同様) mov BX, 1113 mov byte [DS:BX], AL mov BX, 1114 mov byte [DS:BX], AL mov AL, 0x031 ; 色の変更 mov BX, 1115 mov byte [DS:BX], AL mov BX, 1116 mov byte [DS:BX], AL mov BX, 1117 mov byte [DS:BX], AL mov BX, 1118 mov byte [DS:BX], AL mov BX, 1119 mov byte [DS:BX], AL mov BX, 1120 mov byte [DS:BX], AL mov BX, 1121 mov byte [DS:BX], AL times 510 - ($-$$) db 0 dw 0xAA55 </syntaxhighlight> ;予備知識 :: mov命令によるメモリへの書き込み  さて、mov 命令でメモリに書き込むには <code>mov BYTE [123], 0x4567 </code> の書式で書き込みます。 この場合、メモリの123番地に、数値(16進数で)4567を書き込むわけです。 <code>[ ]</code> をつけると、メモリへの指示だとアセンブラなどが認識します。 ここでの「BYTE」 は1バイト長で書き込め、という命令です。 2バイト長なら(BYTE でなく) WORD になります。 4バイト長さなら DWORD になります。 :※ なお、WORDやDWORDを使う場合、リトルエンディアンの順序で書き込まれます。 なお :<code>mov al, BYTE [123] </code> のように書いた場合は、メモリ123番地にある内容をレジスタalに書き込め、という命令になります。 このように、(書き込みだけでなく)メモリからの読み込みにも <code>[ ]</code> は使えます。 つまり、 <code>[ ]</code> をつけると、メモリへの指示だとアセンブラなどが認識します。 ;コードの解説 0xa0000は画面の左上だが、そこに色を塗っても見づらいので、 上記コードでは 0xa1111 から色を塗り始めることにした。 なお 0xaffff は画面の右下である。 画面の真ん中の上のほうに、なんか緑色っぽい線が5ミリくらいの長さで水平に引かれている結果が表示されると思う。 上記のコードでは、分かりやすさを重視して、あえて繰り返し命令(ラベルやジャンプ命令で実装できる)を使わなかったが、実際に図形を書きたい場合は、ラベルを活用して繰り返し命令で処理するのが効率的だろう。 なお、上記コード例1で <syntaxhighlight lang="asm"> mov AX, 0xa000 mov DS, AX </syntaxhighlight> とあるが、 これを、(下記はエラーになる) <syntaxhighlight lang="asm"> mov DS, 0xa000 </syntaxhighlight> とまとめても、なぜかエラーになる。 なので、手本のコードのように、レジスタを経由する必要がある。 ==== テキスト直書き ==== :※ 調査中 一般的名パソコンでは、英数字などのテキスト出力も、ブート直後の段階では、専用のメモリ領域が用意されるので、このメモリを書き換えることで、テキスト文字を出力できます。(ただし、漢字や平仮名・カタカナなどは無理。) ブートプログラムの確認作業などに、便利な機能でしょう。 また、 int 命令によって、1文字ずつ書いていく方法は、原理は単純ですが、実装では、処理速度があまり速くないという問題があります。 ラベル命令やジャンプ命令などを使ってコードの行数を減らしても、int命令で書き込みをするよりも、テキスト用メモリを直に書き換えするほうが処理速度が速くなります。 一般的なパソコンでは 0xb800 からの領域がテキスト用メモリに割り当てられています。 なので、まず <syntaxhighlight lang="asm"> mov ax, 0xb800 </syntaxhighlight> と指定します。 === BIOSに予約されたメモリ領域 === メモリ領域のうち、0xa0000 から0xfffff までの領域は通常のパソコンでは、BIOSがハードウェアを管理するために使用することになっています<ref>白崎博生 著『Linuxのブートプロセスをみる』、株式会社KADOKAWA(発行)、アスキー・メディアワークス(プロデュース)、2014年10月2日 初版、70ページ</ref>。 このため、それらハード管理以外のソフトウェア的な処理をするためにメモリ使用したい場合は、この領域を避けてメモリを使用する必要があります。 こういった用途には Linuxなどの現代のオープンソースOSでは、 メモリを使用する際には 0x100000 以降の領域を使うのが一般的です。 原理的には 0xa0000 未満の領域も使用可能ですが、使いすぎ等のミスによって0xa0000以降にハミ出る恐れがあるので、なるべく 0x100000 以降の領域だけを使うほうが安全でしょう。 == ハードディスクなどへのアクセス == まず、フロッピーディスクやハードディスクなどに読み書きのできる割り込み命令で、 int 0x13 というのがあります。 2000年代の現代では、これを大容量デバイス用に拡張した拡張 int 0x13 というのがあります。 どちらの int 0x13 とも、ドライブ番号は、DLレジスタ(データレジスタの下位(Low)の部分)で指定します。 このように、int 0x13 では、割り込み時におけるレジスタの役割が決められています。 ;拡張 int 0x13 さて、拡張 int 0x13 を使って、フロッピーディスクやハードディスクなどの記憶媒体に割り込みをできます。(USB対応については今後の見通しは不明。書き込みできるものもあるようだが、) int 13h は、レジスタなどの数値で 書き込みの方式や対象を指定します。拡張 int 13h と、非格調 int 13h では、レジスタの解釈が違っております。 格調 int 0x13 のほうの方式を LBA方式といいます。 {| class="wikitable" |+ 格調 int 0x13 (LBA方式)の仕様 |- | AH || 読み込みは 42h で固定 |- | AL || 読み込むセクタ数 |- | DL || ドライブ番号 |- | DS:SI || Disk Address Packet のアドレス |- |} 格調 int 0x13 では、レジスタに収まりきらない様々な情報を、任にの Disk Addres Packet (DAP)という場所に配置しており、その形式も決まっています。 ※ 調査中 ;非拡張の int 0x13 なお、拡張されてない int 0x13 は、ハードディスク容量などの小さい時代の古い規格のものであり、現代では、読み書きに時間が掛かったり、あるいは不可能です。 非拡張の int 0x13 では、ドライブ番号は、DLレジスタ(データレジスタの下位(Low)の部分)で指定します。 AHレジスタが 0x02 なら 読込み、AHレジスタが 0x03 なら 書込み です。 {| class="wikitable" |+ 仕様 |- | AH || 読み込みは 0x02 で固定 |- | AL || 読み込むセクタ数 |- | CH || トラック番号(下位8ビット) |- | CL || |- | DH || ヘッド番号 |- | DH || ヘッド番号 |- | DL || ドライブ番号 |- | ES:BX または ES:EBX || 読み込みたい先のアドレス |- |} ;参考サイト :[http://caspar.hazymoon.jp/OpenBSD/misc/hdd.html ディスクBIOS] :[http://jou4.hateblo.jp/entry/2012/12/15/120611 INT 13h - jou4のブログ] {{code|int 13h}}ともいう。 ;参考文献 :林高勲『作って理解するOS』 328ページで、非拡張 int 13h のCHS方式について解説あり。 == キーボードサービス == === int による割り込み === まず、int命令で、キーボードサービスの割りこみがあり、 int 0x16 がキーボードサービスである。 ;コード例 <syntaxhighlight lang="asm"> mov ah, 0x0e ; 1文字出力 mov al, 'p' ; 「pushしろ」・・・のつもり int 0x10 mov al, ' ' int 0x10 mov al, 's' ; 「space」・・・のつもり int 0x10 mov al, ' ' int 0x10 mov al, ' ' int 0x10 .LOOP: mov ah,0x00 ; キーボード入力待ち. 0x10 でもいい int 0x16 cmp al, ' ' ; 空白なのでスペース jne .LOOP ; 直前の比較cmpの結果が偽(否定)だったらループする mov ah, 0x0e ; 1文字出力 mov al, 'f' ; 「finish 終わったよ」・・・のつもり int 0x10 times 510 - ($ - $$ ) db 0 db 0x55 , 0xaa </syntaxhighlight> さてint 0x16 を呼び出す際、 mov ah,0x00 ; キーボード入力待ち. 0x10 でもいい なら、ah = 0x00 は、キーボードのキー入力待ちである。ah = 0x10 だと拡張キーボード対応らしい[http://softwaretechnique.jp/OS_Development/Tips/Bios_Services/keyboard_services.html] 。 === in または out命令による処理 === 実は一般的なパソコンでは、アセンブリ言語の命令で、いくつかのハードウェアに読み書きのアクセスするための、専用の命令がある。 <code>IN</code> 命令と、 <code>OUT</code>命令である。 そして、キーボードなど、昔のどこのパソコンにも存在したハードウェアは、実はハードウェア番号が決められている(「I/Oポートアドレス」などという)。 たとえば、キーボードはハードウェア番号(I/Oポートアドレス)が十六進数で0x60 番である。(メモリマップとは別。メモリアドレスの0x0060などにdb命令で書き込んでも、目的のハードにはアクセスできない。 ) IN命令で、引数で指定したレジスタ(普通はALレジスタやAXレジスタを指定する)に、もうひとつの引数で指定した目的デバイスから送られた値が保存されます。(引数の順序はアセンブラの種類などによって異なるので、説明を除外。) また、OUT命令で、引数で指定したレジスタ(普通はALレジスタやAXレジスタを指定する)に格納されている値が、もうひとつの引数で目的デバイスに送られます。 たとえば、下記のようなコードで、キーボードの文字「E」または前後のWかRを押すと、1行ぶん下の位置に文字「G」が表示される。 ;コード例 <syntaxhighlight lang="asm"> mov al, 'p' ; 「push e」と表示の予定 int 0x10 mov al, 'u' int 0x10 mov al, 's' int 0x10 mov al, 'h' int 0x10 mov al, ' ' int 0x10 mov al, 'E' int 0x10 mov al, 0x0a ;改行の指示 int 0x10 .LOOP: in al, 0x60 ; in al, 0x0060 でもよい cmp al, 18 ; 値が文字 'E' かどうか判定のつもり jne .LOOP ; 偽なら LOOP 冒頭にジャンプ mov ah, 0x0e ; 1文字出力 mov al, 'G' int 0x10 times 510 - ($ - $$ ) db 0 db 0x55 , 0xaa </syntaxhighlight> ;解説 <code> in al, 0x60 </code> を使えば、キーボードコントローラーから送られてきたキーも al に入力されます。 <code>in al, 0x60 </code> とは、けっして「レジスタ al に 60 を代入しろ!」(×、マチガイ)という意味ではなく(そもそも定数の代入だけなら mov 命令だけで可能である)、「ポートアドレス 0x60番 のポートから送信されてきたデータを、レジスタalに代入しろ」という意味です。勘違いしないでください。 そして、キーボードコントローラーのポートアドレスが 0x60 なので、めでたく、上記コードでキーボードから押されたボタンの情報を受け取れます。 さて、キーボードを押したとき、押したボタンに対応するスキャンコードが、パソコン内部にあるキーボードコントローラー(KBC)という装置に送信される仕組みになっています。 このスキャンコードは、アスキーコードとは異なります。 上記コード例にある cmp al, 18 の数値「18」とは、スキャンコードでの番号です。だいたいスキャンコードで18番のあたりが文字 W,E,R のどれかのあたりです。 また、アスキーでは「2」と「"」とは別の文字ですが、しかし日本語キーボードの場合、「2」と「"」はボタンが同じなので、スキャンコードでは同一になります。 このように、物理的に同じ位置にあるかどうかで、スキャンコードは決まります(なお、JIS配列キーボードやUS配列キーボードのように言語が違うキーボードでも、位置が同じなら、ほとんどのボタンのスキャンコードの内容も同じ場合が多い)。 また、スキャンコードは、押されている時に送信されるコード(「メイク コード」という)と、離した瞬間に送信されるコード(「ブレイク コード」という)とが、それぞれ違うコードです。 日本語キーボードは OADG という規格にほぼ統一されています。 ですが、世界的にスキャンコードの規格は、古いものでも3種類くらいあり、さらにUSBキーボードの規格は別です。このため、日本語 OADG のスキャンコードも、現在でも3種類くらいあります。 下記のリンクが詳しいです。 [http://www3.airnet.ne.jp/saka/hardware/keyboard/109scode.html ] なお、一般的に「メイクコード/ブレイクコード」の書式です。 たとえば、ボタン「1」(「!」と同じ)のスキャンコードが「16 / F0 16」とかかれていれば、メイクコードが「16」であり、ブレイクコードが「FD 16」という意味です。(ある規格では、ブレイクコードは、メイクコードの先頭にF0がついたものになっている。) なお、キーボードコントローラーもインテルなどが製造していました。かつて Intel i8042 というキーボードコントローラーが有名でした。 より正確な仕組みとしては、シリアル通信(PS 2 信号)などで送られた信号をKBCあたりでスキャンコードに変換しているわけですが、CPUから見ればスキャンコードしか見えないので、あまり気にしなくていいでしょう。 ;参考サイト [http://softwaretechnique.jp/OS_Development/kernel_loader3.html 0から作るOS開発 カーネルローダその3 プロテクティッドモードへの移行とA20 ] ※ 本wikibooksの当ページが完成するまでの間、上記の参考サイトが分かりやすくて役立つと思いますので勉強してください。 === 出力例? === 次のようなコードを使えばledが点滅するらしいのだが、しかしエミュレータでの実験では分からなかった(Windows起動により、すでにLEDが点灯しているので、区別しづらい)。 <syntaxhighlight lang="asm"> mov al, 0xED out 0x60, al </syntaxhighlight> 0xED というのは、LED点灯に関する命令の番号。 === BPB === 一般的なブートローダのいくつかには、ブートセクタに BIOS Parameter Block (BPB)というものが書かれており、これは BIOS への指示や設定を出すブロックです。 パソコンの電源を投入して、まず最初に起動するのは BIOS なのですから、このブロックが必要です。少なくとも Windows系OSのブートローダーでは、そうなっていると言われています。 このように、ブートセクタは、書式がほぼ決まっています。 <pre> 冒頭でJMP命令で ブートローダ(IPL: Initial Program Loader)へジャンプ BPB IPL 位置0x01FE に 0x55AA と書いて「ここまでがブートローダ」だとBIOSに認識させる </pre> という構成になっています。 ジャンプしてしまうので、BPB はプログラムカウンタでは読み取れず、BPBはBIOSしか読み取れないことに注目しましょう。 市販のOS自作本にある、DB命令で書き込む冒頭の 「DB 0xeb」 と言うのも、このJMP命令のことです。 JMP命令はX86系CPUの機械語では <code>eb</code> です。 [https://www.intel.co.jp/content/dam/www/public/ijkk/jp/ja/documents/developer/IA32_Arh_Dev_Man_Vol2A_i.pdf 『IA-32 インテル®アーキテクチャソフトウェア・デベロッパーズ・マニュアル』『中巻A:命令セット・リファレンスA-M』3-411] == プロテクトモード == プロテクトモードとは、CPUの32ビットモード(および32ビット以上のモード)のこと。 32ビットモードには、アクセス権の無い状態からのアクセスを禁止するという、特権レベルによる保護機能などがあるので、プロテクトモードという。 プロテクトモードにいこうするためのコードの一部を抜粋すると、おおむね書きのような感じになる<ref>白崎博生 著『Linuxのブートプロセスをみる』、株式会社KADOKAWA(発行)、アスキー・メディアワークス(プロデュース)、2014年10月2日 初版、98ページ </ref>。 ;コード例 <syntaxhighlight lang="asm"> mov eax, cr0 ; or ax, 1 ; mov cr0, eax ; 最下位ビットに1を設定 jmp ジャンプ先のラベル ジャンプ先のラベル: mov ax, ここに何か ; mov ax, 0x10 mov ds, ax mov es, ax mov fs, ax mov gs, ax </syntaxhighlight> ;解説 cr0レジスタの最下位ビット(PEビットという)が1だとプロテクトモードである、という仕様である。 <syntaxhighlight lang="asm"> mov eax, cr0 or ax, 1 mov cr0, eax </syntaxhighlight> の3行の処理で、cr0レジスタの最下位ビットを1に設定している。なお、このcr0の最下位ビットのことをプロテクト・エネーブルド pr0tect enebled という意味でPEビットという。 設定後にわざわざジャンプ命令 jmp を通す理由は、CPUの先読みした命令を破棄するためである<ref>白崎博生 著『Linuxのブートプロセスをみる』、株式会社KADOKAWA(発行)、アスキー・メディアワークス(プロデュース)、2014年10月2日 初版、98ページ </ref><ref>林高勲 著『X86系コンピュータを動かす理論と実装 作って理解するOS』、技術評論社、2019年10月9日 初版 第1刷 発行、471ページ</ref> 。ジャンプ命令には、先読みを破棄する機能がある。 なお、パイプラインという仕組みにより、CPUは先読みしている。このパイプラインの先読みを破棄することをフラッシュという。 実はCPUは、いくつか先の命令をすでに先読みしている(これがパイプライン)。プロテクトモード以降では、それが不具合の原因になるので、いったんフラッシュする(カラにする)必要がある。 なので、CPUのパイプラインをフラッシュするためにジャンプ命令を使っている。 ;全体像 さて、一般にWindowsやLinuxなどのOSには、パーティションという、インストール時にハードディスクの使用領域を決める機能がある。 実はCPU側に、メモリに関する機能だが、似たような動作を機能がある。 GDT(グローバル ディスクリプタ テーブル Global Descriptor Table)といって、メモリのアドレスのどこからどこまでがそのCPUで使える領域を定義する機能がある。 で、プロテクトモードでは、あらかじめ、このGDTを設定しないと動作しない。そういう仕様で、むかしのインテルあたりの人が決めてしまったので、従うしかない。 で、実はCPUにGDTレジスタ(GDTR)という、GDTの場所を保管する専用レジスタがあるので、このGDTレジスタにGDTのアドレスなどの情報を入れる必要がある。 さらに、このGDTレジスタに書き込むための専用の命令 lgdt (ロードgdt)があるので、これを使う必要がある。(「書き込みだから save では?」という疑問も、わくかもしれないが、こういう名前に決まってしまってるので、従うしかない。) 同様に IDT(Interrupt Descriptor Table)というのがある。 さらに、16ビット時代の昔はCPUのアドレスバスが20本までだったので、リアルモードでは利用するアドレスバスが20本までという制限が掛かっており、A00からA19までを使用している。A20以降はマスクされている。 この制限のことを「A20のマスク」という。プロテクトモードに以降するためには、このA20のマスクを解除しないといけない。 下記の順序で作業しないといけない。そういう仕様である。 #  GDT(Global Descriptor Table)の作成 #  GDTレジスタの設定 #  IDT(Interrupt Descriptor Table)の作成 #  IDTレジスタの設定 #  A20のマスク解除 #  CPUへの割り込み禁止 #  cr0レジスタの最下位ビット(PEビット)を1に設定 #  CPUの先読み(パイプライン)を除去する(jmp命令で除去できる) #  セグメントレジスタの設定 A20マスクの解除には複数の方法がある。 * キーボードコントローラーから解除 * System Control Portから制御 * BIOSの割り込み命令 int 15 で解除 キーボードコントローラから解除できる理由は、単に昔のインテルかどこかの人が設計したとき、たまたまキーボードコントローラ用のアドレスバスが余ってたからだけと言う理由らしく、あまり技術的な深い意味は無い。 なお作業の順番について、A20のマスク解除の順場は多少前倒しになっても平気なようである。 == Linuxのブートローダはkernelには無い == ある程度、理解が進むと、 Linux など実際に活用されているオープンソースOSのブートローダを調べたいと感じるかもしれません。 まずOSの起動で最初に動くのはブートローダだからです。 しかし Linux を開発している kernel.org のサイトには、ブートローダは無いのです。 Linux で仕様されているブートローダは、Gnu(グニュー)というオープンソース・ソフトウェア団体の作っている GRUB (グラブ)というソフトウェアです。 なのでブートローダをソースコードを探す場合も、Gru Grub のウェブサイトを探す必要があります。 書籍だとアスキー出版『Linuxのブートプロセスを見る』などの題名の書籍で Grub を紹介してるので、ついつい何となく、ソースコードを読むためにリーナスの管理している kernel.org を探しがちですが、しかし、よくよく考えたら、Grub は Linux ではありません(実際、Windows版Grubもある)。 もし『'''Grub'''のブートプロセスを見る』だと売れないので、出版社が「Linuxのブートプロセスを見る」という題名にしたのでしょう。 私たちOS開発をしたい読者は、けっして出版社にマインド・コントロールされたままでは、イケません。真実「Grub は Linux ではない」に気がつきましょう。 Grub のソースコードのダウンロードにgitコマンド(git clone などのコマンド)が必要なので、あらかじめインストールしておくか、Gitコマンドが最初から使える Ubuntu か Fedora などのLinuxをパソコンにインスト-ルしておきましょう。 Git コマンドのインストールと、Git Hub などのウェブサイトとは別物ですので、混同しないようにしましょう。 '''外部リンク''': [https://git-scm.com/ Gitの公式サイト] なお Windows版のGitはVimエディターにしか対応してないとの情報がインストール時に出ますが、しかしわざわざvimを別途インストールしなくても、Win版GitをインストールすればWindwowsコマンドプロンプトでGitコマンドを使えるようになります。 == 参考文献 == === 書籍出版物 === * 白崎博生 著『Linuxのブートプロセスをみる』、株式会社KADOKAWA(発行)、アスキー・メディアワークス(プロデュース)、2014年10月2日 初版 * 内田公太・上川大介 著『自作エミュレータで学ぶX86アーキテクチャ』、株式会社マイナビ (※出版社名)、2015年8月30日 初版 第1刷 発行、 * 林高勲 著『X86系コンピュータを動かす理論と実装 作って理解するOS』、技術評論社、2019年10月9日 初版 第1刷 発行、 * Igor Zhirkov 著、古川邦夫 監訳『低レベルプログラミング』、翔泳社、2018年01月19日 初版 第1刷 発行、 * このほか、マイナビ出版の『OS自作入門』(川合秀美 著)を参考にしたが(同じ出版社の『自作エミュレータで学ぶX86アーキテクチャ』でも川合氏の文献をところどころ引用的に出して技術解説している)、しかし本書 wikibooks では残念ながら技術内容の確認作業には使えなかった(著者の川合氏が技術内容の正確さよりも初心者の取っ付きやすさを優先しているため。また、ところどころ説明が不十分(アセンブリ言語による各論の理解よりも、読者がC言語でコードを作って動かせることや、全体像の把握を重視している、川合氏の方針のため)。)技術内容の確認作業には、上記一覧の別文献を参考にした。あと、川合氏の文献は2005年の出版物という事もあり、古いので、現代の動向の確認には別文献に当たることになった。 なお、上記文献一覧にある林高勲 著『X86系コンピュータを動かす理論と実装 作って理解するOS』(技術評論社)を、川合氏が監修している。 ただし、直接にこそ川合氏の文献を本wikiは参考にしてないものの、しかし川合氏の文献は日本でのOS自作解説書の草分け的な存在なので、間接的には本wikiも影響を大きく受けているだろう。だからこそ、2019年代の現代でも増刷・再版され続けている(絶版になってない)。 他の著者(名誉のため名前は伏せる)のOS自作本の中には、絶版になってしまったものもある。 == 脚注 == <references/> == 関連項目 == * [[詳細Linux|Linux]] * [[詳細Minix|Minix]] * [[詳細FreBSD|FreeBSD]] * [[IA-32入門|IA-32入門]] == 外部リンク == # [http://softwaretechnique.jp/OS_Development/Tips/Bios_Services/video_services.html 『Tips BIOSサービス割り込み ビデオサービス』] # [https://wiki.osdev.org/Main_Page 『Expanded Main Page - OSDev Wiki』](英語) # [http://elm-chan.org/docs/fat.html#notes FATファイルシステムのしくみと操作法] # [https://www.cqpub.co.jp/column/books/2001a/34331PC_Legacy/default.htm パソコンのレガシィI/O活用大全 ] 7ucsr98jydxrvcg4d28xqg2xunbu8u8 ゲームプログラミング/バランス調整 0 27004 206659 206607 2022-08-16T12:44:22Z Honooo 14373 /*異業種? いやいや、それどころか、異人、異世界の事も想像しろ><!!!*/ コラム前まで修正。1/3。 wikitext text/x-wiki {{substub}} 現在の版の著者達は、ゲーム戦闘の調整の経験はないので、現状では本ページの内容は調べ物としては役立ちません。経験があり、かつ人間性も良好な人の協力をお待ちしています。 ==本ページの目的== 本科目『ゲームプログラミング』は、科目名に「プログラミング」とあるとおり、ゲームクリエイターのための教材ではなくプログラマーのための教材です。 従って、話題がプログラミング的な技術的な話題に片寄っています。一般のゲームクリエイターを目指す人には、本書のバランス調整の記述は到底、役立ちません。 プログラマーが、とりあえず何か趣味でゲームを作る際、バランス調整についての調べ物の手間を少なくするためだけの目的の教科書です。 ……と、前編集者Suj. は書いたんだけど、その割にはこの人物の私欲を満たすためだけの駄文が結構くどくど書かれてる気がするんだけど… 気のせいか?まあまだちゃんと読んでないしね、熱でもあるのカナ? コロナか^^? ==バランス調整== ゲームには難易度というものがあるが、そのゲームの面白さのため、あるいは商品としての購買力アップのため、調整し、最適値を見出す必要があるだろう。敵の強さや主人公の強さ、それらを調整し、最適値を見出すための調査、テストプレイなどが必要だ。 より普遍的に、バグ修正、操作性の改善、仕様実装の更新、そして今書いたバランス調整、ゲームを面白く、評価を高めるための様々な改善を、一般にチューニングと呼んでいる。 英語では、難易度の調整のことを「レベルデザイン」と言う。このレベルとは、高低差の意味で、欧米での昔の3Dゲームにおける、マップの高低差を意図しているらしい。このレベルを調整するツールをレベルエディタというが、このマップの高低差の調整で難易度が変わるので、しだいにレベルデザインが難易度の調整の意味になっていったという<ref>川上大典ほか著『ゲームプランとデザインの教科書』、秀和システム、2018年11月1日第1版第1刷、P.57</ref>。 難易度デザイン、という言葉も使われている<ref>川上大典 ほか著『ゲームプランとデザインの教科書』、秀和システム、2018年11月1日 第1版 第1刷、P.58</ref>。 そして、難易度の調整にはマップの処理もあるので、3Dゲームのレベルデザイン担当者は、MAYAなどの3Dグラフィックツールの技能を持っているスタッフが多いという<ref>吉冨賢介『ゲームプランナー入門』、P234</ref>。 ===詰み、を避けたい=== 製品として販売するゲーム、そしてそうでなくとも、プレイヤーがセーブした時点でクリア不能な状況、仕様になっている、つまり、プログラムの流れとして事実上そうなっている、これを「詰み」、と呼んでいますが、それは避ける必要がある。 これはプログラムの構造の問題ですが、ゲームは進行の仕様自体かなりの複雑さを持っていますから、制作者が気付かないうちにプレイヤーがそこに追い込まれる可能性があり、これは娯楽であるゲームとしては避けたい事態です<ref name="twogc78">蛭田健司『ゲームクリエイターの仕事 イマドキのゲーム制作現場を大解剖』、翔泳社、2016年4月14日初版第1刷発行、P78</ref>。 まず、ゲーム全体のバランスとして、平均的なプレイヤーなら、妥当な労力でクリアできる調整も必要でしょう。 ゲームプレイで詰みに追い込まれるのは、プログラムの構造の悪さでもありますが、それを見つけ出すためには、具体的にテストプレイにおいて、少なくとも誰か一人のテストプレイヤーが、そのゲーム内で想定できるクリア困難な状況から、実際に挽回してクリアしたという、事実、実績が必要です。 つまりコンピュータープログラムで常にセキュリティの問題が発生するのと同様に、ゲームプログラムでは構造が複雑になりすぎて、詰みがプログラマーの想定を超えて発生する可能性があるので、実際のプレイで、実際のプレイヤーの現実の巻き返しで確認して調整したい、という事ですね<ref name="twogc78" />。 そして一方難易度調整として、平均的プレイヤーが平均的な労力でクリアできるようにしておきたい。 ちなみに現編集者の昔のゲームプレイ経験ですが、初代ファミコン版のファイナルファンタジーですね、番号は幾つだったか……市販の攻略本を読みながらプレイしていたのですが、あるところまでいった時点で、攻略本を読んでも、どう考えても先に進めない状況に陥り、まあ私のプレイヤーとしての技量にも問題あったのかもしれませんが、結局にっちもさっちもいかなくなって、プレイを放棄してクリアしないまま積みゲーになってしまったことがあります。もちろんそれでそのゲームの仕様が悪かったと主張するつもりはありませんが、プレイヤーの私としてはその時点で完全に詰んでしまったわけです。 ===実はゲームプレイヤーだけではなく、あらゆる人間が面倒くさい、俺も、あんたもね^^=== ……しかしあんまり面倒くさがると、結局最後には偉い人に怒られてしまうのがこの社会の常です^^;;;。 一般にゲームプレイヤーがプレイ中に面倒くさがることは、覚えること、計算すること、配ること、だと言われています<ref>『ゲームプランとデザインの教科書』,P342</ref>。 ゲーム中に、Wolfram|Alpha が使えるような仕様にすると、案外よかったりしてね^^ ===ゲーム制作者はいろいろ考えて作っているだろうけど、プレイヤーだってそれに負けずに考えてプレイしている=== プレーヤーも制作者も、時代の流れとともに、色々な変遷はありますよね。 時々指摘されるようですが、昔よりの最近の方が、ゲームの難しさに関する感受性が大きくて、割と簡単にこのゲームは難しいと指摘されることが多い、と、言われている。 たとえば携帯ゲームにおいて、平均的なゲームプレイヤーがクリアまでに5回ゲームオーバーになるように調整されたゲームは、今では「難しい」ゲームと判断される<ref>『ゲームプランナーの新しい教科書』、P210</ref>。つまり昔のプレイヤーの方が我慢強かったってこと?? 一方平均的なプレイヤーならゲームオーバーにならない難易度のゲームは、やさしいゲームと呼ばれることが多い。 だからもはやゲームの難しい易しいという言葉さえ、相対的で、結構人によって判断が違う。 2011~2013年頃のテレビ番組で、ゲーム業界を取材した番組、夜中の番組で、こういうものがあったという。 「昔の子供は、難しいゲームをプレイしたとき、「このゲームは難しい」と答えていたが、今の子供は「このゲームはつまらない」 と答える」 しかし実はテレビというのはこの社会で一番いい加減なメディアで、常に制作者に都合のいい印象操作、不当なイメージ操作が行われている。 つまり昔の子供より今の子供の方が愚かだというイメージを作りたいだけで、インチキな企業のためのいんちきな広告としての意味以外何も持たないだろう。 ===商業だろうとそうでなかろうとゲーム制作はプレイヤーの事を考える、難易度はどうする?=== 『ナナのリテラシー』という漫画、作者はゲーム好きで、ゲーム雑誌でも描いていたことがあるようです。ビジネス系しかもノウハウ系かな?2巻がゲーム会社回。 ゲーム会社の隅の老人経営者曰く(この漫画内の話ですよ)、「誰もが飛び越せる絶妙な難易度の壁をクリアさせる」、これがゲーム作りのコツじゃ^^!!! この漫画、前編集者が書くにはかなり、そこそこ取材されているという。 「PS」(プレステ)のロードは、「1回のロードで2WMが限界。どんなマップも2メガに入れなくちゃいけない。会話も音楽も全部ね。」なんて描写があるらしい。 この老人の主張は作品自体の主張でも作者の主張でもないというが、しかし前編集者は重要な事だと考えているようだ。 しかし誰もが飛び越せる絶妙な壁をクリアさせて、消費者に快楽を与えて、ガッポガッポも儲けるにしても、人間には個性があり、性格や性質にもばらつきがある。 全ての人に等しく、偉そうに試練を与えて、それを乗り越えたから気持ちいい、と自己満足に等しく浸らせることは難しい。 だから、インチキにガッポがっぽ儲けるためには(←しつこい^^;;;)、ターゲット層をある程度はしぼりこむ必要がある<ref>『ゲームプランとデザインの教科書』、P.97 </ref>。 「遊んだプレイヤー全員が満足するものを、目指さない」との記述がある書籍もある<ref>塩川洋介『ゲームデザイン プロフェッショナル』、技術評論社、2020年10月3日 第1刷発行、P.173</ref>。ただこれはテストプレイヤーの意見を重視しすぎて振り回されないように、という意図がある記述だという。 ターゲット層を絞りこむには、実在の人物をイメージするのが良いと言う。「20代社会人男性が」、ではなく、自分の知人・友人・家族、あの人を面白がらせたい!!、と、いうのがいいようだ<ref>『ゲームデザイン プロフェッショナル』、P205</ref>。 {{コラム|カラケオは気持ちよく歌いたい^^| 80年代~90年代にカラオケが流行した。と、いっても今でも、盛んだけどね。俺も好き^^ カラオケの難易度は、利用者が楽しめるように易しめに作られているようですね。というか前の項目で書いた、絶妙な難易度らしいよ。そこそこ難しく、それを乗り越えると俺は偉いと自己満足にふけれるらしい。岡田斗司夫が90年代後半にその指摘をしていたというが、しかし本当に前編集者は岡田斗司夫が好きなのね^^;;;。 小室哲哉の曲が典型的にそれだという人もいるらしい。そういえば、NHKアニメーション「だぁ!だぁ!だぁ!」のエンディングは凄く良かったな^^。いや、もちろんこれは只の雑談ですが^^;;;。 エヴァンゲリオンの残酷な天使のテーゼは、監督やスポンサーのレコード会社プロデューサーが、子供でも歌いやすいように作曲してくれと作曲家に依頼している。 確かに凝った楽曲の割に、カラオケで歌いやすい^^ }} {{コラム|作者の意図通りに視聴者が受け取るとは限らない。作者の意図とは全く別に受け手は作品を楽しむ。それが嫌ならそもそも創作するなよ。| 商業作品であるなら、最終的には売上によって作品の是非が決まる、なんて前編集者は書いてるけど、インチキ書くなよ、あくまでも金は商売としての是非、作品としての価値、意義は別の話だよ。 しかしこいつほんとにアフリマンなのね。金と物質以外何も見えないのか。 ゲームの話題としては、味の善し悪しはプレイヤーが決める、という言葉があるようですね<ref>『ゲームデザイン プロフェッショナル』、P.167</ref>。ターゲット層が、美味い^^!!、と、いう作品を作りたい。 ジブリアニメの『となりのトトロ』は、子供たちにアニメばかり見ずに外で遊ぶように啓蒙するようなストーリーを作者・監督の宮崎駿は目指したと言われています。 ところでこれ↑前編集者の文章だけど、完全なる虚偽だよ、いいかがんにしろ。あのねー、宮崎さんという人は確かに少し偏屈な大人だから、その手の事は時々言うけど、映画を作る時は基本的に、見た人に楽しんでほしい、夢のような時間を過ごしてほしい、そしてこの社会に生まれてよかったと、子供も大人も思ってほしい、そういう思いで、常にそれが第一テーマで漫画映画を作ってるの。 すじ肉先輩さー、あんた俺や他の編集者を何度も知ったかぶりって書いたけど、結局あんたが人類史上、唯一最大の知ったかぶりだね。そもそもあんた、トトロ、観てないんじゃないの? ほんとにあんたってなにも見えてないのね。「うちの子は、よく宮崎先生のアニメを見ています。面白いアニメを作ってくださり有難うございます」なんて感想は全く問題ないだろ。宮崎氏だってありがたく受け取ってるよ。それに対してアニメばかり観ずに外で遊べ!!なんて言うのはお前とお前の同類のキチガイだけだ。 あとガンダムやエヴァンゲリオンでも似たような逸話があるとのことだが、こっちはどうでもいい。そもそもこれを作っている連中は、宮崎氏ほど切迫した気持ちで作っているわけではなく、ただ金が欲しくて自分が偉いと思いたいだけだから、作った方がどう思おうが、そいつらに金を与えて養ってる連中がどう思おうが、大したことじゃあないだろ? }} ===チュートリアル=== ゲームをプレイするための、操作方法をプレイヤーが知って覚えるための入門的なイベントをチュートリアルというようですね。実は現編集者はあまり、特に最近はほとんどコンピューターゲームはしないので、ここの執筆をしつつもゲームについてはあまり知らない。 ただここの主要執筆者で、ゲーム大好き、プログラム大好き、アニメ大好き、自分自身も一応絵描き、そしてハイルオタキングの E.Suj. かなりひどい内容の文章を大量に書き散らすので、このサイトの参加者として嫌々多少書き直しをせざるを得ない。 そこでチュートリアル、これはふつうゲーム自体に組み込まれ、初盤がそれになりますが、これは別モードにすると良いという指摘がある<ref>『ゲームプランとデザインの教科書』、P401</ref>。 『不思議のダンジョン2 風来のシレン』が、このスタイルを採用している。 とはいえプレイヤーが必ずチュートリアルをプレイしなければ、ゲームを楽しめない構成なら、あまり大きな意味があるとも思えないが、しかしそうでない場合も多いだろう。 ゲーム構成の選択手として考えてもいいだろう。 ===技能の習得としてのゲーム=== ====ゲームをプレイしていることで、プレイヤーは何を知って、何を身につけているか?==== まあゲームをしていることで、プレイヤーは何らかの行為、練習を繰り返して、技能様の物を身につけていく、と、考えても、いい? まあいいか、とりあえずはそう見なしましょう。 ですからそこでプレイヤーが身に着ける技能を想定しておくと、上手にバランス調整が出来るという。 すじにく大先生が愛読している文献では、「教育的難易度」という用語を使っています<ref>吉沢秀雄『ゲームプランナー入門講座』SBクリエイティブ、2015年12月29日 初版第1刷発行、225ページ</ref>。まあゲーム関係者で教育について分かってる奴なんて、ほとんどいないだろうけど… ここでの教育難易度とは、むしろ大先生の意図とは逆で、ある敵を攻略するのにプレイヤーがなんらかの操作が必要な時、まず1個だけのその敵の撃破用の操作技能だけをプレイヤーが修得できれば攻略できるようにしろと、つまり、プレイヤーが技能を覚えやすいように、難易度を下げろという事でしょう。 前編集者は本質的キチガイなので、とにかく世の中で自分が偉いことが何より大事なので「教育」という言葉を使いたい。一方で割と似たようなことを語る時に、学習という言葉を使っている文献もある<ref>『ゲームプランとデザインの教科書』、P.61 </ref>。要するにこの本の筆者の方が、E.Suj. よりまともな人間だという事でしょう。 ただ、プレイヤーの技能の習得という視点は、バランス調整の時に一番重要になるという。確かにゲームは技能や知恵、解決のための何らかの手段、鍛錬も必要だが、一方では間違いなく娯楽で、面白いものであるはずだ。 そしてゲームをすることで、自分の思考力が磨かれて、成長したという感慨を持つプレイヤーも多いようで<ref>https://www.teu.ac.jp/ap_page/koukai/2019_03_3endo.pdf 66ページ</ref>、全くその気持ちを否定する意図はないが、でもねー、ゲームっていうのは結局遊びなんだよ? ゲーミフィケーションなんて言葉を使っていい気になっている連中もいるようだけど、まあその概念や運動がまったく意味を持たないとは言わないが、でもやっぱりゲームは娯楽であり遊びであり、ある程度堕落した、ある程度常識的な硬い世界からは非難される要素があるもので、あまり理屈を並べて自分たちの世界が高級なものだと主張しない方がいいんじゃあない? {{コラム|ゲーミフィケーション| どうもゲーム業界の連中が、自分たちの仕事を美化して、正当化したいため、ゲーミフィケーションがどうの、なんて言いだしたようだよ<ref>https://news.denfaminicogamer.jp/kikakuthetower/190731a</ref>。 2019年にゲーミフィケーション学会設立。もっともこの運動や概念がまったく意味がないものだとは、現編集者も言わない。確かにゲーム的な行為を、もう少し遊びから離れて、現実の有用な出来事に結び付けようというのは、それほど間違っていないし、意義はある。 2013年ごろからすでに、企業の新人研修で、ゲームの要素を取り入れた研修などがされていたようだ。 岸本好弘(ファミスタの父、と呼ばれているらしい)の言では、「ゲームの本質っていうのは、人間が頭で想像することの素晴らしさ」<ref>https://www.fantasy.co.jp/edutainment/article/interview16</ref>ってことらしいけど、なんか軽い言葉だね。想像には意義があるが、それってほんとに頭でするもの? 40年前(※1980頃?)、 :「そのころアーケードゲームのデザインで言われていたのは、初めてそのゲームに挑戦したプレイヤーでも3分間程度は遊べるようにすること。「もう一度チャレンジしたら、先に進めそうだ!」と、プレイヤーの気持ちが動くように制作すること」 ってことだけど、そうすれば子供が100円玉いっぱい入れて、お前らが儲かるってだけだろ? :「これって、現在IT業界で言われるUX、ユーザーエクスペリエンスですよね。ゲーム業界では理論化、言語化していなかったけれど、40年前から現代に通じることをやっていたんだなと思いました。」 何かそれらしい言葉だけ踊ってかっこつけてるようにしか聞こえん^^;;;。 :「ゲームって全部「そそのかし」なんです。ゲームをプレイしていて、Aの洞窟に行きなさいとか、Bの洞窟には行くなとは言われないですよね。プレイヤーが2つの洞窟をぱっと見たときに「こっちの洞窟に宝があるかも!」って見えるように作っているんです。これを「そそのかし」って言うんです。」 まあそれはそれでいいけど、それってそんなに大したことかね? : (抜粋)「先生は答えを教えるのではなく、生徒が自分で「わかった!」、「僕が一人で気が付いた!」と思わせることが大切。」 思わせるっていうのがすごいし、傲慢だよな。お前は神か? : 「ゲームをデザインするのも授業をデザインするのも同じです。楽しいと思うことやワクワクすることは脳の働きを最大限にする。だから、つらいことを我慢するのはよくない。脳が楽しいと感じることがとても大切なんです。」 お前みたいな奴って、すぐ脳がどうのって言うよな。まあ楽しいことやワクワクするのが大事なのは認めるが、人生つらいことを我慢しなければいけない時なんてしょっちゅうだよ。後ゲームと授業は別物にしろ、一緒にするな。 しかし思うんだけど、ゲーム業界の奴らって、自分たちの仕事に少しやましさがあるから、教育と結び付けて、高級なものに仕立て上げたいんじゃあないの? まあゲーム的な教育っていうのはありだが、やはりゲームの本質は遊びで娯楽で、しかも堕落だよ。 }} {{コラム|すじ肉しちゅ~は今日も右手を上げて、「ハイル、オタキング!!!」と言った。| 1990年代後半に、オタキング岡田斗司夫は、著書『世紀の大怪獣!!オカダ―岡田斗司夫のお蔵出し 』(おそらく)で、マリオカートを例に、市販のゲームソフトの多くは達成感を味合わせるものだと指摘した。 岡田に言わせれば、ゲーム文化以前の人生の趣味の多くは、必ずしも努力の量と、上達とが比例しない。スポーツ、絵画、しかしこれほんと?もちろん厳密に量を考えて、グダグダ気色悪い比較をすれば、そう見えることはあるけど、少なくとも人間、何かをすれば必ず、それなりに得るものがあるはずなんだけどね。 しかしファミコン以降のコンピュータ式のゲームでは努力は無駄にならず、ほぼ必ずといっていいくらい、少なくとも初心者レベルの範囲でなら、プレイして練習すれば上達するように設計されていると、岡田の著書では述べられている。 ふーん、要するにゲームプレイヤーって、ゲーム制作者が作った達成感が欲しいから、金払うってわけね。 岡田が言うには、人生はゲームみたいに甘くないし、もしかしたらゲームは現実逃避で不健全かもしれないけど、でも大人だって親だって達成感をもっと感じたいんだぜ・・・だから今日も娘といっしょにマリオカートをプレイしている、と書いてたって言うけど、そもそも現実逃避や不健全から達成感って手に入る? なんか頭のおかしい奴はやたら達成感って言うんだけど、それってほんとに欲しい? いや、もちろんある程度は欲しいけど、でもそんな重要な事かね? もっと人生で必要なもの、いっぱいないかね? }} {{コラム|ガイナックスとはオタキング岡田斗司夫が創業した、アニメーションとコンピューターゲームの制作会社である。| ガイナックスは、コンピューターゲームも作っていたね。確か、美少女18禁ソフトもあったよね。 1991年、『プリンセスメーカー』、育成シミュレーションゲーム。確かに赤井孝美さんのグラフィックは魅力的だった。 少女を光源氏的に育成するゲームだったか、キャラクター育成ゲームのはしりだね<ref>STUDIO SHIN『ゲームプランナーの新しい教科書』、翔泳社、2018年3月10日 初版 第2刷 発行、P182</ref>。 98年にはコナミ社『ときめきメモリアル』というのが出た。ただこれは育成というよりは、美少女との恋愛疑似体験ゲームみたいな、まあ俺はやったことないから詳細は知らないけど、まあ美少女と上手に付き合えるように、男性キャラクターを育成する要素はあったのかね。 「プリンセスメーカー」→「同級生」→「ときメモ」の流れがあるって、ある評論家は言う。 良くわからないけど、岡田斗司夫はゲーム制作会社の社長でもあるんだから、前のコラムの達成感がどうののたわごとに意義を認めろって、すじ肉は書くんだけど、なんなのこいつ。 岡田斗司夫の肩書に関する議論って意味ある? 別にアニメ評論家でも、会社社長でも、なんでも勝手に名乗って威張っていればいいけど、でもやっぱり岡田斗司夫の肩書は、オタキングだよね。 }} {{コラム|プリンセスメーカーdeathpenalty| 少女育成ゲーム・プリンセスメーカーは全滅時の損失が軽いのが、割と画期的だったようです。戦闘で全滅すると、拠点に戻されたうえ、1か月経過する。 全滅時の損失のことを和製英語でデス ペナルティといいます。英語では dead damage と云うらしい(DDと略すようです)。英語の death penalty は「死刑」の意味だって。 つまりどうやら、デスペナルティが軽くても、面白いはRPG は作れるらしい。 ;デスルーラ 全滅しても拠点に戻るだけのシステムだと、拠点に戻りたい場合にわざと全滅する方法を使える。これを和製英語で「デスルーラ」と言う。ルーラとはドラクエの移動魔法ルーラのこと。 全滅したときに拠点に戻るゲームでは、拠点に戻れなくするイベントは不可能。 全滅したら拠点に戻れるからね。ただ、戦いが起こらなければどうかな? どちらにしろこの議論、意味ある? ただ例外的に全滅したとき拠点以外に戻る、っていう事は仕様で作れるよね。 }} {{コラム|Roblox,Among_Us| 現編集者は現在は基本的に、コンピューターゲームはしない生活、でもほんのちょっと前、思うところあって、MicrosoftStore,Xbox 経由で、すこしゲームをしていた時期があった。 そしてMicrosoftStore はなんだかんだでゲームを売り込んでくるよね。 その時思ったんだけど、Roblox って面白そうだよねー。プレイはしていないんだけど、広告や表示を見ると、これ絶対面白いなって直感的に思う。 だからこのゲームのユーザーやプレイヤー、あるいは関係者にこのページの執筆してほしいな^^ 後、Among_Us っていうのも面白そう。何か皮肉がすごく効いてそうだね。 }} {{コラム|デスペナルティ関連| このコラム、前編集者が、(この話題は、後述の商学書『メイド・イン・ジャパンは負けるのか』の話題と関連するので、残す必要がある。)ってメモを張っていたんだけど、読んでみたんだけど、現編集者Hにはちょっと話が見えなくてね。おそらくRPG をやりこんでいる人は内容が良くわかるんだろうけど、現編集者にとってはかなりの部分が???????だね。だからできるだけまとめる一方で、詳細不明の部分は前編集者の記述をそのまま残しました。 ;帰り道を通せんぼするイベントは、詰みのリスクが高くなる。 サガシリーズはどこでもセーブできるが、この場合、帰り道を通せんぼするイベントは、上手に設計しないとクリア不能になる恐れがある。 ファミコン~スーファミ時代のドラクエとファイナルファンタジー、GB版サガとロマサガには帰り道を通せんぼするイベントは無いように見える。 ロマサガ1の氷結城の帰り道で通せんぼするボス敵がいる。しかし会話選択肢で戦闘を回避すると、詰みを避けられる。 古い時代のサガ系とロマサガでは、ダンジョン奥まで探検すると、最深部に一方通行のダンジョン出口がある。これは帰り道短縮の意味と、テンポ感向上(プレイヤーが既に理解していることを再度要求しないから)の効果がある。 しかしこの場合、もしダンジョンに一方通行出口がない場合、プレイヤーは帰り道にボス戦があると予測する。これはネタバレになってよくない。ドラクエは、最後の一方通行出口をあまり用意しないが、この狙いがあるのだろう。 このようにゲームのルール設定が、可能なイベントやマップを限定する。 }} さて、ゲームのシリーズ物は、ルールが一様になる傾向がある。 だから、シリーズ作品によって搭載されるイベントの傾向も決まってくる。 イベントの傾向が限定されると、マンネリ化につながる恐れもある。 『メイド・イン・ジャパンは負けるのか』という2010年ごろの書籍でも、 シリーズ化とマンネリ化との相互関係が語られていて、基本的に家庭用ゲーム機の作品群の多くはゲーム性の根幹が90年代以降の作品は変わっておらず、変わったのはグラフィックが細かくなっただけ、と書かれている。 しかしゲーム会社からすれば、新規の斬新な発想のゲームはむしろ売れないと見られている。 グラフィック重視は、商業ゲームでは非常に重要と考えられているらしい。 そしてゲーム評論家は偉そうな批判はするが、自分では結局ゲームを作らない。 1980年代は、家庭用ゲーム黎明期。1995年ごろ、プレステ1時代からソフト容量が飛躍的に伸びた。 昔はゲームに勢いがあったが、今となっては、新しくて画期的かつリアリティと説得力のあるルールを思いつくこと自体、そんな簡単な事ではない。 漫画産業やアニメーション産業は黎明期をとっくに過ぎたようだが、結局今でもこの産業は続いている。そもそも、ラジオ、新聞、書籍、オールドメディアと呼んでいい産業も、今、しっかり続いている。2010年代のゲーム産業だって、もしかしたらスマホゲーム黎明期、ソーシャルゲーム黎明期なのかもしれない。 {{コラム|オタキングアノマリー論| オタキングによるアノマリー(片寄り)論(『東大オタク学講座』に記述あり)によると、ゲームのバランス調整は結局普遍性は持たず、作家の世界観が反映されるものになる、という。 都市運営シミュレーション『シムシティ』、アメリカ製のゲームですが、ここでは火力発電所よりも原子力発電所の方が効果的な投資になっている。これは現実の経済情勢を正しく反映しているか? これは現実の経済分析の話だが、現編集者はYESだと思っている。巨大なお金が動いているからこそ、いまだにこの国は原発をやめられない。 そして岡田はこの設定をアメリカ的な都市政策観の反映だとしている。しかし岡田はこのゲームの感覚を片寄りだと思っているのか? そのほか、岡田は、ドラクエシリーズに対して、「なぜ作者の堀井さんは、作中で父親と子の関係に、どの作品でも、こだわりたがるんだろう? なにかあったんじゃねえの?」的なゲスい勘繰りもしています。 ↑ちなみに上の段落は前編集者、E.Suj.の記述をそのまま残したものだが、まあね、オタキングがゲスい人間なのは、オタク全員が知っているからね^^;;;。 ここで書いたシムシティに関する議論と堀井氏に関する議論はどうも別の話のように見える。 つまり前編集者の議論は当初から混乱しているのだが、結局E.Suj. は作家の個性とは異常性の裏返しだと言いたいらしい。つまり個性とは長所ではなく、欠点の別形態だと。 では現編集者はこのE.Suj. に質問したいが、結局人間、個性持っていたほうがいいの?持っていない方がいいの? 大人は欠点すらうまく自分で活用しなければいけない、なんて書いてるけど、そんなこと上手く出来ている大人なんて、この地球上に一人もいないよ。 }} ====本文==== さて、上述までの再編集により、前編集者E.Suj, の邪念から生まれた、ゲーム-教育-成長のインチキ理論は完全に否定できたと思う。 結局前編集者もゲームにおける教育論は疑似的なものだと記述してるが、そんなら最初っからそんなこと書くな。 地獄のような長時間の再編集を終え、やっと話を本題のバランス調整にもどせることになった。 まずアクションゲームの調整。 敵が飛び道具で来るならどうする? もちろん事実上はほぼ無限の対応策があるが、例えば、物陰に隠れながら移動して近づく、あるいはこちらも飛び道具で応戦とか、幾つか具体策は見えるでしょう。 (しかしよく考えたら、この行動って、E.Suj.のこのサイトでの行動とそっくりだよね^^;;;。) 基本的にゲームバランス調整では、例えば、物陰に隠れて攻撃を避けるなどの具体的技法、そして事実上それはそのゲームでの有効策なのですが、プレイヤーがこの対応策を覚えるように導く、そしてそれを可能なものにするため難易度を下げる、これが必要だと言います<ref>吉沢秀雄『ゲームプランナー入門講座』SBクリエイティブ、2015年12月29日初版第1刷発行、226ページ</ref>。 一つの方針としては、必要だと思われる技能をプレイヤーが行っていると判断したら、しかも一度には基本的に一つ、その敵を簡単に倒せるようなプログラムにする。 とにかく特定の方向にプレーヤーを導く意図を持つ、つまり導きたい方向にプレイヤーが行為すれば、難易度が下がる。だから、飛び道具を避ける物陰には、罠も無ければ敵もいない<ref>吉沢秀雄『ゲームプランナー集中講座』SBクリエイティブ、2015年12月29日初版第1刷発行、226ページ</ref>。 あれっ、今気づいたんだけど、新約聖書には、狭き門から入れ、って言葉があったよね…。 基本的には前編集をわかり易く書き直してるだけなんだけど… とにかくこの場合、推奨されるパラメーター設定は、目的の敵を妥当な経過で主人公が攻撃したら、敵はすぐ倒せるようにしておけって書いてるんだけど、これって広き門じゃあない? とにかくこの前編集は、あらゆるプログラムを駆使して、プレイヤーが特定の行動をするよう導けって書いてある…。 まあしかしまとめ編集を続けるかね… 大抵のゲームは先に進むと難易度が上がっていくようだが、いや、これ自体事実かどうか怪しいが、仮にそうするとした場合、その難易度の上がった敵のギミックや行動は、制作者が導く行動を複数、と言ってもごく少数の複合だろうが、プレイヤーがなしたら、敵を倒せるようにしたら良いという。複合技をプレイヤーが繰り出すことで、成長した感や、興奮を、ユーザーは感じるだろう<ref>吉沢秀雄『ゲームプランナー集中講座』SBクリエイティブ、2015年12月29日 初版 第1刷発行、228ページ</ref>。 前編集者は、ゲームの後半難易度を上げるのは、プレイヤーに創意工夫を呼び起こすためと書いている。 確かに難易度が上がれば、創意工夫して解決を目指すのはゲームだけではない。しかし現編集者が問題を感じるのは、常にプログラムの手妻を駆使して、特定行動にユーザを導けと主張している点だ。 これは実はアメリカの過去の宇宙開発で宇宙に送る実験動物を調教、教育した方法と全く同じだ。 とにかくゲーム制作者の中に、このような馬鹿げた教育論を持っている愚か者はそこそこいそうだが。 このインチキな前編集者の愛読書には、ボス戦などの難しいイベントの目的は、プレイヤーが自分自身の技量を試す、自分がこのゲームにおける熟練プレイヤーか試す、そこにあるという。歯ごたえのある敵と戦って、自分がこのゲームにはまっているかどうか知る事が出来る、そういうことだろう<ref>吉冨賢介『ゲームプランナー入門』、P60</ref>。 ;やはり何事も制限はあるか? 例えば主人公が不死身なら、まあゲームになりませんよね。何らかの弱いところは必ずあるでしょう。 所持金が無限とか、無いですよね。お前はドラえもんのポケットか?^^;;; 敵もそこそこ強いよね、あんまり弱いのはちょっと。 (たとえばアクションゲームで一時停止ボタン(ポーズボタン)を押さずにトイレに行ってウンコを数分してきても、ウンコから戻ってきてもキャラが負けてないのは明らかに駄目)。 ↑ちなみにこれは前編集者の記述だけど、ん~、まあ、残しておくか^^;;;。 だから前編集者としては、プレイヤーに創意工夫を求める。まあもっともプレイヤーが創意工夫しないゲームなんて、この世にないけど。 だからゲームオーバーはやっぱり必要だということか<ref>川上大典 ほか著『ゲームプランとデザインの教科書』、秀和システム、2018年11月1日第1版第1刷、P.254</ref>。 だから前編集者はゲームには敗北とそれを回避するための努力が必要だと主張する。 まあでもこのサイトの別の場所でも書いたけど、E.Suj.は努力なんて全くしてないけどね。ただ毎日欲望のまま手を動かしてるだけ。 ;真実は一つ^^!!!本当?とりあえず解法は複数^^!!!! スーパーマリオのステージ1-1の最初のクリボーをどうする? (解1)踏んずけてやる^^!!!(解2)そのクリボーを飛び越えてこっちに来い!!!^^(解3)ブロックに乗って、絶景哉^^。 ====ゲームと漫画、アニメーション==== 非常におおざっぱに語ると、漫画やアニメーションは完成して世に出た時点で、その版では、定められた運命が記述されている、ヤーンの書のようなものでしょう。 ゲームはインタラクティブだから、運命は決まっていないし、あいまいで、事実上選択肢がある世界。 そしてゲーム=戦闘ではないが、戦闘を描いたゲーム、漫画、アニメーション、 というのは明らかにある、そしてその話なんですが… 1982年『鳥山明のヘタッピマンガ研究所』という書籍では、マンガやアニメや特撮(ウルトラマン)などの敵の強さは、主人公がなんとか苦戦しながら倒せるギリギリの強さだと指摘されている。ただしこの出典関係の記述にはWiki著書の記憶違いがあるかもしれない。 しかしゲームでの敵は、もうちょっと弱めにしておくといいらしい。 まあそりゃあそうだよね。毎回毎回ギリギリの敵と戦うなら、ゲームなんて誰もしなくなるよ。これに関して前編集者はプレイヤーの創意工夫がどうのなんて書いてるけど、完全なる欺瞞だろう。 具体作品を上げると、ゲーム『激神フリーザ』。要するにドラゴンボール原作のゲームですね。クリリンでもちょっと鍛えて頑張ればザーボン(ナメック星編の中ボス敵)を倒せるようになっている(原作マンガだとクリリンはザーボンを倒せない)。 漫画やアニメーションでは、一回の戦闘での強敵の倒しかたが一通りしかなく、いちばん読者に魅力的に見える奇想天外・破天荒な倒しかたで、敵を倒します。なのでここでは、ギリギリ倒せる強さのほうが良い。 しかしゲームの強敵では、多くのプレイヤーの、それぞれ異なる色々なアイデアに対応した倒し方を何通りも準備する必要があるので、ゲームでの強敵の強さは、ギリギリ倒せる状態よりも少し弱めにする必要がある。しかしやはりそれ以前に、あまり敵が強すぎたら、プレイヤーがしんどすぎるだろ、単に難易度が高いゲームになっちゃうよ。 ==== 「廃人」 ==== 基本的にコンピューターゲーム界隈は、いちびった下品な人間が多いので、そこで飛び交う言葉も汚い言葉が多い。 例えば、廃人、なんてよく言うらしいよ。つまりいろいろな理由で暇な人間、まあ、E,Suj. もそうだけど、普通に忙しい人間より、ネットゲームとかでは有利だよね。そういう人間を貶めたくて言うんだね。 後色々な理由でゲームに過度にお金を費やせる人に悪口言いたい時とかね。 まあはっきり言って、E.Suj. も間違いなくこの廃人の一人だけど、彼の愛読書では、「廃課金ユーザー」という記述にしているらしい<ref>『ゲームプランとデザインの教科書』、P66</ref>。「廃Wikiユーザー」とか? だけど世の中色々でね。人にはそれぞれ事情がある。望まなくても廃人になってしまう人はいっぱいいるよ。 ===ゲーム作者が自作をプレイしたら、やはり他者プレイヤーよりそのゲームは簡単だと見なすだろう。=== あらゆる分野で作者は自作は面白いし、難易度やネガティブな要素は低いと見るだろう。作り手は妥当なバランスをどう見出したら良いだろうか? ====作者が客観的に自作を見る事さえ難しい、しかしいいバランスは見つけ出したい==== やはり常識的な判断としても、経験則としても、作者がやや簡単だと思うくらいがちょうどいい、という事だろう<ref>STUDIO SHIN 著『ゲームプランナーの新しい教科書』、翔泳社、2018年3月10日 初版第2刷発行、54ページ</ref>。 プレイヤーにとっては易しいほうの案Aと難しいほうの案Bとがあったら、ゲーム本編には、やさしいほうの案Aを採用するのが良い<ref>吉沢秀雄『ゲームプランナー集中講座』SBクリエイティブ、2015年12月29日初版第1刷発行、P207および235ページ</ref>。 難しい方の案Bは、付加的なサブステージ(クリアには不要な)に流用するといいですかね<ref>吉沢秀雄『ゲームプランナー集中講座』SBクリエイティブ、2015年12月29日 初版第1刷発行、P207および235ページ</ref>。 RPGにおいてはクリアに絶対に必要なイベントと、エクストラのクリア条件ではないイベントがありますね。それぞれ「強制イベント」、「任意イベント」と、呼ぶこともあります<ref>STUDIO SHIN著『ゲームプランナーの新しい教科書』、P198</ref>。 サブステージや任意イベントの難易度は、割と自由に扱う事が出来そう。むしろ様々な難易度があった方が、多様なユーザーの要求に対応しているとも言えるし、しかしそもそもサブステージなどなくてもいいとも言えますが、あるとしたら、遊びは多くなりますよね<ref>吉沢秀雄『ゲームプランナー集中講座』SBクリエイティブ、2015年12月29日初版第1刷発行、P208</ref>。 そして基本的に作り手は「簡単」だと思っていても、初めてプレイするプレイヤーには難しい、それはよくあることですよね<ref>吉冨賢介『ゲームプランナー入門』、P56</ref>。 ====レベル上げを楽しむ?==== 一般的なゲームは、例えばRPGでは、ストーリーや戦術性の面白さが普遍的な主流の興味ですよね。作り手も、RPGというジャンルが今現在、どういう一般的な魅力があるか、それを考えて、それを重視して作る。 一方プレイヤーとしては、正道を外れたややマニアックな楽しみ方もある。RPGのレベル上げ(だけ)を楽しむ、なんて遊び方もできますよね。 つまりプレイヤーはプレイヤーで、本来の制作者が意図した別のところで楽しみを見出すこともある。ある意味コンピュータープログラムのインタラクティブな性質が、そういう遊び方を見出す余地を持っていると言える。 しかし制作者はやはり、RPGの持つ本道の面白さを目指してゲームを作るでしょう。 前編集者はこのことを、少年漫画を例に語っていますね。 漫画家スポコン漫画(そう?^^;;)「バクマン」では、こんなエピソードがあったようです。 「たとえ少女の読者がいても、その少女は、「男の子が読んでいるマンガを自分も読んでみたい」、と思うような女の子。少年ジャンプの取るべき編集姿勢としては、あくまで、男の子向けを貫かないといけない」 少年漫画誌は、ターゲットは、少年、割と年少の男の子ですからね。それ以外のファンがいても、その読者層におもねる漫画は載せないでしょう。それはカテゴリ崩壊だよね。 しかし実は少年にもいろいろな個性を持つ子がいる。少女にも、大人にも、老人にもいろいろな個性がある。ターゲットがどうのと言ったところで、実は結構あいまいでいい加減な物なんだよね。 少年ジャンプは自らの分析として、売れる漫画の方向性として、「友情・努力・勝利」の3原則を提唱した。この3原則を外すことは今現在は許されてはいないのでしょう。 ====No title.==== ある意味当然のことだが、ゲームの作者は、ほかのプレイヤーより、自身のゲームの難易度を低いと見るだろう。「作者バイアス」という言葉が使われることもある。 ;雑誌「ゲーム批評」による指摘 1990年代に「ゲーム批評」という雑誌が、ゲームの内容を考えるときは、ゲーム制作に熟練していない人は、既存ゲームを難しくアレンジした提案をしがちだと指摘しています。 例えば、スーパーファミコン版のマリオ、こういうゲームを自分たちが作る時、どういうゲームにしようか? マリオが空を飛んだ時、簡単にクリアできるけど、ここで空中に敵キャラクターを多く配置したらどうだろうか? そして『超音速攻撃ヘリ エアーウルフ』、、云々の記述が前編集にあったが、これはいつものこの前編集者の一般的な他者に対する愚弄目的の文章なので、再掲載する必要はないだろう。 そしてこのアイディアに対する、一般的な批判としては、マリオの地上ステージの空中に敵が少ないのは、ゲームが苦手なプレイヤーのための救済措置だったり、あるいは体験済みステージ前半を無視するための工夫、であるので、その部分を難しく、複雑にするのは不適切だと思われる、と、いうことになる。 ところでやや話題が脱線するが、過去少年マガジンに掲載されていた、漫画作品、[[w:1・2の三四郎]]にも、似たような話があった。 高校生の主人公、東 三四郎と、本当はレスリング部にしたい西上 馬之助と三四郎の友人南小路 虎吉の三人で柔道部の活動をしていたのだが、ある日三四郎が馬之助にこう言う。 「スタンハンセンのウエスタンラリアット(プロレスの技)の改良技を考えたのだが」 「ほう」 「ハンセンは、ラリアットを打撃技にしているが、ここで打撃しないで、首に引っかけるようにして倒して後頭部をマットに打ち付けるのはどうだろう?」 「あほ!!それはジャイアント馬場の、ランニング・ネックブリーカー・ドロップや。ハンセンはそれをもとにウエスタンラリアットを考えたの。なんでお前がわざわざそれをもとに戻してんのや」 ただ、今ではこのジャイアント馬場云々は俗説と言われているようですね。 少しマリオの話とは違うかもしれませんが、脱線の雑談として書いてみました^^ さて、今仮に、「ゲーム作者はネットの批評はあまり参考にしない。基本的にゲームを作ったことのない人の意見はあまり意味がないと考えている。」と、いう主張があったところで、あなたはこの意見をどう思いますか? まず全くの素の状態でこの言及を聴いたところで、その通りだと思います?あるいはいや、違うと思います?。 そしてもし素の状態ではなく、仮に出典とやらがあった場合、出典と言ってもいろいろありますよね。ネットの言及の場合もあるし、あるいは何らかの偉そうな市販の書籍にそう書いてあるかもしれない。 この辺の出典とかの情報、事実で意見変わります? だからあなたが素の状態でどう思おうと、偉そうな人の言及があったら、じゃあそれは正しいんだと思いますか?。 しかしまあこの言及の場合は、ゲーム作家とやらが、ああ、俺はそう思っていると言えば、一つの証言となりますよね。 しかしゲーム作家だって複数いる。しかもゲーム作家と呼んでいい人とは具体的にだれか? ですから現編集者はこの議論は全く無意味だと考える。しかし実は前編集者もやりたいことは、ただただ商業の創作者を持ち上げて、ネット上や同人の創作者を貶めたいだけなんですよね。 とにかく前編集者は私欲を見たすために、この言及の出典とやらを探しましたが、辛うじて、「一次情報以外、個性には役立たない:インターネットやSNS:そうした情報は知識として役に立つことはありますが、ゲームデザイナーが個性を発揮するうえではあまり役に立ちません<ref>『ゲームデザイン プロフェショナル』、P314</ref>」という記述を見つけただけだったという。 {{コラム|マリオメーカー、他| マリオメーカーは任天堂が2015に発売した、Wii U用の(3DS用も有)ゲームソフトウェアですね。マリオのゲームの素材を使って、自分でもアクションマリオゲームが作れる。 このソフトウェアでは、自作のマリオゲームを任天堂のWebサイトに投稿、公開する事が出来ます。しかし条件があって、一度そのゲームをクリアしないと、公開はできません。 そして一方、実は、マリオメーカーが発売される前、インターネット上には「改造マリオ」といって、マリオのROMを違法改造して、自作ステージをつくって無料公開する行為が行われていました。 実際には改造マリオのデータを、ゲームとして利用するのはなかなか手間がかかり、むしろそのプレイ映像を動画化し、それが動画サイトで人気になったようです。しかし改造マリオを作るという行為自体が、著作権の問題を持っていました。 そして多くの場合、そのステージの難易度は異常に高くなり、そしてその難易度の高いマリオを実際にクリアする動画が非常に人気を持ったようです。 さて、そこでこのことに関して、前編集者は例え話を始めたのですが、まず一つ目が、「犬が人をかんでもニュースにならないが、人が犬をかむとニュースになる」、だそうです。 つまり…改造マリオの方が人が犬を噛んでいる? すると任天堂本家のマリオメーカーが、犬が人を噛んでいるか? 辛うじてこの例え話の意味は分かるけど、もう一つの例え話がこれ↓なんだけど… また、アンケート調査などの心理学的ノウハウとして、「あなたは○○を買いますか?」と「あなたは○○を好きですか?」と聞いたときでは、アンケート結果の傾向がかなり異なり、多くの人が、「○○を好きですか?」と質問されても決して実際に好きなものを答えるのではなく、世間から賞賛されそうな趣味趣向の場合にだけ回答で「はい、好きです」と答えるようであるという、分析結果があります。 これはさらによくわからん(?_?)????? マリオメーカーは買うで、改造マリオは好き? 要するにいつものこの編集者の議論で、商業のマリオメーカーを褒め称えて、Web文化の改造マリオは貶めたいんだろうね。 まあ改造マリオは違法性があるから、別にそれはそれでいいけど… }} {{コラム|とにかく E.Suj. はWeb文化を貶めて、商業文化を誉めそやしたい| 確かにWeb上には無料コンテンツも多々あるが、商売人たちが仕掛けているのは、有料コンテンツのための撒き餌のようなものだ。一方で同人、アマチュア活動として、無料で作品を公開している人もたくさんいるし、これらのコンテンツまで貶めようと試みる E.Suj. は本当に性根の腐った嫌な人間だね。勿論違法性のある無料コンテンツもあるから、これらは当然非難されてしかるものだろう。 まずゲームに関しては、前編集者の報告では、実際にプレイすることなく、無料動画を見ただけとか、あるいはさらに悪い例はWeb上の言論だけをもとに、特定のゲームを批判する人物がいるようで、これは確かに良くないことだ。 漫画界でも、似たような問題があるようだ。マンガ『ラーメン発見伝』(小学館ビッグコミックスペリオール )では、作中のライバル役のラーメン屋経営者(いわゆる「ラーメンハゲ」)が、ネットの情報をもとにラーメンの実際の食べたときの味を無視してラーメン評論をするラーメンマニアに陰口で悪態をついています。確かに漫画だろうが、ラーメンだろうが、映画だろうが、小説だろうが、実物に触れないのにあれこれ言うのは、基本的には悪いことだろう。 とはいえ現編集者は、[[v:Topic:読まないのに書評]]なんてやっちゃったけどね。まあ気にすんなよ^^;;;。 そこで前編集者は、Webを徹底的に否定して、市販本だけに価値を置いているけど、それも極論じゃあない? ゲームを実際にプレイしないで、各種情報で知った気になるのは確かに良くないこと<ref>『ゲームデザイン プロフェッショナル』、P.282</ref>だけど、我々だってすべてのゲームはプレイできないよ。 それに各種情報から、何となくいけ好かない存在って誰にでもあるものだし、まあ基本悪口はよくないけど、Webは新しい混沌メディアだからね。市販の書籍やゲームが圧倒的に価値高いわけではないね。 新聞の第一面によく載っている、有り得なく馬鹿馬鹿しい書籍の広告、あんなの絶対に買わないし、読まなくたって無条件で悪口言いたくなるよ。 とにかく E.Suj.はゲームに関して、メジャー作品、人気作をプレイせよ<ref>『ゲームデザイン プロフェッショナル』、P280</ref>、なんて書くけど大きなお世話。自分のプレイするゲームは自分で選ぶね。 YouTube動画に、「アニメ私塾」というチャンネルがあるらしくて、そこで勧める絵の練習法は、プロのアニメ作品の模写らしいけど、これだって単に一つの意見。絵の勉強法なんて無数にあるよ。 まあ確かに漫画に関する違法サイト読書は問題だろうし、検挙もされているけど、同人誌やエロ関係の無断掲載は検挙もしていないように見える。 ただそこで漫画を読むことは倫理的に非難はされるけど、読んだ以上は、作品を読んでいないという評価は違うだろう。勿論不正な方法で読んだという非難は正当だけどね。 結局、E.Suj.の目的は、いい加減な言論を駆使して、既成の商業コンテンツの権威と金を守りたいんだろう。 }} アナログゲーム(カードゲームやボードゲーム)の設計者は、ネット上の意見はもとより、実際のテストプレイヤーの意見さえあまりあてにならないという考えがあるらしい。テストプレーヤーも様々な理由で本音を語らなかったり、何らかのバイアスであまり有用な意見が出てこないという見方もある。一番重視するのは、実際のプレイの様子を観察することだいう<ref>『ゲームプランとデザインの教科書』、P338</ref>。 {{コラム|世のメディアでは、人気投票企画は多いが、基本的には遊びでお祭りでファンサービスで、本格的な統計調査とは別物だろう。| イナズマイレブン、2008発売のサッカーRPG。アニメ化や映画化もされている。中学校サッカー部が舞台だから、中学生がメインターゲットだろう。 この公式サイトが、登場キャラクターの人気投票を行ったという。 作品中に、五条というマイナーキャラクターがいた。中学生で、おじさんぽい顔、眼鏡で目が隠れ、何を考えているかわからない不気味な悪役的キャラクター。 ある匿名掲示板で、おそらく[[w:2ちゃんねる]]だと思いますが、このキャラクターへの組織票投票の呼びかけが行われました。 はたして2(5)ちゃんねるに中学生のユーザーがいるのか? 少しはいるかもしれないが、やはりこの組織票祭りの参加者の多くはもっと年長、しかしそれほど年寄りのメンバーもいないように思われる。 まあ結局オタクどもの遊び、祭りということだろうが、しかしその影響か、その公式サイトでの人気投票結果は、五条が一位になった。 まあ不合理な結果と言えば結果だが、ネット上ではその手の馬鹿げたことはしょっちゅう起こる。少しこだわりのある変わり者たちが、自然な状態をかき乱したくて、色々なことを仕掛けてくる。 公式サイトの運営者としては、面白くない展開だが、そもそもイナズマイレブンのゲームユーザーの何割が中学生か? 購買層の中に明らかにこの手のオタク、大きなお友達が、かなりの数占めているだろう。 しかしこういう人たちが、企画内容に大きな影響を及ぼすなら、やはり運営としては面白くない話だ。 AKB48の人気投票は、CDに投票券をつけている形式だが、やはりここでも不規則状況を狙って、投票券目当てでおなじCDを何枚も購入するファンがいるらしい。 勿論この手の、奇矯な手妻は、人気投票の企画者にとっては、面白くないことだが、しかし世の中こういう変わり者は必ずある程度いるものでね、それはそれぞれの企画者が上手に運営方法考えればいいのであって、こんな話をこのページにわざわざコラムとか言って書く意味ある? ;美人投票 経済学者ケインズは、投資家の行動を美人投票にたとえた。「100枚の写真の中から最も美人だと思う人に投票してもらい、最も投票が多かった人に投票した人達に賞品を与える」、投資家は、この手の美人投票に参加しているようなものだと。普通の美人投票では、自分自身が美人だと思う女性に投票する。しかしこの投資家の美人投票では、賞品目当てなので、自分自身がどう思うかより、票が集まる写真はどれかを予想して投票するだろう。 前述のイナズマイレブンの投票祭りも、自分が好きな登場人物に投票しているわけではない。地味で目立たないキャラクターが一位になれば面白かろうと、示し合わせて、不美人投票をしているのだ。 ;ノイジー・マイノリティ ノイジー・マイノリティとは、少数派であるのにその声は大きい、目立つ、目立つにかかわらず、そのような考え方、主張をする人は少数である、だから基本的にはその人たちの大きい声は聞き入れない方が良い、多数派の意見を反映していない、ということでしょう。 基本的にはネガティブな意味を持つ言葉であり、大騒ぎするクレーマーに近いイメージだろう。 なるほどね、確かに現編集者の主張はいつでも希少な少数派の意見に近いだろう。 そしてすじ肉しちゅ~なる人物はいつも多数派の味方で、多数派の安易で愚かな意見が絶対的に正しいと振りかざし、他者を愚弄し常に暴力をふるっている。 そういう多数派の暴力に対抗するために、マイノリティとして常に俺は大騒ぎしているのだが、物は言いよう、言い方を少し変えれば、集団、多数派の暴力が正しいと、言い張る事が出来るんだね。 衆愚の暴力とは、どこまでも防ぐのが困難なのね。 }} さて、我々は学業でも、スポーツでも、趣味でも、そしてもちろん仕事でも、必ず技能というのがあって、それを日々身に着けている、身に着けようと試みていると考えていいと思いますが、果たして今の自分はどんな技能を持っているのか?そもそも何らかの技能持っているのか?そういうことで悩んだり考え込んでしまうことはありますよね。 E.Suj.のように集団におもねる以外の生き方を一切知らず、大した技能なんかないのに、スキルスキルと威張り倒して他人を貶めること以外何もしない人間がいる一方で、かなりの技能を持っているのに自信が持てず、鬱々と生活している人間もいます。 勿論技能自体はかなり客観的な物でしょうが、他者の技能評価は結構いいかげんで、技能が大したない人間が威張り散らして、ある程度技能がある人間をこき下ろして貶めている事なんて、世の中でしょっちゅう起こっていますよ。 そこで大した話ではないんですが、ある技能からある技能に転向する場合がありますよね。つまり生活自体が変わるのでしょう。特定の技能をふるう生活から別の技能中心の生活に変わること。 具体的にゲーム業務に関する話題では、デザイナーからプランナーに役務が変わるとか… その時にはやはり、デザイナーとしての自分は封印したほうがいい<ref>大久保磨『レベルデザイン徹底指南書』、2016年12月14日 初版 第1刷発行、P81</ref>。 やはりプランナーとしての仕事を優先し、デザインに関してあまり大上段に口を出さない方がいいでしょう。 {{コラム|一人で何でも出来るわけではない。しかし偏向した愚か者の集団より、一人の総合的な人間の方が、相対的にいいものを作り出すだろう。| 基本的に商業漫画、商業アニメーション、そしてほとんど多くの商業メディアはその根源的な創作部分でさえ、多人数の協業で作られています。一応全体を統括する指揮者はいますが、個々の秀逸な表現はその監督だけの手柄ではない。 これはこの手の物事についてある程度知っている人間にとっては、もちろんたまには例外もありますが、ほぼ当たり前のことで、得意げに語ることでも何でもない。 「と学会」の人が2010年ごろにニコニコ生放送の番組に出演したときに、この人物は、ある漫画原作者にネタ提供したと語ったという。しかしネタ提供といっても様々な形態があり、ピンからキリまであり、実際にその作品に貢献していない場合もあるし、単にこいつ、自慢話したかっただけだろ? 漫画家にしろ脚本家にしろ、色々な事柄にアイディアの元を頼っているだろう。有償無償に関わらず、アドバイザーも多いと思う。 ゴルゴ13なんかは明らかに協業で作られていたし、各種映画やテレビドラマも、様々な人間がその作品の質の向上に寄与している。 歴史ものや軍事物、その分野の専門家が強力に考証を加えているし、当然設定の信頼度も高くなる。 だから創作作品は協業関係が上手に機能して、それを統一した理念でまとめ上げれば、当然質はかなり高いものを作る事が出来る。 }} {{コラム|可処分時間| 経理には「可処分所得」という用語があります。労働者の給料のうち、税金や社会保険料など支払いが義務付けられているものを差し引いた、残りの自由に使えるぶんの金額です。勿論その中から自分の生活費は支出しなければいけませんがね。 そこから類推して「可処分時間」。 前編集者の言葉では、「1日のうちの自分の起きている時間のうち、労働時間などを差し引いた、残りの自由に使える時間」。 だから、もし無職で何らかの理由で生活できるなら、100%が可処分時間でしょう。 で、E.Suj. はこのサイトで、こういう人間をひたすら愚弄するような文章を書き続けて来たのですが、 E.Suj. 自身の可処分時間は何%? 仮にこのサイトでインチキ書いてお金が入っても、それは可処分時間に入れろよ? そして…「商売の競争とは、消費者の可処分所得の奪い合い」ということらしいけど…希少な可処分時間を奪われたうえ、そいつらに金払うの? 可処分時間って必ず金払って埋めなければいけないの? }} ===ドラゴンクエストは、ゲームを進めるため、ゲーム操作の技能を得ることを求めていない?=== ドラゴンクエストでは、ゲームのプレイを続け、キャラクターのレベルが上がっていくごとに、キャラクターも戦闘力が上がり、より強い敵も倒せるようになる。これはそれ以前のアーケードゲームのように、プレイヤーがゲーム操作の上手な技能を身に着けることによってクリアするのではなく、レベルが上がることで事実上、プレイヤーが上手な操作する必要なく強くなっている。これを、「クリア保障」と呼んでいるWebコンテンツもある<ref>https://news.denfaminicogamer.jp/column05/170905b 2020年12月21日に閲覧して確認.</ref>。 ドラクエでダンジョンに入った場合でも、様々な試行錯誤は繰り返すであろうが、プレイし続けて時間経過とともに経験値が上がると、最後にはダンジョンのボスも倒す事が出来て、クリアする事が出来る。 つまりドラゴンクエストでは、プレイヤーがそのゲームの操作の技能を覚えることで、難易度の高いステージをクリアしているのではなく、ゲームを続け、経験値が上がりレベルが上がることによって、ある意味自動的に強くなっている。 序盤のダンジョンで未探検のものがある場合、その時点ではかなり探索は困難を極めるが、レベルが上がった時点では、割と簡単に、クリアできる。つまり難易度が自動的に下がっているともいえる。 つまりドラゴンクエストのクリアシステムは、ゲームを続けてプレイを重ねていくうちに自動的にキャラクターは強くなり、最後にはゲームクリア、コンプリートに至る、ということだろう。 ドラゴンクエストのようなインターフェイスでも、古いゲームやフリーゲームではこの特徴を満たしてはいないものがあると、前編集者は書いていたが、どういう事だろう? 何度も書くが現編集者はそれ程沢山ゲームをやりこんでいるわけではない。 アクションゲームでは当然難易度の高いステージはそれなりの技能やテクニックが必要だろう。しかしRPGではそれほど技能の必要や出る幕もないから、多かれ少なかれドラゴンクエストのような形態にはなるのではないだろうか? 全体を通してレベルがそれほど上がらないゲームというのはあるし、あったのだろう。この場合は何らかのゲーム上の困難の打開策や有効な戦術を見出さない限り、クリア困難の事態に陥るだろう。 RPGに限らず一般に、ゲームの後半に行くに従って、次ステージ攻略などのための事前準備の増加や、試行錯誤の時間の増加に時間のかかるようになっていく事が多い。そして、ステージクリアに必要な時間の増加が、ゲームを苦手とするプレイヤーに、そのゲームのクリアを諦めさせる<ref>http://endohlab.org/paper/whydoplayersdrop.pdf 2020年12月21日に閲覧して確認.</ref>。つまり娯楽であるはずのゲームが、難易度が上がりすぎてその機能を果たさなくなるのだろう。 === 自由度 === 一本道で難題を乗り越えるゲームもありますが、いっぽうでマルチエンディングとか、攻略ルートや展開が複数あるゲームもありますよね。こういう自由度の高いゲームは、その展開の場合の数に応じて、調整の際に考慮する事項も増えていきます<ref>『ゲームクリエイターの仕事 イマドキのゲーム制作現場を大解剖!』、P78</ref>。 ===Non-title=== ※バランス調整に限った話題ではないが、他に適した単元が見つからないし、メインページに書くほどでもないので(←なら書かないで削除せよ。by E.H.)、間借り(まがり)的にバランス調整のページで書くことにする。ただし、この節の内容を他のぺージに移動することは、 E.H.が禁止する。 ====ゲーム業界に就職したい?==== ……ならば、今現在の業界を構成している人達のアドバイスに従うのが無難だろう。 まず彼らが望むのは、ゲーム人気作の知識。特にデザイナーならなおさららしい。まず過去の名作は手本になるという。それから共通言語としての、コンセプトや知識を知っておくべきだと<ref>『ゲームデザイン プロフェッショナル』、P278</ref>。 とにかくゲームについて知らないのはよくないようだ。過去現在の人気作や、自分の興味ある、そして入社出来たら実際に作っているジャンルのゲームについて、プレイし、周辺知識も知っておきたい。 ====[https://www.uta-net.com/movie/59818/ シッパイマン]==== この節のタイトルは、失敗とは何かを知りたければ、以下を読むよりリンク先を見た方がいいだろう、という意味のリンク付きタイトルです。 基本的に前編集者は手本がなくては生きていけないようで、創意工夫という言葉もあまり知らない。そして権威ある手本のパワーに依存しまくって、他者を愚弄しまくる。 しかしまあとりあえず、その論旨に乗っかって記述するが、人気作や人気シリーズをとりあえず崇めて手本にせよと。そして人気でない作も良く調べて、崇める手本と比べてどこが良くないか見いだせ<ref>https://news.denfaminicogamer.jp/interview/200615a/3 2020年11月27日に閲覧して確認.</ref>、と。 そしてなぜか前編集者はゲームの事だけで完結せず、アニメの事も語りたがるんだけど、まあ好きだからなんだろうけど、ガンダムについて語りたければ、それ以前のロボットアニメについても調べろ、と、岡田斗司夫や氷川竜介が書いていたんだって。 結局、性格の汚い有名人の権威に頼りっぱなし。 そしてまたまた岡田斗司夫の著作によると、演劇作家・演出家の鴻上尚史氏はゲーム進出に失敗したらしい。失敗してたの^^;;;??? 現編集者はそれは知らなかった。ゲームに手を出したことは知っていたけど…そもそも鴻上さん、映画制作も失敗していなかった^^;;;?。特別に好きでファンだという訳ではないけど、一時期この人のラジオかなり聴いていたんだけど… とにかく岡田氏の結論は、鴻上氏とどういう関連があるかはわからないが、「成功例から学びたがる人は多いが、しかし成功例だけから学ぶのは素人。プロは失敗例にこそ学ぶ。」、らしい。もっともこれはあくまでも前編集者の要約だけど… うーん、プロだの素人だのはどうでもいいけど、失敗と成功の両方から学ぶのは、ごくごく当たり前で妥当なことじゃないの? あと失敗に関しては、畑村洋太郎氏の失敗学という概念もある。<ref>https://www.jstage.jst.go.jp/article/jjlp1960/43/2/43_2_182/_pdf</ref> {{コラム|「失敗を恐れるな!!」なんてよく言うけど、実は誰もが失敗は怖い。むしろその怖さや失敗自体との向き合い方が問題なのだろう。| まあ現実問題として、失敗のない人生なんてないよね。 かと言ってねー、そう簡単に人間成功しないし、物事上手くいかないものだよ。 とにかくどん欲に成功を求めすぎるのも、逆説的に失敗の元になるだろう あとあまり点数とか量について考えない方がいいと思う。 マーフィーの法則ではないけど、この世界と我々の人生は明らかに失敗方向にバイアスがかかっている。 失点しても試合に勝てばいいという意見もあるけど<ref>『ゲームデザイン プロフェッショナル』、P.334</ref>、結局ぼろ負けして泣いて帰ることもしょっちゅうだよ^^;;;。 しかしまあ、誰もがそこそこ成功したいよね。 だけどさー、なんだかんだであんたらの人生、物事上手くいって楽しいときは確実にあるでしょ? }} ===異業種? いやいや、それどころか、異人、異世界の事も想像しろ><!!!=== ゲームとは文化でもあるでしょうか。様々な文化の一分野? そうなると文芸とかイラストとか、短歌とか映画とか、小説とか漫画とか、様々な文化のジャンルがありますよね。 特定のジャンルが衰退するとか発展するとか、具体的にはどういうことですか? もちろん商業文化としての、流通の規模というのはありますよね。しかし文化というのはだれ一人手掛けなくても、自分自身がその創作活動を続け、何らかの形で発表し、そしてそれを享受する人がある程度いる以上、仮にお金は一切発生しなくても、完全にこの世から消え去ることはない。 2012年に新日本プロレスリングを買収したゲーム会社のブシロードは、こう述べた。「すべてのジャンルはマニアが潰す」<ref>https://newspicks.com/news/4135958/body/ 2021年11月7日に確認→ただし有料コンテンツなので表紙を確認しただけ^^;;;</ref>。マニアねー。そもそもオタクとマニアはどう違うの? オタキングを崇拝している人たちは、マニアは悪く言えるけど、オタクは悪く言えないよね? どっちにしろ大した言及じゃあないよ、馬鹿げた話だね。 そしてゲーム業界は、1990~2000年の一時期、ジャンルによってはゲームが高難易度化した作品が多くなって、新規参入者が苦手と感じてプレイヤーが減って衰退縮小していったことがあったという。 まずゲームのジャンルが明確に固定化されているとは思えない。ある程度はそれ様の物はあると思うけど、結局これって、ゲーム商売の話であって、もっと一般にゲームが好きな人たちの事を考えると、特定のジャンルが好きならば絶対自分たち自身でその分野を盛り上げようとするだろうし、そういう人たちが少なければ当然ジャンルの規模は小さくなり、小さくなったり消えてしまったところで、それはそれ、歴史の流れなんじゃあない? ゲームセンターの対戦格闘ゲームでは、初心者が筐体をプレイすると、熟練者が参入して、初心者を打ち負かす「初心者狩り」が起こり、初心者が楽しめない、参入者が減ってそのジャンル自体が衰退、ということもあったようです。 スポーツ競技でも似たようなことが起きると言うが、まあ結局この社会、やさしいいい人なんてほとんどいないし、本当の意味で賢い人間もほとんどいない。 とにかくどんな分野でも、事実上楽しくなければ、人は去っていくだろう。 {{コラム|作者は答えを知ってしまっている| バランス調整とは少し違いますが、作者はネタバレを知ってるので、シナリオに感動できないわけです。 これは、ハドソン(ゲーム会社名)の『新桃太郎伝説』(スーファミ版)の攻略本『新桃太郎伝説 究極本』(KKベストセラーズ 刊)で、作者の さくま あきら が、読者インタビューに答える形でそう言っています。 ゲーム雑誌での読者からの「ゲーム中、もっとも印象に残ったシーンはどこですか?」という旨の質問に対し、さくま氏は「作者はシナリオの答えを知ってるので、もっとも印象に残るとかそういうのはありません」的な内容の返答をしています。 }} ;ティッシュテスター さて、作者バイアスでバランスが分からなくなるのは作者だけではなく、テストプレイヤーやデバッガーも、そのゲームに慣れてゆくと、次第に感覚が一般プレイヤーとズレていき、テストプレイヤー達もゲームの適切なバランス側が分からなくなっていく。 このことを比喩した表現として、「ティッシュ テスター」(tissue tester)という用語がある。使い捨てティッシュが1枚あたり1度しか使えないように、そのゲームに予備知識の無いテスターも、一度しか使えないのである。「フレッシュミート」(新鮮な肉、fresh meat)とも言います。 かといって、テストプレイヤーの人数にも限りがあるので、ゲーム作者は、たとえ自作ゲームのバランス調整が不完全でも、最低限の調整をしたら、もう「えいやっ」と(フリーゲームや同人ゲームなら)ゲームのver1.00および以降バージョンを出さざるを得ない。 単にバグを探すだけのデバッグ用テストならティッシュテスターでなくても可能ですが、しかしバランス調整ではティッシュテスターがいたほうが効率的です。 === 要素の相互関係 === ==== 概要 ==== 文献『ゲームデザイン プロフェッショナル』によると、調整は、関連あるものを、まとめて同時期に、ただし1個ずつ調整していきます<ref>『ゲームデザイン プロフェッショナル』、P.182</ref>。 このため、まだ関連ある要素を実装しきっていない段階では、調整しません。だから開発の最初から調整することは、まず無いでしょう。 しかし、場合によっては、要素の実装をそろうの待つと調整開始の時期が遅くなりすぎてしまい、計画に支障が出る場合があります。そういう場合、ある程度のまとまりのある実装ができた段階で、調整をするようです。 具体的な調整の判断基準については、参考文献『ゲームデザイン プロフェッショナル』を買ってお読みください。 もし読者が練習として、てっとり早くレベルデザイン・バランス調整の経験を積みたい場合、角川書店(現: KADOKAWA)の『RPGツクール』という制作ツールで実際にゲームを作ってみるのが良いでしょう。文献『レベルデザイン徹底指南書』(大久保磨 著)でも、RPGツクールによる練習・勉強を進めています<ref>大久保磨『レベルデザイン徹底指南書』、2016年12月14日 初版 第1刷発行、P81</ref>。 ==== マップと敵の相互関係 ==== ゲームバランスを決めるのは、敵の強さだけでなく、マップの構成、さらにRPGのダンジョンなら宝箱の中にあるアイテムや装備品の強さ、などなどのさまざまな要素が加わります。 宝箱もマップの構成要素ですから、広い意味では宝箱もマップだとすると、つまり敵そのもののの強さだけでなく、マップもバランス調整に大きく影響します。だから、もし仮に時間が無限にあるのなら、理想的には、ダンジョンなど各ステージののマップが実装されてからバランス調整を行うのが理想でしょう。 しかし、実際には、マップの実装は、なかなか時間の掛かることです。特に、マップを考えることは、そのステージの世界観などを考えることでもあるので、そういった理系的ではない文系的なことも考えなければなりません。 マップに敵を組み込む方式で調整する場合だとマップの実装を待っている間にはバランス調整が出来ないのも、なかなか難しい問題です。 だからマップと敵の調整の順序は、おそらく人や会社によって色々な方式があると思います。たとえば、 :マップを作ってからそのマップに敵を組み込んでみてプレイしてみて、敵の強さを決めるのか、 :それとも敵の強さを決めてから、マップを決めるのか、 :あるいはマップと敵を別々に決めてから、最後に組み合わせて微調整するのか、 などなどです。 ご自身の作品にあった方式をお選びください。 ===== 始めよければ全てよし ===== さて、ゲームが長編になる場合、まずはプロトタイプ的に、序盤をやや多めに通しプレイをして、とりあえず序盤のバランスがゲームとして面白くなるように調整すると良いでしょう。 書籍『ゲームプランナー集中講座』でも、ゲームの初めと終わりの印象がよければ、途中のバランスが少しくらい悪くても楽しんでもらえると述べています<ref>『ゲームプランナー集中講座』、P236</ref>。 :※ なお、アニメ産業でも、実はテレビアニメは、第1話と最終話だけ、他のエピソードよりも予算が多めに作られるのが普通です(特に公言はされてないが、多くの作品で明らかにクオリティが違う場合が多い)。 とはいえ、ゲーム制作当初は、そもそも終盤のストーリーがまだ未完成だったりするので、意図せずとも、こういったプロトタイプ的に序盤をやや多めに調整する方法が自然に行われる事になるでしょう。 商業作品でも、たとえば攻略本やファンブックなどに書いてあるゲーム開発裏話などを見ると、RPGでは、(プレイヤーからは数値の見えない)敵の強さのほうを動かすことで、バランスを調整するという事例などもよく紹介されています。よくある話が、最終ボスなどの能力値です。原理的には、敵側の能力値ではなく、味方の能力値で調整したり、あるいは装備品で調整したりしてもイイはずですが、しかしよく開発裏話に出てくるのは、なぜか敵側の能力値の話題ばかりです。 たとえば、スーファミRPG『新 桃太郎伝説』では、最終ボスのパラメータのほうを調整していることが、KKベストセラーズ(出版社名)から出た攻略本『新桃太郎伝説究極本』に書かれています。(調整前はボスはもっとHPが多かった。) :※ただし、あくまでRPG限定の話題。アクションゲームなどでは、違うかもしれない。 また、こういった調整順序の前提として、調整はゲーム序盤から順番に、ゲーム後半に向かって調整していくしかありません。 そのため、古いゲームなどでは、よくゲーム後半で、調整不足のために、極端に難しかったり、あるいは逆にあっけなく簡単すぎる後半だったりなどの話題も、よく聞きます。ドラクエ2の後半ダンジョンであるロンダルキア洞窟とその次ステージが典型です。 さて、プレイヤーに目立つ部分(たとえば味方キャラの能力値や装備品の性能など)を基準にして調整するといって、けっして全く数値をイジラないというワケではないのです。あくまで、(調整による変動幅の大きい敵能力値と比べたら、)「比較的には、味方キャラ関連の数値は、調整による数値の変動の幅が小さめ。敵の能力値は、調整による変動の幅が大きい。」という事にすぎません。 {{コラム|ノイマン「ゲーム理論」で説明できないのがテレビゲーム| 日本の人類学者の中沢新一は、ノイマンのゲーム理論で説明できないのが昨今のコンピュータゲームの特徴だと言っています。その発言の出典は忘れたのですが、人類学者で有名な中沢新一は近年、ゲーム産業に関心を持ち、たとえばナムコ出身の遠藤雅信などとも対談しています<ref>https://news.denfaminicogamer.jp/kikakuthetower/nakagawa-endo_bb/2 『ゼビウスからポケモンGOまで… 国内ゲーム史を遠藤雅伸氏と『現代ゲーム全史』著者が振り返る。中沢新一氏も壇上に登場!【イベントレポ】』 2017年4月12日 12:30 公開 ] 2022年1月18日に確認. </ref>。(なお、リンク先イベント記事の司会役の「中川」氏とゲストの「中沢」氏は別人なので、混同しないように) ゲーム理論の用途としては、現代日本の学問では、政治的局面での外交戦略などを語る際によく政治学書で用いられたりします。ただし、そのゲーム理論でも、中沢新一によると、それでコンピュータゲームを語るのは不足だという事です。 中沢は特に言及していないですが、数学的にモデル化するなら、政策応用なら「国際情勢」など外交的な制約によって出力にとりうる値1個あたりの幅や個数が2~3個に限定されたりのような、値の個数が十分に小さくて有限の整数個の場合でないと、なかなかゲーム理論の応用は効果を発揮しません。 (20世紀の天才数学者 フォン・ノイマンの)『ゲーム理論』のような出力値に選べる個数が極端に少ない理論は、コンピュータゲームの調整では不足でしょう。本ページでも、ノイマンのゲーム理論については、版にもよりますが、このコラム以外では特に言及していないだろうと思います(2022年1月までの時点では、ノイマンのゲーム理論には言及していない)。 さて中沢の意見ではないですが、そもそもゲーム理論についてノイマンについての出典として、たしか数学者の森毅(もり つよし)のエッセイ本だったと思いますが、ゲーム理論はもともとノイマンが第二次大戦中の亡命中か何かにトランプのポーカーを参考に考えついたらしいです。 ネット上のゲーム評論では、経済由来の表現でよく使われる表現は、ゲーム理論ではなく「インフレ」「デフレ」などといった表現です。 経済学を知らなくてもゲームは製作できるでしょうが、どうしても経済学を参考にするなら、ゲーム理論よりも物価政策のほうを勉強したほうが良いかもしれません。 一応、書籍『ゲーム作りの発想法と企画書の作り方』ではゲーム理論も紹介されていますが、しかし具体的にどうゲーム作りにゲーム理論を応用するかは書かれていません<ref>『ゲーム作りの発想法と企画書の作り方』、P64</ref>。 }} === 各論(デザイン的なこと) === どの程度、レベル上昇でキャラクターを強くすればいいかについては、ハドソン社あたりでの有名な慣習があり、新しく訪れたダンジョンなどでは「レベルが3上がると、敵を1撃で倒せるようにすべし」という有名な基準があります<ref>『ゲームプランとデザインの教科書』、P.94、 ※ 著者のひとりの「平川らいあん」氏はハドソン出身</ref>。他社ゲームでは別かもしれませんが、だいたいスーファミ時代の桃太郎伝説シリーズはこんな感じに調整されているはずです。 == RPGのダメージ計算式 == === 特化型が有利になりやすい === 文献『ゲームプランとデザインの教科書』によると、ファミコン時代のゲームに限らず、21世紀の現代的なゲームでも、「なんでも平均的にできる」キャラクターよりも「○○だけなら自分が一番強い」といった感じの特化型のキャラクターが戦闘では強くなりやすい傾向があります<ref>川上大典 ほか著『ゲームプランとデザインの教科書』、秀和システム、2018年11月1日 第1版 第1刷、P.227</ref>。対して、バランス型は「器用貧乏」になりやすいのが現状です<ref>川上大典 ほか著『ゲームプランとデザインの教科書』、秀和システム、、2018年11月1日 第1版 第1刷、P.227</ref>。 なお文献『ゲーム作りの発想法と企画書の作り方』によると、ダメージ計算式を考えるのは(プログラマーの仕事ではなく)ゲームデザイナーの仕事です<ref>『ゲーム作りの発想法と企画書の作り方』、P145</ref>。 では、特化型が有利になりやすい原理を、これから説明していきます。 たとえば、キャラクターに能力をプレイヤーが自由に選んで振り分け配分できるシステムのゲームがあったとしましょう。(商業ゲームでも、いくつかの作品で、似たようなシステムのRPGがあります。) 説明の単純化のため、合計値が必ず100だとしましょう。 つまり、たとえば下記のようになります。 ;作成キャラの能力例 :(※ 合計100) ちから: 10 たいりょく: 30 しゅびりょく: 10 すばやさ: 40 きようさ: 10 さて、別の作成キャラ例を考えます。 ;平均型キャラA ちから: 20 たいりょく:20 しゅびりょく: 20 すばやさ: 20 きようさ: 20 :(※ 合計100) のように、能力値を平均にふりわけたキャラクターと 合計値は同じですが、特定のパラメータに特化して能力値を振り分けした ;特化型キャラB ちから: 40 たいりょく:20 しゅびりょく: 30 すばやさ: 5 きようさ: 5 :(※ 合計100) のようなキャラクターを、 コンピュータ上でRPGの戦闘システムのアルゴリズム上で対戦させた場合、 ほとんどの20世紀のRPGのアルゴリズムでは、特化型のキャラBのほうが勝ち、つまり特化型のほうが強くなってしまいます。 さらに言うと、たいてい「攻撃力」のような、敵にダメージを与える意味のパラメーターに振り割ったほうが、キャラクターが強くなるゲームのほうが多いです。(ファミコン時代から、ウィザードリィ1の攻略本でそういわれていました。敵モンスター『ワイバーン』あたりの攻略法として「攻撃は最大の防御」という格言を出しています。表紙の黒かった攻略本なので、たぶんゲームアーツの本。『ウィザードリィ攻略の手引き』(MIA BOOKS)かと思われます。) なぜこうなるかと言うと、なぜなら、もし攻撃力が上がると、敵を倒すのに要するターン数も減少するので、結果的に敵を倒すまでに自キャラの受けるダメージ量も減るからです。(なお、現実の軍事学でも、似たような事が言われており、戦術論ですが、クラウゼヴィッツ(近代ドイツの軍事学者の一人)は防御重視の作戦よりも攻撃重視の作戦のほうが有利だと述べています。防御だけで攻撃しなければ、現実でもゲ-ムでも戦闘では絶対に勝てません。) 裏を返せば、平均型能力のキャラは、多くのゲームシステムでは弱くなりがちです。 パラメータの振り分けは自由ではないですが、ドラクエ2(ファミコン版)でいう、サマルトリア王子が弱くなる現象です。ファイナルファンタジー3・5の赤魔導師も、似たような弱点を抱えています。 理由はいろいろとありますが、バランス側の弱くなりやすい理由のひとつとして、参考文献などは特には無いですが、 :・ウィザードリィやドラクエなどの古いRPGのアルゴリズムが、特化型に有利になっているという歴史的な経緯。 :・命中率などの確率に関わるパラメータ(「器用さ」)のある場合、パラメータ割り振り前から既にある程度の底上げ補正がされている場合が多いので、わざわざ命中率を上げると割り損になる。 :・「すばやさ」(素早さ)が攻撃の順番にしか影響しない場合、素早さが低くても1ターンに1度は攻撃できるので、素早さを上げると損。 などの理由があるでしょうか。 命中率に関しては、多くのRPGで、攻撃が外れるのは、プレイヤーに不満感を与えるので、たいていのゲームでは、ゲーム序盤のレベル1のキャラであっても、数値上での「命中率」や「器用さ」などの表向きの命中率が低くても、たとえば「命中率 40」と表示されていても、実際のゲーム内部での命中率はたとえば+20%されてて本当の命中率が60%だったりするような場合もあります。 このような底上げ命中率のあるシステムだと、20%底上げされる場合、命中率を80%以上に育てるのは損です。なぜなら100%以上には上がりようが無いからです。 命中率が101%以上の場合に特殊な追加スキルなどを獲得できるなら別ですが(たとえば、クリティカルヒットの確率がけっこう増えるとか)、たいていの古いゲームでは、そこまでの手入れをしていません。おそらく調整に時間が掛かるからでしょう。 === ダメージ計算式 === さて、RPGの戦闘におけるダメージの計算式(「ダメージ計算式」といいます)に、アルテリオス計算式というのがあります。これは、昔のゲーム『アルテリオス』で採用された計算式なのですが、 攻撃側の攻撃力 - 守備側の守備力 = 守備側のダメージ という計算式です。 ドラクエやファイナルファンタジーのシリーズの計算式はもっと複雑なのですが、どのRPGでもダメージ計算式の基本的な設計思想・方針はアルテリオス計算式と同じです。 アルテリオス以外のダメージ計算式でも、たとえば :1.3×攻撃側の攻撃力 - 0.75 × 守備側の守備力 = 守備側のダメージ というような感じの計算式である作品も多いです。 せいぜい、変数の前に定数係数が掛かっている程度です。 なぜ、どの会社のRPGでも、この程度の中学校レベルの単純な計算式なのかというと、バランス調整が簡単だからです。 バランス調整するのは人間なので、もし、ダメージ計算式があまりに複雑な方程式であると(たとえば量子物理のシュレーディンガー方程式みたいなのだったりすると)、そもそもバランス調整担当の社員が理解できません。 そして、このアルテリオス式を見ると分かるのですが、 :攻撃側の攻撃力 - 守備側の守備力 = 守備側のダメージ もし自軍の攻撃力が0の場合、敵にダメージを与えられないので(ダメージが0)、絶対に負けてしまいます。つまり、攻撃力が敵の守備力を下回る場合も、絶対に負けるのです。 一方、「すばやさ」パラメータが戦闘の先攻/後攻の順番にしか影響しない場合、素早さが0であっても、勝つことは可能です。 また、守備力が0であっても、勝つことは可能です。 このように、パラメータの種類ごとに、そのゲームにおいて重視・軽視の差があり、不公平になっている事が多いのです。 また、バランス型の能力値のキャラクターの場合、せっかく「ちから」を上げて攻撃力を上げても、守備側の守備力を下回っていると、ダメージ0になってしまい、絶対に負けます。 つまり、 自分の攻撃力 > 敵の守備力 でないと、アルテリオス式では必ず負けるのです。 一方、 :1.3×攻撃側の攻撃力 - 0.75 × 守備側の守備力 = 守備側のダメージ のように係数を掛けた計算式の場合、 守備力を1ポイント増やしても、その効果は25%減少されます。(たとえばレベルアップの際に上昇パラメータを一種類選べるシステムの場合、守備力を選ぶと損になる場合が多い。) いっぽう、攻撃力を1ポイント増やすと、効果は30%増しです。 このように、計算式によって、有利/不利なパラメータという格差が生じます。 === DPS (Damage Per Second) の概念 === :※ 出典は無いが、あまりに有名な概念なので、さすがに消さない。 最近のRPGゲームには攻撃コマンド選択時に「二段斬り」などのスキル選択ができます。 スキルを設計するとき、昔の初心者のやりがちなミスとして、最近は減ってきましたが、スキルの結果の見かけの数値にゴマかされて、実はスキルが強くなってない特技を設計してしまうミスが時々ありました。 たとえば典型的なのは特技『ためる』です。これは、次回ターン時のダメージを数倍に倍増し、次回ターンの1回だけ、ダメージを倍増させる特技です。 この『ためる』は必ず、次回ターン時のダメージが2倍を超えないと(たとえば2.5倍にならないと)、無意味です。 なぜなら、『ためる』コマンドを選択したターンは、攻撃をしてないからです。 つまり、スキルを使わずに普通に2ターン通常攻撃した場合、ダメージ量は単純計算で :1+1=2 より、2ターンぶんのダメージです。 いっぽう、『ためる』コマンドを使えば、それがもし2倍しかダメージが倍増しない場合、 :0+2=2 で、結果は同じ通常攻撃2発ぶんのダメージのままです。 計算すれば子供でも分かる理屈ですが、しかしファミコン時代には市販の商業ゲームですら、こういうミスがありました。たとえばファイナルファンタジー3の職業『空手家』のスキル『ためる』です。 このようなミスを犯さないために必要な概念としては、'''DPS''' ('''D'''amage '''P'''er '''S'''econd) の概念が便利でしょう。DPS とは1秒あたりのダメージ量、という意味です。 もともと欧米のアクションゲームについての理論研究に由来する用語なので、単位が 秒 (second)になっていますが、RPGに応用する場合には単位をターンに変えるなどして工夫しましょう。 このDPSの概念を使って、上述の『ためる』コマンドの設計ミスを説明すれば、つまり、1ターンあたりのダメージ量(DPS)が上昇していないのが問題点です。 では、私たちが改善策を考えましょう。数学的に考えれば中学レベルで充分で、 : 0 + x > 2 を満たす変数xを設計するだけの問題です。 なので、たとえば、『ためる』後の攻撃ダメージ量を「2.5倍」とか「3倍」とかの数値に設計すればいいのです。 では、次に応用問題を考えましょう。 「『ためる』を2回続けると、さらにダメージ量がアップ」などのシステムを導入するときも、必ずDPSが増えるようにしましょう。 たとえば、この場合、ダメージを与えるのに最低3ターンが必要なので、不等式を考えれば、 変数xについての :0 + 0 + x > 3 を満たさないといけません。 つまり、『ためる』2回後のダメージ量は、最低でも「3.5倍」のように3を超える数値、あるいは整数に限定すれば、たとえば「4倍」とか「5倍」とかになっている必要があります。 == KPI == Key Performance Indicator という経営的な指標があり、『レベルデザイン徹底指南書』P140 および 『ゲームプランとデザインの教科書』P70 によると、共通しているのは後述の内容です。なお、『ゲームプランとデザインの教科書』P67 によると、オンラインゲームの運営などで使われる用語ですが、別にゲーム業界限定の用語ではありません。 ;DAU(Daily Active User) :デイリー・アクティブ・ユーザー DAUとは、その日に遊んでくれたユーザーの人数です。 ;MAU(Mathly Active User) :マンスリー・アクティブ・ユーザー MAUとは、その月に遊んでくれたユーザーの人数です。 ;WAU(Weekly Active User) :ウィークリー・アクティブ・ユーザー WAUとは、その週に遊んでくれたユーザーの人数です。 ;PU(Paying User) :ペイング・ユーザー 課金ユーザーの人数のことです。その日を課金ユーザー人数をDPU、その月の課金ユーザー人数をMPUと言います<ref>『レベルデザイン徹底指南書』、P140</ref>。 ;課金率 たとえば、ある月のユーザ数のうちの課金ユーザーの割合など、 一定期間中の課金ユーザーの割合を言ったりしますす<ref>『レベルデザイン徹底指南書』、P140</ref>。 あるいは、全ユーザーのうちの課金ユーザーのことだったりしますす<ref>『ゲームプランとデザインの教科書』、P70</ref>。(書籍によって、内容が微妙に違う) ;継続率 前月と比べて今月はどんだけユーザーが残っているかとか、あるいは前週と比べて今週はどんだけユーザーが残っているかのことを、 継続率といいます。 (以上) このほかにも、色々な指標があります。 == 参考文献・脚注など == a2qi0pwlm0o73mhos5ew3iy9mgbz6ew 206660 206659 2022-08-16T20:06:05Z Honooo 14373 /* 異業種? いやいや、それどころか、異人、異世界の事も想像しろ><!!! */ wikitext text/x-wiki {{substub}} 現在の版の著者達は、ゲーム戦闘の調整の経験はないので、現状では本ページの内容は調べ物としては役立ちません。経験があり、かつ人間性も良好な人の協力をお待ちしています。 ==本ページの目的== 本科目『ゲームプログラミング』は、科目名に「プログラミング」とあるとおり、ゲームクリエイターのための教材ではなくプログラマーのための教材です。 従って、話題がプログラミング的な技術的な話題に片寄っています。一般のゲームクリエイターを目指す人には、本書のバランス調整の記述は到底、役立ちません。 プログラマーが、とりあえず何か趣味でゲームを作る際、バランス調整についての調べ物の手間を少なくするためだけの目的の教科書です。 ……と、前編集者Suj. は書いたんだけど、その割にはこの人物の私欲を満たすためだけの駄文が結構くどくど書かれてる気がするんだけど… 気のせいか?まあまだちゃんと読んでないしね、熱でもあるのカナ? コロナか^^? ==バランス調整== ゲームには難易度というものがあるが、そのゲームの面白さのため、あるいは商品としての購買力アップのため、調整し、最適値を見出す必要があるだろう。敵の強さや主人公の強さ、それらを調整し、最適値を見出すための調査、テストプレイなどが必要だ。 より普遍的に、バグ修正、操作性の改善、仕様実装の更新、そして今書いたバランス調整、ゲームを面白く、評価を高めるための様々な改善を、一般にチューニングと呼んでいる。 英語では、難易度の調整のことを「レベルデザイン」と言う。このレベルとは、高低差の意味で、欧米での昔の3Dゲームにおける、マップの高低差を意図しているらしい。このレベルを調整するツールをレベルエディタというが、このマップの高低差の調整で難易度が変わるので、しだいにレベルデザインが難易度の調整の意味になっていったという<ref>川上大典ほか著『ゲームプランとデザインの教科書』、秀和システム、2018年11月1日第1版第1刷、P.57</ref>。 難易度デザイン、という言葉も使われている<ref>川上大典 ほか著『ゲームプランとデザインの教科書』、秀和システム、2018年11月1日 第1版 第1刷、P.58</ref>。 そして、難易度の調整にはマップの処理もあるので、3Dゲームのレベルデザイン担当者は、MAYAなどの3Dグラフィックツールの技能を持っているスタッフが多いという<ref>吉冨賢介『ゲームプランナー入門』、P234</ref>。 ===詰み、を避けたい=== 製品として販売するゲーム、そしてそうでなくとも、プレイヤーがセーブした時点でクリア不能な状況、仕様になっている、つまり、プログラムの流れとして事実上そうなっている、これを「詰み」、と呼んでいますが、それは避ける必要がある。 これはプログラムの構造の問題ですが、ゲームは進行の仕様自体かなりの複雑さを持っていますから、制作者が気付かないうちにプレイヤーがそこに追い込まれる可能性があり、これは娯楽であるゲームとしては避けたい事態です<ref name="twogc78">蛭田健司『ゲームクリエイターの仕事 イマドキのゲーム制作現場を大解剖』、翔泳社、2016年4月14日初版第1刷発行、P78</ref>。 まず、ゲーム全体のバランスとして、平均的なプレイヤーなら、妥当な労力でクリアできる調整も必要でしょう。 ゲームプレイで詰みに追い込まれるのは、プログラムの構造の悪さでもありますが、それを見つけ出すためには、具体的にテストプレイにおいて、少なくとも誰か一人のテストプレイヤーが、そのゲーム内で想定できるクリア困難な状況から、実際に挽回してクリアしたという、事実、実績が必要です。 つまりコンピュータープログラムで常にセキュリティの問題が発生するのと同様に、ゲームプログラムでは構造が複雑になりすぎて、詰みがプログラマーの想定を超えて発生する可能性があるので、実際のプレイで、実際のプレイヤーの現実の巻き返しで確認して調整したい、という事ですね<ref name="twogc78" />。 そして一方難易度調整として、平均的プレイヤーが平均的な労力でクリアできるようにしておきたい。 ちなみに現編集者の昔のゲームプレイ経験ですが、初代ファミコン版のファイナルファンタジーですね、番号は幾つだったか……市販の攻略本を読みながらプレイしていたのですが、あるところまでいった時点で、攻略本を読んでも、どう考えても先に進めない状況に陥り、まあ私のプレイヤーとしての技量にも問題あったのかもしれませんが、結局にっちもさっちもいかなくなって、プレイを放棄してクリアしないまま積みゲーになってしまったことがあります。もちろんそれでそのゲームの仕様が悪かったと主張するつもりはありませんが、プレイヤーの私としてはその時点で完全に詰んでしまったわけです。 ===実はゲームプレイヤーだけではなく、あらゆる人間が面倒くさい、俺も、あんたもね^^=== ……しかしあんまり面倒くさがると、結局最後には偉い人に怒られてしまうのがこの社会の常です^^;;;。 一般にゲームプレイヤーがプレイ中に面倒くさがることは、覚えること、計算すること、配ること、だと言われています<ref>『ゲームプランとデザインの教科書』,P342</ref>。 ゲーム中に、Wolfram|Alpha が使えるような仕様にすると、案外よかったりしてね^^ ===ゲーム制作者はいろいろ考えて作っているだろうけど、プレイヤーだってそれに負けずに考えてプレイしている=== プレーヤーも制作者も、時代の流れとともに、色々な変遷はありますよね。 時々指摘されるようですが、昔よりの最近の方が、ゲームの難しさに関する感受性が大きくて、割と簡単にこのゲームは難しいと指摘されることが多い、と、言われている。 たとえば携帯ゲームにおいて、平均的なゲームプレイヤーがクリアまでに5回ゲームオーバーになるように調整されたゲームは、今では「難しい」ゲームと判断される<ref>『ゲームプランナーの新しい教科書』、P210</ref>。つまり昔のプレイヤーの方が我慢強かったってこと?? 一方平均的なプレイヤーならゲームオーバーにならない難易度のゲームは、やさしいゲームと呼ばれることが多い。 だからもはやゲームの難しい易しいという言葉さえ、相対的で、結構人によって判断が違う。 2011~2013年頃のテレビ番組で、ゲーム業界を取材した番組、夜中の番組で、こういうものがあったという。 「昔の子供は、難しいゲームをプレイしたとき、「このゲームは難しい」と答えていたが、今の子供は「このゲームはつまらない」 と答える」 しかし実はテレビというのはこの社会で一番いい加減なメディアで、常に制作者に都合のいい印象操作、不当なイメージ操作が行われている。 つまり昔の子供より今の子供の方が愚かだというイメージを作りたいだけで、インチキな企業のためのいんちきな広告としての意味以外何も持たないだろう。 ===商業だろうとそうでなかろうとゲーム制作はプレイヤーの事を考える、難易度はどうする?=== 『ナナのリテラシー』という漫画、作者はゲーム好きで、ゲーム雑誌でも描いていたことがあるようです。ビジネス系しかもノウハウ系かな?2巻がゲーム会社回。 ゲーム会社の隅の老人経営者曰く(この漫画内の話ですよ)、「誰もが飛び越せる絶妙な難易度の壁をクリアさせる」、これがゲーム作りのコツじゃ^^!!! この漫画、前編集者が書くにはかなり、そこそこ取材されているという。 「PS」(プレステ)のロードは、「1回のロードで2WMが限界。どんなマップも2メガに入れなくちゃいけない。会話も音楽も全部ね。」なんて描写があるらしい。 この老人の主張は作品自体の主張でも作者の主張でもないというが、しかし前編集者は重要な事だと考えているようだ。 しかし誰もが飛び越せる絶妙な壁をクリアさせて、消費者に快楽を与えて、ガッポガッポも儲けるにしても、人間には個性があり、性格や性質にもばらつきがある。 全ての人に等しく、偉そうに試練を与えて、それを乗り越えたから気持ちいい、と自己満足に等しく浸らせることは難しい。 だから、インチキにガッポがっぽ儲けるためには(←しつこい^^;;;)、ターゲット層をある程度はしぼりこむ必要がある<ref>『ゲームプランとデザインの教科書』、P.97 </ref>。 「遊んだプレイヤー全員が満足するものを、目指さない」との記述がある書籍もある<ref>塩川洋介『ゲームデザイン プロフェッショナル』、技術評論社、2020年10月3日 第1刷発行、P.173</ref>。ただこれはテストプレイヤーの意見を重視しすぎて振り回されないように、という意図がある記述だという。 ターゲット層を絞りこむには、実在の人物をイメージするのが良いと言う。「20代社会人男性が」、ではなく、自分の知人・友人・家族、あの人を面白がらせたい!!、と、いうのがいいようだ<ref>『ゲームデザイン プロフェッショナル』、P205</ref>。 {{コラム|カラケオは気持ちよく歌いたい^^| 80年代~90年代にカラオケが流行した。と、いっても今でも、盛んだけどね。俺も好き^^ カラオケの難易度は、利用者が楽しめるように易しめに作られているようですね。というか前の項目で書いた、絶妙な難易度らしいよ。そこそこ難しく、それを乗り越えると俺は偉いと自己満足にふけれるらしい。岡田斗司夫が90年代後半にその指摘をしていたというが、しかし本当に前編集者は岡田斗司夫が好きなのね^^;;;。 小室哲哉の曲が典型的にそれだという人もいるらしい。そういえば、NHKアニメーション「だぁ!だぁ!だぁ!」のエンディングは凄く良かったな^^。いや、もちろんこれは只の雑談ですが^^;;;。 エヴァンゲリオンの残酷な天使のテーゼは、監督やスポンサーのレコード会社プロデューサーが、子供でも歌いやすいように作曲してくれと作曲家に依頼している。 確かに凝った楽曲の割に、カラオケで歌いやすい^^ }} {{コラム|作者の意図通りに視聴者が受け取るとは限らない。作者の意図とは全く別に受け手は作品を楽しむ。それが嫌ならそもそも創作するなよ。| 商業作品であるなら、最終的には売上によって作品の是非が決まる、なんて前編集者は書いてるけど、インチキ書くなよ、あくまでも金は商売としての是非、作品としての価値、意義は別の話だよ。 しかしこいつほんとにアフリマンなのね。金と物質以外何も見えないのか。 ゲームの話題としては、味の善し悪しはプレイヤーが決める、という言葉があるようですね<ref>『ゲームデザイン プロフェッショナル』、P.167</ref>。ターゲット層が、美味い^^!!、と、いう作品を作りたい。 ジブリアニメの『となりのトトロ』は、子供たちにアニメばかり見ずに外で遊ぶように啓蒙するようなストーリーを作者・監督の宮崎駿は目指したと言われています。 ところでこれ↑前編集者の文章だけど、完全なる虚偽だよ、いいかがんにしろ。あのねー、宮崎さんという人は確かに少し偏屈な大人だから、その手の事は時々言うけど、映画を作る時は基本的に、見た人に楽しんでほしい、夢のような時間を過ごしてほしい、そしてこの社会に生まれてよかったと、子供も大人も思ってほしい、そういう思いで、常にそれが第一テーマで漫画映画を作ってるの。 すじ肉先輩さー、あんた俺や他の編集者を何度も知ったかぶりって書いたけど、結局あんたが人類史上、唯一最大の知ったかぶりだね。そもそもあんた、トトロ、観てないんじゃないの? ほんとにあんたってなにも見えてないのね。「うちの子は、よく宮崎先生のアニメを見ています。面白いアニメを作ってくださり有難うございます」なんて感想は全く問題ないだろ。宮崎氏だってありがたく受け取ってるよ。それに対してアニメばかり観ずに外で遊べ!!なんて言うのはお前とお前の同類のキチガイだけだ。 あとガンダムやエヴァンゲリオンでも似たような逸話があるとのことだが、こっちはどうでもいい。そもそもこれを作っている連中は、宮崎氏ほど切迫した気持ちで作っているわけではなく、ただ金が欲しくて自分が偉いと思いたいだけだから、作った方がどう思おうが、そいつらに金を与えて養ってる連中がどう思おうが、大したことじゃあないだろ? }} ===チュートリアル=== ゲームをプレイするための、操作方法をプレイヤーが知って覚えるための入門的なイベントをチュートリアルというようですね。実は現編集者はあまり、特に最近はほとんどコンピューターゲームはしないので、ここの執筆をしつつもゲームについてはあまり知らない。 ただここの主要執筆者で、ゲーム大好き、プログラム大好き、アニメ大好き、自分自身も一応絵描き、そしてハイルオタキングの E.Suj. かなりひどい内容の文章を大量に書き散らすので、このサイトの参加者として嫌々多少書き直しをせざるを得ない。 そこでチュートリアル、これはふつうゲーム自体に組み込まれ、初盤がそれになりますが、これは別モードにすると良いという指摘がある<ref>『ゲームプランとデザインの教科書』、P401</ref>。 『不思議のダンジョン2 風来のシレン』が、このスタイルを採用している。 とはいえプレイヤーが必ずチュートリアルをプレイしなければ、ゲームを楽しめない構成なら、あまり大きな意味があるとも思えないが、しかしそうでない場合も多いだろう。 ゲーム構成の選択手として考えてもいいだろう。 ===技能の習得としてのゲーム=== ====ゲームをプレイしていることで、プレイヤーは何を知って、何を身につけているか?==== まあゲームをしていることで、プレイヤーは何らかの行為、練習を繰り返して、技能様の物を身につけていく、と、考えても、いい? まあいいか、とりあえずはそう見なしましょう。 ですからそこでプレイヤーが身に着ける技能を想定しておくと、上手にバランス調整が出来るという。 すじにく大先生が愛読している文献では、「教育的難易度」という用語を使っています<ref>吉沢秀雄『ゲームプランナー入門講座』SBクリエイティブ、2015年12月29日 初版第1刷発行、225ページ</ref>。まあゲーム関係者で教育について分かってる奴なんて、ほとんどいないだろうけど… ここでの教育難易度とは、むしろ大先生の意図とは逆で、ある敵を攻略するのにプレイヤーがなんらかの操作が必要な時、まず1個だけのその敵の撃破用の操作技能だけをプレイヤーが修得できれば攻略できるようにしろと、つまり、プレイヤーが技能を覚えやすいように、難易度を下げろという事でしょう。 前編集者は本質的キチガイなので、とにかく世の中で自分が偉いことが何より大事なので「教育」という言葉を使いたい。一方で割と似たようなことを語る時に、学習という言葉を使っている文献もある<ref>『ゲームプランとデザインの教科書』、P.61 </ref>。要するにこの本の筆者の方が、E.Suj. よりまともな人間だという事でしょう。 ただ、プレイヤーの技能の習得という視点は、バランス調整の時に一番重要になるという。確かにゲームは技能や知恵、解決のための何らかの手段、鍛錬も必要だが、一方では間違いなく娯楽で、面白いものであるはずだ。 そしてゲームをすることで、自分の思考力が磨かれて、成長したという感慨を持つプレイヤーも多いようで<ref>https://www.teu.ac.jp/ap_page/koukai/2019_03_3endo.pdf 66ページ</ref>、全くその気持ちを否定する意図はないが、でもねー、ゲームっていうのは結局遊びなんだよ? ゲーミフィケーションなんて言葉を使っていい気になっている連中もいるようだけど、まあその概念や運動がまったく意味を持たないとは言わないが、でもやっぱりゲームは娯楽であり遊びであり、ある程度堕落した、ある程度常識的な硬い世界からは非難される要素があるもので、あまり理屈を並べて自分たちの世界が高級なものだと主張しない方がいいんじゃあない? {{コラム|ゲーミフィケーション| どうもゲーム業界の連中が、自分たちの仕事を美化して、正当化したいため、ゲーミフィケーションがどうの、なんて言いだしたようだよ<ref>https://news.denfaminicogamer.jp/kikakuthetower/190731a</ref>。 2019年にゲーミフィケーション学会設立。もっともこの運動や概念がまったく意味がないものだとは、現編集者も言わない。確かにゲーム的な行為を、もう少し遊びから離れて、現実の有用な出来事に結び付けようというのは、それほど間違っていないし、意義はある。 2013年ごろからすでに、企業の新人研修で、ゲームの要素を取り入れた研修などがされていたようだ。 岸本好弘(ファミスタの父、と呼ばれているらしい)の言では、「ゲームの本質っていうのは、人間が頭で想像することの素晴らしさ」<ref>https://www.fantasy.co.jp/edutainment/article/interview16</ref>ってことらしいけど、なんか軽い言葉だね。想像には意義があるが、それってほんとに頭でするもの? 40年前(※1980頃?)、 :「そのころアーケードゲームのデザインで言われていたのは、初めてそのゲームに挑戦したプレイヤーでも3分間程度は遊べるようにすること。「もう一度チャレンジしたら、先に進めそうだ!」と、プレイヤーの気持ちが動くように制作すること」 ってことだけど、そうすれば子供が100円玉いっぱい入れて、お前らが儲かるってだけだろ? :「これって、現在IT業界で言われるUX、ユーザーエクスペリエンスですよね。ゲーム業界では理論化、言語化していなかったけれど、40年前から現代に通じることをやっていたんだなと思いました。」 何かそれらしい言葉だけ踊ってかっこつけてるようにしか聞こえん^^;;;。 :「ゲームって全部「そそのかし」なんです。ゲームをプレイしていて、Aの洞窟に行きなさいとか、Bの洞窟には行くなとは言われないですよね。プレイヤーが2つの洞窟をぱっと見たときに「こっちの洞窟に宝があるかも!」って見えるように作っているんです。これを「そそのかし」って言うんです。」 まあそれはそれでいいけど、それってそんなに大したことかね? : (抜粋)「先生は答えを教えるのではなく、生徒が自分で「わかった!」、「僕が一人で気が付いた!」と思わせることが大切。」 思わせるっていうのがすごいし、傲慢だよな。お前は神か? : 「ゲームをデザインするのも授業をデザインするのも同じです。楽しいと思うことやワクワクすることは脳の働きを最大限にする。だから、つらいことを我慢するのはよくない。脳が楽しいと感じることがとても大切なんです。」 お前みたいな奴って、すぐ脳がどうのって言うよな。まあ楽しいことやワクワクするのが大事なのは認めるが、人生つらいことを我慢しなければいけない時なんてしょっちゅうだよ。後ゲームと授業は別物にしろ、一緒にするな。 しかし思うんだけど、ゲーム業界の奴らって、自分たちの仕事に少しやましさがあるから、教育と結び付けて、高級なものに仕立て上げたいんじゃあないの? まあゲーム的な教育っていうのはありだが、やはりゲームの本質は遊びで娯楽で、しかも堕落だよ。 }} {{コラム|すじ肉しちゅ~は今日も右手を上げて、「ハイル、オタキング!!!」と言った。| 1990年代後半に、オタキング岡田斗司夫は、著書『世紀の大怪獣!!オカダ―岡田斗司夫のお蔵出し 』(おそらく)で、マリオカートを例に、市販のゲームソフトの多くは達成感を味合わせるものだと指摘した。 岡田に言わせれば、ゲーム文化以前の人生の趣味の多くは、必ずしも努力の量と、上達とが比例しない。スポーツ、絵画、しかしこれほんと?もちろん厳密に量を考えて、グダグダ気色悪い比較をすれば、そう見えることはあるけど、少なくとも人間、何かをすれば必ず、それなりに得るものがあるはずなんだけどね。 しかしファミコン以降のコンピュータ式のゲームでは努力は無駄にならず、ほぼ必ずといっていいくらい、少なくとも初心者レベルの範囲でなら、プレイして練習すれば上達するように設計されていると、岡田の著書では述べられている。 ふーん、要するにゲームプレイヤーって、ゲーム制作者が作った達成感が欲しいから、金払うってわけね。 岡田が言うには、人生はゲームみたいに甘くないし、もしかしたらゲームは現実逃避で不健全かもしれないけど、でも大人だって親だって達成感をもっと感じたいんだぜ・・・だから今日も娘といっしょにマリオカートをプレイしている、と書いてたって言うけど、そもそも現実逃避や不健全から達成感って手に入る? なんか頭のおかしい奴はやたら達成感って言うんだけど、それってほんとに欲しい? いや、もちろんある程度は欲しいけど、でもそんな重要な事かね? もっと人生で必要なもの、いっぱいないかね? }} {{コラム|ガイナックスとはオタキング岡田斗司夫が創業した、アニメーションとコンピューターゲームの制作会社である。| ガイナックスは、コンピューターゲームも作っていたね。確か、美少女18禁ソフトもあったよね。 1991年、『プリンセスメーカー』、育成シミュレーションゲーム。確かに赤井孝美さんのグラフィックは魅力的だった。 少女を光源氏的に育成するゲームだったか、キャラクター育成ゲームのはしりだね<ref>STUDIO SHIN『ゲームプランナーの新しい教科書』、翔泳社、2018年3月10日 初版 第2刷 発行、P182</ref>。 98年にはコナミ社『ときめきメモリアル』というのが出た。ただこれは育成というよりは、美少女との恋愛疑似体験ゲームみたいな、まあ俺はやったことないから詳細は知らないけど、まあ美少女と上手に付き合えるように、男性キャラクターを育成する要素はあったのかね。 「プリンセスメーカー」→「同級生」→「ときメモ」の流れがあるって、ある評論家は言う。 良くわからないけど、岡田斗司夫はゲーム制作会社の社長でもあるんだから、前のコラムの達成感がどうののたわごとに意義を認めろって、すじ肉は書くんだけど、なんなのこいつ。 岡田斗司夫の肩書に関する議論って意味ある? 別にアニメ評論家でも、会社社長でも、なんでも勝手に名乗って威張っていればいいけど、でもやっぱり岡田斗司夫の肩書は、オタキングだよね。 }} {{コラム|プリンセスメーカーdeathpenalty| 少女育成ゲーム・プリンセスメーカーは全滅時の損失が軽いのが、割と画期的だったようです。戦闘で全滅すると、拠点に戻されたうえ、1か月経過する。 全滅時の損失のことを和製英語でデス ペナルティといいます。英語では dead damage と云うらしい(DDと略すようです)。英語の death penalty は「死刑」の意味だって。 つまりどうやら、デスペナルティが軽くても、面白いはRPG は作れるらしい。 ;デスルーラ 全滅しても拠点に戻るだけのシステムだと、拠点に戻りたい場合にわざと全滅する方法を使える。これを和製英語で「デスルーラ」と言う。ルーラとはドラクエの移動魔法ルーラのこと。 全滅したときに拠点に戻るゲームでは、拠点に戻れなくするイベントは不可能。 全滅したら拠点に戻れるからね。ただ、戦いが起こらなければどうかな? どちらにしろこの議論、意味ある? ただ例外的に全滅したとき拠点以外に戻る、っていう事は仕様で作れるよね。 }} {{コラム|Roblox,Among_Us| 現編集者は現在は基本的に、コンピューターゲームはしない生活、でもほんのちょっと前、思うところあって、MicrosoftStore,Xbox 経由で、すこしゲームをしていた時期があった。 そしてMicrosoftStore はなんだかんだでゲームを売り込んでくるよね。 その時思ったんだけど、Roblox って面白そうだよねー。プレイはしていないんだけど、広告や表示を見ると、これ絶対面白いなって直感的に思う。 だからこのゲームのユーザーやプレイヤー、あるいは関係者にこのページの執筆してほしいな^^ 後、Among_Us っていうのも面白そう。何か皮肉がすごく効いてそうだね。 }} {{コラム|デスペナルティ関連| このコラム、前編集者が、(この話題は、後述の商学書『メイド・イン・ジャパンは負けるのか』の話題と関連するので、残す必要がある。)ってメモを張っていたんだけど、読んでみたんだけど、現編集者Hにはちょっと話が見えなくてね。おそらくRPG をやりこんでいる人は内容が良くわかるんだろうけど、現編集者にとってはかなりの部分が???????だね。だからできるだけまとめる一方で、詳細不明の部分は前編集者の記述をそのまま残しました。 ;帰り道を通せんぼするイベントは、詰みのリスクが高くなる。 サガシリーズはどこでもセーブできるが、この場合、帰り道を通せんぼするイベントは、上手に設計しないとクリア不能になる恐れがある。 ファミコン~スーファミ時代のドラクエとファイナルファンタジー、GB版サガとロマサガには帰り道を通せんぼするイベントは無いように見える。 ロマサガ1の氷結城の帰り道で通せんぼするボス敵がいる。しかし会話選択肢で戦闘を回避すると、詰みを避けられる。 古い時代のサガ系とロマサガでは、ダンジョン奥まで探検すると、最深部に一方通行のダンジョン出口がある。これは帰り道短縮の意味と、テンポ感向上(プレイヤーが既に理解していることを再度要求しないから)の効果がある。 しかしこの場合、もしダンジョンに一方通行出口がない場合、プレイヤーは帰り道にボス戦があると予測する。これはネタバレになってよくない。ドラクエは、最後の一方通行出口をあまり用意しないが、この狙いがあるのだろう。 このようにゲームのルール設定が、可能なイベントやマップを限定する。 }} さて、ゲームのシリーズ物は、ルールが一様になる傾向がある。 だから、シリーズ作品によって搭載されるイベントの傾向も決まってくる。 イベントの傾向が限定されると、マンネリ化につながる恐れもある。 『メイド・イン・ジャパンは負けるのか』という2010年ごろの書籍でも、 シリーズ化とマンネリ化との相互関係が語られていて、基本的に家庭用ゲーム機の作品群の多くはゲーム性の根幹が90年代以降の作品は変わっておらず、変わったのはグラフィックが細かくなっただけ、と書かれている。 しかしゲーム会社からすれば、新規の斬新な発想のゲームはむしろ売れないと見られている。 グラフィック重視は、商業ゲームでは非常に重要と考えられているらしい。 そしてゲーム評論家は偉そうな批判はするが、自分では結局ゲームを作らない。 1980年代は、家庭用ゲーム黎明期。1995年ごろ、プレステ1時代からソフト容量が飛躍的に伸びた。 昔はゲームに勢いがあったが、今となっては、新しくて画期的かつリアリティと説得力のあるルールを思いつくこと自体、そんな簡単な事ではない。 漫画産業やアニメーション産業は黎明期をとっくに過ぎたようだが、結局今でもこの産業は続いている。そもそも、ラジオ、新聞、書籍、オールドメディアと呼んでいい産業も、今、しっかり続いている。2010年代のゲーム産業だって、もしかしたらスマホゲーム黎明期、ソーシャルゲーム黎明期なのかもしれない。 {{コラム|オタキングアノマリー論| オタキングによるアノマリー(片寄り)論(『東大オタク学講座』に記述あり)によると、ゲームのバランス調整は結局普遍性は持たず、作家の世界観が反映されるものになる、という。 都市運営シミュレーション『シムシティ』、アメリカ製のゲームですが、ここでは火力発電所よりも原子力発電所の方が効果的な投資になっている。これは現実の経済情勢を正しく反映しているか? これは現実の経済分析の話だが、現編集者はYESだと思っている。巨大なお金が動いているからこそ、いまだにこの国は原発をやめられない。 そして岡田はこの設定をアメリカ的な都市政策観の反映だとしている。しかし岡田はこのゲームの感覚を片寄りだと思っているのか? そのほか、岡田は、ドラクエシリーズに対して、「なぜ作者の堀井さんは、作中で父親と子の関係に、どの作品でも、こだわりたがるんだろう? なにかあったんじゃねえの?」的なゲスい勘繰りもしています。 ↑ちなみに上の段落は前編集者、E.Suj.の記述をそのまま残したものだが、まあね、オタキングがゲスい人間なのは、オタク全員が知っているからね^^;;;。 ここで書いたシムシティに関する議論と堀井氏に関する議論はどうも別の話のように見える。 つまり前編集者の議論は当初から混乱しているのだが、結局E.Suj. は作家の個性とは異常性の裏返しだと言いたいらしい。つまり個性とは長所ではなく、欠点の別形態だと。 では現編集者はこのE.Suj. に質問したいが、結局人間、個性持っていたほうがいいの?持っていない方がいいの? 大人は欠点すらうまく自分で活用しなければいけない、なんて書いてるけど、そんなこと上手く出来ている大人なんて、この地球上に一人もいないよ。 }} ====本文==== さて、上述までの再編集により、前編集者E.Suj, の邪念から生まれた、ゲーム-教育-成長のインチキ理論は完全に否定できたと思う。 結局前編集者もゲームにおける教育論は疑似的なものだと記述してるが、そんなら最初っからそんなこと書くな。 地獄のような長時間の再編集を終え、やっと話を本題のバランス調整にもどせることになった。 まずアクションゲームの調整。 敵が飛び道具で来るならどうする? もちろん事実上はほぼ無限の対応策があるが、例えば、物陰に隠れながら移動して近づく、あるいはこちらも飛び道具で応戦とか、幾つか具体策は見えるでしょう。 (しかしよく考えたら、この行動って、E.Suj.のこのサイトでの行動とそっくりだよね^^;;;。) 基本的にゲームバランス調整では、例えば、物陰に隠れて攻撃を避けるなどの具体的技法、そして事実上それはそのゲームでの有効策なのですが、プレイヤーがこの対応策を覚えるように導く、そしてそれを可能なものにするため難易度を下げる、これが必要だと言います<ref>吉沢秀雄『ゲームプランナー入門講座』SBクリエイティブ、2015年12月29日初版第1刷発行、226ページ</ref>。 一つの方針としては、必要だと思われる技能をプレイヤーが行っていると判断したら、しかも一度には基本的に一つ、その敵を簡単に倒せるようなプログラムにする。 とにかく特定の方向にプレーヤーを導く意図を持つ、つまり導きたい方向にプレイヤーが行為すれば、難易度が下がる。だから、飛び道具を避ける物陰には、罠も無ければ敵もいない<ref>吉沢秀雄『ゲームプランナー集中講座』SBクリエイティブ、2015年12月29日初版第1刷発行、226ページ</ref>。 あれっ、今気づいたんだけど、新約聖書には、狭き門から入れ、って言葉があったよね…。 基本的には前編集をわかり易く書き直してるだけなんだけど… とにかくこの場合、推奨されるパラメーター設定は、目的の敵を妥当な経過で主人公が攻撃したら、敵はすぐ倒せるようにしておけって書いてるんだけど、これって広き門じゃあない? とにかくこの前編集は、あらゆるプログラムを駆使して、プレイヤーが特定の行動をするよう導けって書いてある…。 まあしかしまとめ編集を続けるかね… 大抵のゲームは先に進むと難易度が上がっていくようだが、いや、これ自体事実かどうか怪しいが、仮にそうするとした場合、その難易度の上がった敵のギミックや行動は、制作者が導く行動を複数、と言ってもごく少数の複合だろうが、プレイヤーがなしたら、敵を倒せるようにしたら良いという。複合技をプレイヤーが繰り出すことで、成長した感や、興奮を、ユーザーは感じるだろう<ref>吉沢秀雄『ゲームプランナー集中講座』SBクリエイティブ、2015年12月29日 初版 第1刷発行、228ページ</ref>。 前編集者は、ゲームの後半難易度を上げるのは、プレイヤーに創意工夫を呼び起こすためと書いている。 確かに難易度が上がれば、創意工夫して解決を目指すのはゲームだけではない。しかし現編集者が問題を感じるのは、常にプログラムの手妻を駆使して、特定行動にユーザを導けと主張している点だ。 これは実はアメリカの過去の宇宙開発で宇宙に送る実験動物を調教、教育した方法と全く同じだ。 とにかくゲーム制作者の中に、このような馬鹿げた教育論を持っている愚か者はそこそこいそうだが。 このインチキな前編集者の愛読書には、ボス戦などの難しいイベントの目的は、プレイヤーが自分自身の技量を試す、自分がこのゲームにおける熟練プレイヤーか試す、そこにあるという。歯ごたえのある敵と戦って、自分がこのゲームにはまっているかどうか知る事が出来る、そういうことだろう<ref>吉冨賢介『ゲームプランナー入門』、P60</ref>。 ;やはり何事も制限はあるか? 例えば主人公が不死身なら、まあゲームになりませんよね。何らかの弱いところは必ずあるでしょう。 所持金が無限とか、無いですよね。お前はドラえもんのポケットか?^^;;; 敵もそこそこ強いよね、あんまり弱いのはちょっと。 (たとえばアクションゲームで一時停止ボタン(ポーズボタン)を押さずにトイレに行ってウンコを数分してきても、ウンコから戻ってきてもキャラが負けてないのは明らかに駄目)。 ↑ちなみにこれは前編集者の記述だけど、ん~、まあ、残しておくか^^;;;。 だから前編集者としては、プレイヤーに創意工夫を求める。まあもっともプレイヤーが創意工夫しないゲームなんて、この世にないけど。 だからゲームオーバーはやっぱり必要だということか<ref>川上大典 ほか著『ゲームプランとデザインの教科書』、秀和システム、2018年11月1日第1版第1刷、P.254</ref>。 だから前編集者はゲームには敗北とそれを回避するための努力が必要だと主張する。 まあでもこのサイトの別の場所でも書いたけど、E.Suj.は努力なんて全くしてないけどね。ただ毎日欲望のまま手を動かしてるだけ。 ;真実は一つ^^!!!本当?とりあえず解法は複数^^!!!! スーパーマリオのステージ1-1の最初のクリボーをどうする? (解1)踏んずけてやる^^!!!(解2)そのクリボーを飛び越えてこっちに来い!!!^^(解3)ブロックに乗って、絶景哉^^。 ====ゲームと漫画、アニメーション==== 非常におおざっぱに語ると、漫画やアニメーションは完成して世に出た時点で、その版では、定められた運命が記述されている、ヤーンの書のようなものでしょう。 ゲームはインタラクティブだから、運命は決まっていないし、あいまいで、事実上選択肢がある世界。 そしてゲーム=戦闘ではないが、戦闘を描いたゲーム、漫画、アニメーション、 というのは明らかにある、そしてその話なんですが… 1982年『鳥山明のヘタッピマンガ研究所』という書籍では、マンガやアニメや特撮(ウルトラマン)などの敵の強さは、主人公がなんとか苦戦しながら倒せるギリギリの強さだと指摘されている。ただしこの出典関係の記述にはWiki著書の記憶違いがあるかもしれない。 しかしゲームでの敵は、もうちょっと弱めにしておくといいらしい。 まあそりゃあそうだよね。毎回毎回ギリギリの敵と戦うなら、ゲームなんて誰もしなくなるよ。これに関して前編集者はプレイヤーの創意工夫がどうのなんて書いてるけど、完全なる欺瞞だろう。 具体作品を上げると、ゲーム『激神フリーザ』。要するにドラゴンボール原作のゲームですね。クリリンでもちょっと鍛えて頑張ればザーボン(ナメック星編の中ボス敵)を倒せるようになっている(原作マンガだとクリリンはザーボンを倒せない)。 漫画やアニメーションでは、一回の戦闘での強敵の倒しかたが一通りしかなく、いちばん読者に魅力的に見える奇想天外・破天荒な倒しかたで、敵を倒します。なのでここでは、ギリギリ倒せる強さのほうが良い。 しかしゲームの強敵では、多くのプレイヤーの、それぞれ異なる色々なアイデアに対応した倒し方を何通りも準備する必要があるので、ゲームでの強敵の強さは、ギリギリ倒せる状態よりも少し弱めにする必要がある。しかしやはりそれ以前に、あまり敵が強すぎたら、プレイヤーがしんどすぎるだろ、単に難易度が高いゲームになっちゃうよ。 ==== 「廃人」 ==== 基本的にコンピューターゲーム界隈は、いちびった下品な人間が多いので、そこで飛び交う言葉も汚い言葉が多い。 例えば、廃人、なんてよく言うらしいよ。つまりいろいろな理由で暇な人間、まあ、E,Suj. もそうだけど、普通に忙しい人間より、ネットゲームとかでは有利だよね。そういう人間を貶めたくて言うんだね。 後色々な理由でゲームに過度にお金を費やせる人に悪口言いたい時とかね。 まあはっきり言って、E.Suj. も間違いなくこの廃人の一人だけど、彼の愛読書では、「廃課金ユーザー」という記述にしているらしい<ref>『ゲームプランとデザインの教科書』、P66</ref>。「廃Wikiユーザー」とか? だけど世の中色々でね。人にはそれぞれ事情がある。望まなくても廃人になってしまう人はいっぱいいるよ。 ===ゲーム作者が自作をプレイしたら、やはり他者プレイヤーよりそのゲームは簡単だと見なすだろう。=== あらゆる分野で作者は自作は面白いし、難易度やネガティブな要素は低いと見るだろう。作り手は妥当なバランスをどう見出したら良いだろうか? ====作者が客観的に自作を見る事さえ難しい、しかしいいバランスは見つけ出したい==== やはり常識的な判断としても、経験則としても、作者がやや簡単だと思うくらいがちょうどいい、という事だろう<ref>STUDIO SHIN 著『ゲームプランナーの新しい教科書』、翔泳社、2018年3月10日 初版第2刷発行、54ページ</ref>。 プレイヤーにとっては易しいほうの案Aと難しいほうの案Bとがあったら、ゲーム本編には、やさしいほうの案Aを採用するのが良い<ref>吉沢秀雄『ゲームプランナー集中講座』SBクリエイティブ、2015年12月29日初版第1刷発行、P207および235ページ</ref>。 難しい方の案Bは、付加的なサブステージ(クリアには不要な)に流用するといいですかね<ref>吉沢秀雄『ゲームプランナー集中講座』SBクリエイティブ、2015年12月29日 初版第1刷発行、P207および235ページ</ref>。 RPGにおいてはクリアに絶対に必要なイベントと、エクストラのクリア条件ではないイベントがありますね。それぞれ「強制イベント」、「任意イベント」と、呼ぶこともあります<ref>STUDIO SHIN著『ゲームプランナーの新しい教科書』、P198</ref>。 サブステージや任意イベントの難易度は、割と自由に扱う事が出来そう。むしろ様々な難易度があった方が、多様なユーザーの要求に対応しているとも言えるし、しかしそもそもサブステージなどなくてもいいとも言えますが、あるとしたら、遊びは多くなりますよね<ref>吉沢秀雄『ゲームプランナー集中講座』SBクリエイティブ、2015年12月29日初版第1刷発行、P208</ref>。 そして基本的に作り手は「簡単」だと思っていても、初めてプレイするプレイヤーには難しい、それはよくあることですよね<ref>吉冨賢介『ゲームプランナー入門』、P56</ref>。 ====レベル上げを楽しむ?==== 一般的なゲームは、例えばRPGでは、ストーリーや戦術性の面白さが普遍的な主流の興味ですよね。作り手も、RPGというジャンルが今現在、どういう一般的な魅力があるか、それを考えて、それを重視して作る。 一方プレイヤーとしては、正道を外れたややマニアックな楽しみ方もある。RPGのレベル上げ(だけ)を楽しむ、なんて遊び方もできますよね。 つまりプレイヤーはプレイヤーで、本来の制作者が意図した別のところで楽しみを見出すこともある。ある意味コンピュータープログラムのインタラクティブな性質が、そういう遊び方を見出す余地を持っていると言える。 しかし制作者はやはり、RPGの持つ本道の面白さを目指してゲームを作るでしょう。 前編集者はこのことを、少年漫画を例に語っていますね。 漫画家スポコン漫画(そう?^^;;)「バクマン」では、こんなエピソードがあったようです。 「たとえ少女の読者がいても、その少女は、「男の子が読んでいるマンガを自分も読んでみたい」、と思うような女の子。少年ジャンプの取るべき編集姿勢としては、あくまで、男の子向けを貫かないといけない」 少年漫画誌は、ターゲットは、少年、割と年少の男の子ですからね。それ以外のファンがいても、その読者層におもねる漫画は載せないでしょう。それはカテゴリ崩壊だよね。 しかし実は少年にもいろいろな個性を持つ子がいる。少女にも、大人にも、老人にもいろいろな個性がある。ターゲットがどうのと言ったところで、実は結構あいまいでいい加減な物なんだよね。 少年ジャンプは自らの分析として、売れる漫画の方向性として、「友情・努力・勝利」の3原則を提唱した。この3原則を外すことは今現在は許されてはいないのでしょう。 ====No title.==== ある意味当然のことだが、ゲームの作者は、ほかのプレイヤーより、自身のゲームの難易度を低いと見るだろう。「作者バイアス」という言葉が使われることもある。 ;雑誌「ゲーム批評」による指摘 1990年代に「ゲーム批評」という雑誌が、ゲームの内容を考えるときは、ゲーム制作に熟練していない人は、既存ゲームを難しくアレンジした提案をしがちだと指摘しています。 例えば、スーパーファミコン版のマリオ、こういうゲームを自分たちが作る時、どういうゲームにしようか? マリオが空を飛んだ時、簡単にクリアできるけど、ここで空中に敵キャラクターを多く配置したらどうだろうか? そして『超音速攻撃ヘリ エアーウルフ』、、云々の記述が前編集にあったが、これはいつものこの前編集者の一般的な他者に対する愚弄目的の文章なので、再掲載する必要はないだろう。 そしてこのアイディアに対する、一般的な批判としては、マリオの地上ステージの空中に敵が少ないのは、ゲームが苦手なプレイヤーのための救済措置だったり、あるいは体験済みステージ前半を無視するための工夫、であるので、その部分を難しく、複雑にするのは不適切だと思われる、と、いうことになる。 ところでやや話題が脱線するが、過去少年マガジンに掲載されていた、漫画作品、[[w:1・2の三四郎]]にも、似たような話があった。 高校生の主人公、東 三四郎と、本当はレスリング部にしたい西上 馬之助と三四郎の友人南小路 虎吉の三人で柔道部の活動をしていたのだが、ある日三四郎が馬之助にこう言う。 「スタンハンセンのウエスタンラリアット(プロレスの技)の改良技を考えたのだが」 「ほう」 「ハンセンは、ラリアットを打撃技にしているが、ここで打撃しないで、首に引っかけるようにして倒して後頭部をマットに打ち付けるのはどうだろう?」 「あほ!!それはジャイアント馬場の、ランニング・ネックブリーカー・ドロップや。ハンセンはそれをもとにウエスタンラリアットを考えたの。なんでお前がわざわざそれをもとに戻してんのや」 ただ、今ではこのジャイアント馬場云々は俗説と言われているようですね。 少しマリオの話とは違うかもしれませんが、脱線の雑談として書いてみました^^ さて、今仮に、「ゲーム作者はネットの批評はあまり参考にしない。基本的にゲームを作ったことのない人の意見はあまり意味がないと考えている。」と、いう主張があったところで、あなたはこの意見をどう思いますか? まず全くの素の状態でこの言及を聴いたところで、その通りだと思います?あるいはいや、違うと思います?。 そしてもし素の状態ではなく、仮に出典とやらがあった場合、出典と言ってもいろいろありますよね。ネットの言及の場合もあるし、あるいは何らかの偉そうな市販の書籍にそう書いてあるかもしれない。 この辺の出典とかの情報、事実で意見変わります? だからあなたが素の状態でどう思おうと、偉そうな人の言及があったら、じゃあそれは正しいんだと思いますか?。 しかしまあこの言及の場合は、ゲーム作家とやらが、ああ、俺はそう思っていると言えば、一つの証言となりますよね。 しかしゲーム作家だって複数いる。しかもゲーム作家と呼んでいい人とは具体的にだれか? ですから現編集者はこの議論は全く無意味だと考える。しかし実は前編集者もやりたいことは、ただただ商業の創作者を持ち上げて、ネット上や同人の創作者を貶めたいだけなんですよね。 とにかく前編集者は私欲を見たすために、この言及の出典とやらを探しましたが、辛うじて、「一次情報以外、個性には役立たない:インターネットやSNS:そうした情報は知識として役に立つことはありますが、ゲームデザイナーが個性を発揮するうえではあまり役に立ちません<ref>『ゲームデザイン プロフェショナル』、P314</ref>」という記述を見つけただけだったという。 {{コラム|マリオメーカー、他| マリオメーカーは任天堂が2015に発売した、Wii U用の(3DS用も有)ゲームソフトウェアですね。マリオのゲームの素材を使って、自分でもアクションマリオゲームが作れる。 このソフトウェアでは、自作のマリオゲームを任天堂のWebサイトに投稿、公開する事が出来ます。しかし条件があって、一度そのゲームをクリアしないと、公開はできません。 そして一方、実は、マリオメーカーが発売される前、インターネット上には「改造マリオ」といって、マリオのROMを違法改造して、自作ステージをつくって無料公開する行為が行われていました。 実際には改造マリオのデータを、ゲームとして利用するのはなかなか手間がかかり、むしろそのプレイ映像を動画化し、それが動画サイトで人気になったようです。しかし改造マリオを作るという行為自体が、著作権の問題を持っていました。 そして多くの場合、そのステージの難易度は異常に高くなり、そしてその難易度の高いマリオを実際にクリアする動画が非常に人気を持ったようです。 さて、そこでこのことに関して、前編集者は例え話を始めたのですが、まず一つ目が、「犬が人をかんでもニュースにならないが、人が犬をかむとニュースになる」、だそうです。 つまり…改造マリオの方が人が犬を噛んでいる? すると任天堂本家のマリオメーカーが、犬が人を噛んでいるか? 辛うじてこの例え話の意味は分かるけど、もう一つの例え話がこれ↓なんだけど… また、アンケート調査などの心理学的ノウハウとして、「あなたは○○を買いますか?」と「あなたは○○を好きですか?」と聞いたときでは、アンケート結果の傾向がかなり異なり、多くの人が、「○○を好きですか?」と質問されても決して実際に好きなものを答えるのではなく、世間から賞賛されそうな趣味趣向の場合にだけ回答で「はい、好きです」と答えるようであるという、分析結果があります。 これはさらによくわからん(?_?)????? マリオメーカーは買うで、改造マリオは好き? 要するにいつものこの編集者の議論で、商業のマリオメーカーを褒め称えて、Web文化の改造マリオは貶めたいんだろうね。 まあ改造マリオは違法性があるから、別にそれはそれでいいけど… }} {{コラム|とにかく E.Suj. はWeb文化を貶めて、商業文化を誉めそやしたい| 確かにWeb上には無料コンテンツも多々あるが、商売人たちが仕掛けているのは、有料コンテンツのための撒き餌のようなものだ。一方で同人、アマチュア活動として、無料で作品を公開している人もたくさんいるし、これらのコンテンツまで貶めようと試みる E.Suj. は本当に性根の腐った嫌な人間だね。勿論違法性のある無料コンテンツもあるから、これらは当然非難されてしかるものだろう。 まずゲームに関しては、前編集者の報告では、実際にプレイすることなく、無料動画を見ただけとか、あるいはさらに悪い例はWeb上の言論だけをもとに、特定のゲームを批判する人物がいるようで、これは確かに良くないことだ。 漫画界でも、似たような問題があるようだ。マンガ『ラーメン発見伝』(小学館ビッグコミックスペリオール )では、作中のライバル役のラーメン屋経営者(いわゆる「ラーメンハゲ」)が、ネットの情報をもとにラーメンの実際の食べたときの味を無視してラーメン評論をするラーメンマニアに陰口で悪態をついています。確かに漫画だろうが、ラーメンだろうが、映画だろうが、小説だろうが、実物に触れないのにあれこれ言うのは、基本的には悪いことだろう。 とはいえ現編集者は、[[v:Topic:読まないのに書評]]なんてやっちゃったけどね。まあ気にすんなよ^^;;;。 そこで前編集者は、Webを徹底的に否定して、市販本だけに価値を置いているけど、それも極論じゃあない? ゲームを実際にプレイしないで、各種情報で知った気になるのは確かに良くないこと<ref>『ゲームデザイン プロフェッショナル』、P.282</ref>だけど、我々だってすべてのゲームはプレイできないよ。 それに各種情報から、何となくいけ好かない存在って誰にでもあるものだし、まあ基本悪口はよくないけど、Webは新しい混沌メディアだからね。市販の書籍やゲームが圧倒的に価値高いわけではないね。 新聞の第一面によく載っている、有り得なく馬鹿馬鹿しい書籍の広告、あんなの絶対に買わないし、読まなくたって無条件で悪口言いたくなるよ。 とにかく E.Suj.はゲームに関して、メジャー作品、人気作をプレイせよ<ref>『ゲームデザイン プロフェッショナル』、P280</ref>、なんて書くけど大きなお世話。自分のプレイするゲームは自分で選ぶね。 YouTube動画に、「アニメ私塾」というチャンネルがあるらしくて、そこで勧める絵の練習法は、プロのアニメ作品の模写らしいけど、これだって単に一つの意見。絵の勉強法なんて無数にあるよ。 まあ確かに漫画に関する違法サイト読書は問題だろうし、検挙もされているけど、同人誌やエロ関係の無断掲載は検挙もしていないように見える。 ただそこで漫画を読むことは倫理的に非難はされるけど、読んだ以上は、作品を読んでいないという評価は違うだろう。勿論不正な方法で読んだという非難は正当だけどね。 結局、E.Suj.の目的は、いい加減な言論を駆使して、既成の商業コンテンツの権威と金を守りたいんだろう。 }} アナログゲーム(カードゲームやボードゲーム)の設計者は、ネット上の意見はもとより、実際のテストプレイヤーの意見さえあまりあてにならないという考えがあるらしい。テストプレーヤーも様々な理由で本音を語らなかったり、何らかのバイアスであまり有用な意見が出てこないという見方もある。一番重視するのは、実際のプレイの様子を観察することだいう<ref>『ゲームプランとデザインの教科書』、P338</ref>。 {{コラム|世のメディアでは、人気投票企画は多いが、基本的には遊びでお祭りでファンサービスで、本格的な統計調査とは別物だろう。| イナズマイレブン、2008発売のサッカーRPG。アニメ化や映画化もされている。中学校サッカー部が舞台だから、中学生がメインターゲットだろう。 この公式サイトが、登場キャラクターの人気投票を行ったという。 作品中に、五条というマイナーキャラクターがいた。中学生で、おじさんぽい顔、眼鏡で目が隠れ、何を考えているかわからない不気味な悪役的キャラクター。 ある匿名掲示板で、おそらく[[w:2ちゃんねる]]だと思いますが、このキャラクターへの組織票投票の呼びかけが行われました。 はたして2(5)ちゃんねるに中学生のユーザーがいるのか? 少しはいるかもしれないが、やはりこの組織票祭りの参加者の多くはもっと年長、しかしそれほど年寄りのメンバーもいないように思われる。 まあ結局オタクどもの遊び、祭りということだろうが、しかしその影響か、その公式サイトでの人気投票結果は、五条が一位になった。 まあ不合理な結果と言えば結果だが、ネット上ではその手の馬鹿げたことはしょっちゅう起こる。少しこだわりのある変わり者たちが、自然な状態をかき乱したくて、色々なことを仕掛けてくる。 公式サイトの運営者としては、面白くない展開だが、そもそもイナズマイレブンのゲームユーザーの何割が中学生か? 購買層の中に明らかにこの手のオタク、大きなお友達が、かなりの数占めているだろう。 しかしこういう人たちが、企画内容に大きな影響を及ぼすなら、やはり運営としては面白くない話だ。 AKB48の人気投票は、CDに投票券をつけている形式だが、やはりここでも不規則状況を狙って、投票券目当てでおなじCDを何枚も購入するファンがいるらしい。 勿論この手の、奇矯な手妻は、人気投票の企画者にとっては、面白くないことだが、しかし世の中こういう変わり者は必ずある程度いるものでね、それはそれぞれの企画者が上手に運営方法考えればいいのであって、こんな話をこのページにわざわざコラムとか言って書く意味ある? ;美人投票 経済学者ケインズは、投資家の行動を美人投票にたとえた。「100枚の写真の中から最も美人だと思う人に投票してもらい、最も投票が多かった人に投票した人達に賞品を与える」、投資家は、この手の美人投票に参加しているようなものだと。普通の美人投票では、自分自身が美人だと思う女性に投票する。しかしこの投資家の美人投票では、賞品目当てなので、自分自身がどう思うかより、票が集まる写真はどれかを予想して投票するだろう。 前述のイナズマイレブンの投票祭りも、自分が好きな登場人物に投票しているわけではない。地味で目立たないキャラクターが一位になれば面白かろうと、示し合わせて、不美人投票をしているのだ。 ;ノイジー・マイノリティ ノイジー・マイノリティとは、少数派であるのにその声は大きい、目立つ、目立つにかかわらず、そのような考え方、主張をする人は少数である、だから基本的にはその人たちの大きい声は聞き入れない方が良い、多数派の意見を反映していない、ということでしょう。 基本的にはネガティブな意味を持つ言葉であり、大騒ぎするクレーマーに近いイメージだろう。 なるほどね、確かに現編集者の主張はいつでも希少な少数派の意見に近いだろう。 そしてすじ肉しちゅ~なる人物はいつも多数派の味方で、多数派の安易で愚かな意見が絶対的に正しいと振りかざし、他者を愚弄し常に暴力をふるっている。 そういう多数派の暴力に対抗するために、マイノリティとして常に俺は大騒ぎしているのだが、物は言いよう、言い方を少し変えれば、集団、多数派の暴力が正しいと、言い張る事が出来るんだね。 衆愚の暴力とは、どこまでも防ぐのが困難なのね。 }} さて、我々は学業でも、スポーツでも、趣味でも、そしてもちろん仕事でも、必ず技能というのがあって、それを日々身に着けている、身に着けようと試みていると考えていいと思いますが、果たして今の自分はどんな技能を持っているのか?そもそも何らかの技能持っているのか?そういうことで悩んだり考え込んでしまうことはありますよね。 E.Suj.のように集団におもねる以外の生き方を一切知らず、大した技能なんかないのに、スキルスキルと威張り倒して他人を貶めること以外何もしない人間がいる一方で、かなりの技能を持っているのに自信が持てず、鬱々と生活している人間もいます。 勿論技能自体はかなり客観的な物でしょうが、他者の技能評価は結構いいかげんで、技能が大したない人間が威張り散らして、ある程度技能がある人間をこき下ろして貶めている事なんて、世の中でしょっちゅう起こっていますよ。 そこで大した話ではないんですが、ある技能からある技能に転向する場合がありますよね。つまり生活自体が変わるのでしょう。特定の技能をふるう生活から別の技能中心の生活に変わること。 具体的にゲーム業務に関する話題では、デザイナーからプランナーに役務が変わるとか… その時にはやはり、デザイナーとしての自分は封印したほうがいい<ref>大久保磨『レベルデザイン徹底指南書』、2016年12月14日 初版 第1刷発行、P81</ref>。 やはりプランナーとしての仕事を優先し、デザインに関してあまり大上段に口を出さない方がいいでしょう。 {{コラム|一人で何でも出来るわけではない。しかし偏向した愚か者の集団より、一人の総合的な人間の方が、相対的にいいものを作り出すだろう。| 基本的に商業漫画、商業アニメーション、そしてほとんど多くの商業メディアはその根源的な創作部分でさえ、多人数の協業で作られています。一応全体を統括する指揮者はいますが、個々の秀逸な表現はその監督だけの手柄ではない。 これはこの手の物事についてある程度知っている人間にとっては、もちろんたまには例外もありますが、ほぼ当たり前のことで、得意げに語ることでも何でもない。 「と学会」の人が2010年ごろにニコニコ生放送の番組に出演したときに、この人物は、ある漫画原作者にネタ提供したと語ったという。しかしネタ提供といっても様々な形態があり、ピンからキリまであり、実際にその作品に貢献していない場合もあるし、単にこいつ、自慢話したかっただけだろ? 漫画家にしろ脚本家にしろ、色々な事柄にアイディアの元を頼っているだろう。有償無償に関わらず、アドバイザーも多いと思う。 ゴルゴ13なんかは明らかに協業で作られていたし、各種映画やテレビドラマも、様々な人間がその作品の質の向上に寄与している。 歴史ものや軍事物、その分野の専門家が強力に考証を加えているし、当然設定の信頼度も高くなる。 だから創作作品は協業関係が上手に機能して、それを統一した理念でまとめ上げれば、当然質はかなり高いものを作る事が出来る。 }} {{コラム|可処分時間| 経理には「可処分所得」という用語があります。労働者の給料のうち、税金や社会保険料など支払いが義務付けられているものを差し引いた、残りの自由に使えるぶんの金額です。勿論その中から自分の生活費は支出しなければいけませんがね。 そこから類推して「可処分時間」。 前編集者の言葉では、「1日のうちの自分の起きている時間のうち、労働時間などを差し引いた、残りの自由に使える時間」。 だから、もし無職で何らかの理由で生活できるなら、100%が可処分時間でしょう。 で、E.Suj. はこのサイトで、こういう人間をひたすら愚弄するような文章を書き続けて来たのですが、 E.Suj. 自身の可処分時間は何%? 仮にこのサイトでインチキ書いてお金が入っても、それは可処分時間に入れろよ? そして…「商売の競争とは、消費者の可処分所得の奪い合い」ということらしいけど…希少な可処分時間を奪われたうえ、そいつらに金払うの? 可処分時間って必ず金払って埋めなければいけないの? }} ===ドラゴンクエストは、ゲームを進めるため、ゲーム操作の技能を得ることを求めていない?=== ドラゴンクエストでは、ゲームのプレイを続け、キャラクターのレベルが上がっていくごとに、キャラクターも戦闘力が上がり、より強い敵も倒せるようになる。これはそれ以前のアーケードゲームのように、プレイヤーがゲーム操作の上手な技能を身に着けることによってクリアするのではなく、レベルが上がることで事実上、プレイヤーが上手な操作する必要なく強くなっている。これを、「クリア保障」と呼んでいるWebコンテンツもある<ref>https://news.denfaminicogamer.jp/column05/170905b 2020年12月21日に閲覧して確認.</ref>。 ドラクエでダンジョンに入った場合でも、様々な試行錯誤は繰り返すであろうが、プレイし続けて時間経過とともに経験値が上がると、最後にはダンジョンのボスも倒す事が出来て、クリアする事が出来る。 つまりドラゴンクエストでは、プレイヤーがそのゲームの操作の技能を覚えることで、難易度の高いステージをクリアしているのではなく、ゲームを続け、経験値が上がりレベルが上がることによって、ある意味自動的に強くなっている。 序盤のダンジョンで未探検のものがある場合、その時点ではかなり探索は困難を極めるが、レベルが上がった時点では、割と簡単に、クリアできる。つまり難易度が自動的に下がっているともいえる。 つまりドラゴンクエストのクリアシステムは、ゲームを続けてプレイを重ねていくうちに自動的にキャラクターは強くなり、最後にはゲームクリア、コンプリートに至る、ということだろう。 ドラゴンクエストのようなインターフェイスでも、古いゲームやフリーゲームではこの特徴を満たしてはいないものがあると、前編集者は書いていたが、どういう事だろう? 何度も書くが現編集者はそれ程沢山ゲームをやりこんでいるわけではない。 アクションゲームでは当然難易度の高いステージはそれなりの技能やテクニックが必要だろう。しかしRPGではそれほど技能の必要や出る幕もないから、多かれ少なかれドラゴンクエストのような形態にはなるのではないだろうか? 全体を通してレベルがそれほど上がらないゲームというのはあるし、あったのだろう。この場合は何らかのゲーム上の困難の打開策や有効な戦術を見出さない限り、クリア困難の事態に陥るだろう。 RPGに限らず一般に、ゲームの後半に行くに従って、次ステージ攻略などのための事前準備の増加や、試行錯誤の時間の増加に時間のかかるようになっていく事が多い。そして、ステージクリアに必要な時間の増加が、ゲームを苦手とするプレイヤーに、そのゲームのクリアを諦めさせる<ref>http://endohlab.org/paper/whydoplayersdrop.pdf 2020年12月21日に閲覧して確認.</ref>。つまり娯楽であるはずのゲームが、難易度が上がりすぎてその機能を果たさなくなるのだろう。 === 自由度 === 一本道で難題を乗り越えるゲームもありますが、いっぽうでマルチエンディングとか、攻略ルートや展開が複数あるゲームもありますよね。こういう自由度の高いゲームは、その展開の場合の数に応じて、調整の際に考慮する事項も増えていきます<ref>『ゲームクリエイターの仕事 イマドキのゲーム制作現場を大解剖!』、P78</ref>。 ===Non-title=== ※バランス調整に限った話題ではないが、他に適した単元が見つからないし、メインページに書くほどでもないので(←なら書かないで削除せよ。by E.H.)、間借り(まがり)的にバランス調整のページで書くことにする。ただし、この節の内容を他のぺージに移動することは、 E.H.が禁止する。 ====ゲーム業界に就職したい?==== ……ならば、今現在の業界を構成している人達のアドバイスに従うのが無難だろう。 まず彼らが望むのは、ゲーム人気作の知識。特にデザイナーならなおさららしい。まず過去の名作は手本になるという。それから共通言語としての、コンセプトや知識を知っておくべきだと<ref>『ゲームデザイン プロフェッショナル』、P278</ref>。 とにかくゲームについて知らないのはよくないようだ。過去現在の人気作や、自分の興味ある、そして入社出来たら実際に作っているジャンルのゲームについて、プレイし、周辺知識も知っておきたい。 ====[https://www.uta-net.com/movie/59818/ シッパイマン]==== この節のタイトルは、失敗とは何かを知りたければ、以下を読むよりリンク先を見た方がいいだろう、という意味のリンク付きタイトルです。 基本的に前編集者は手本がなくては生きていけないようで、創意工夫という言葉もあまり知らない。そして権威ある手本のパワーに依存しまくって、他者を愚弄しまくる。 しかしまあとりあえず、その論旨に乗っかって記述するが、人気作や人気シリーズをとりあえず崇めて手本にせよと。そして人気でない作も良く調べて、崇める手本と比べてどこが良くないか見いだせ<ref>https://news.denfaminicogamer.jp/interview/200615a/3 2020年11月27日に閲覧して確認.</ref>、と。 そしてなぜか前編集者はゲームの事だけで完結せず、アニメの事も語りたがるんだけど、まあ好きだからなんだろうけど、ガンダムについて語りたければ、それ以前のロボットアニメについても調べろ、と、岡田斗司夫や氷川竜介が書いていたんだって。 結局、性格の汚い有名人の権威に頼りっぱなし。 そしてまたまた岡田斗司夫の著作によると、演劇作家・演出家の鴻上尚史氏はゲーム進出に失敗したらしい。失敗してたの^^;;;??? 現編集者はそれは知らなかった。ゲームに手を出したことは知っていたけど…そもそも鴻上さん、映画制作も失敗していなかった^^;;;?。特別に好きでファンだという訳ではないけど、一時期この人のラジオかなり聴いていたんだけど… とにかく岡田氏の結論は、鴻上氏とどういう関連があるかはわからないが、「成功例から学びたがる人は多いが、しかし成功例だけから学ぶのは素人。プロは失敗例にこそ学ぶ。」、らしい。もっともこれはあくまでも前編集者の要約だけど… うーん、プロだの素人だのはどうでもいいけど、失敗と成功の両方から学ぶのは、ごくごく当たり前で妥当なことじゃないの? あと失敗に関しては、畑村洋太郎氏の失敗学という概念もある。<ref>https://www.jstage.jst.go.jp/article/jjlp1960/43/2/43_2_182/_pdf</ref> {{コラム|「失敗を恐れるな!!」なんてよく言うけど、実は誰もが失敗は怖い。むしろその怖さや失敗自体との向き合い方が問題なのだろう。| まあ現実問題として、失敗のない人生なんてないよね。 かと言ってねー、そう簡単に人間成功しないし、物事上手くいかないものだよ。 とにかくどん欲に成功を求めすぎるのも、逆説的に失敗の元になるだろう あとあまり点数とか量について考えない方がいいと思う。 マーフィーの法則ではないけど、この世界と我々の人生は明らかに失敗方向にバイアスがかかっている。 失点しても試合に勝てばいいという意見もあるけど<ref>『ゲームデザイン プロフェッショナル』、P.334</ref>、結局ぼろ負けして泣いて帰ることもしょっちゅうだよ^^;;;。 しかしまあ、誰もがそこそこ成功したいよね。 だけどさー、なんだかんだであんたらの人生、物事上手くいって楽しいときは確実にあるでしょ? }} ===異業種? いやいや、それどころか、異人、異世界の事も想像しろ><!!!=== ゲームとは文化でもあるでしょうか。様々な文化の一分野? そうなると文芸とかイラストとか、短歌とか映画とか、小説とか漫画とか、様々な文化のジャンルがありますよね。 特定のジャンルが衰退するとか発展するとか、具体的にはどういうことですか? もちろん商業文化としての、流通の規模というのはありますよね。しかし文化というのはだれ一人手掛けなくても、自分自身がその創作活動を続け、何らかの形で発表し、そしてそれを享受する人がある程度いる以上、仮にお金は一切発生しなくても、完全にこの世から消え去ることはない。 2012年に新日本プロレスリングを買収したゲーム会社のブシロードは、こう述べた。「すべてのジャンルはマニアが潰す」<ref>https://newspicks.com/news/4135958/body/ 2021年11月7日に確認→ただし有料コンテンツなので表紙を確認しただけ^^;;;</ref>。マニアねー。そもそもオタクとマニアはどう違うの? オタキングを崇拝している人たちは、マニアは悪く言えるけど、オタクは悪く言えないよね? どっちにしろ大した言及じゃあないよ、馬鹿げた話だね。 そしてゲーム業界は、1990~2000年の一時期、ジャンルによってはゲームが高難易度化した作品が多くなって、新規参入者が苦手と感じてプレイヤーが減って衰退縮小していったことがあったという。 まずゲームのジャンルが明確に固定化されているとは思えない。ある程度はそれ様の物はあると思うけど、結局これって、ゲーム商売の話であって、もっと一般にゲームが好きな人たちの事を考えると、特定のジャンルが好きならば絶対自分たち自身でその分野を盛り上げようとするだろうし、そういう人たちが少なければ当然ジャンルの規模は小さくなり、小さくなったり消えてしまったところで、それはそれ、歴史の流れなんじゃあない? ゲームセンターの対戦格闘ゲームでは、初心者が筐体をプレイすると、熟練者が参入して、初心者を打ち負かす「初心者狩り」が起こり、初心者が楽しめない、参入者が減ってそのジャンル自体が衰退、ということもあったようです。 スポーツ競技でも似たようなことが起きると言うが、まあ結局この社会、やさしいいい人なんてほとんどいないし、本当の意味で賢い人間もほとんどいない。 とにかくどんな分野でも、事実上楽しくなければ、人は去っていくだろう。 {{コラム|作者は答えを知ってしまっている、が、それでも、自分の作りだした物語と世界は、素敵で魅力的なものだと思っているだろう。| ハドソン『新桃太郎伝説』(スーファミ版)の攻略本『新桃太郎伝説 究極本』(KKベストセラーズ 刊)で、作者の さくま あきら が、読者インタビューにこう答えています。 読者「ゲーム中、もっとも印象に残ったシーンはどこですか?」 さくま氏「作者はシナリオの答えを知ってるので、もっとも印象に残るとかそういうのはありません」 これは明らかに質問の仕方がおかしいし、不適切だろう。最も印象に残ったシーンって、…これはゲームと物語を受け取った側が感じる事じゃない? 。 }} ;ティッシュテスター 作者バイアスでバランスが分からなくなるのは作者だけではなく、テストプレイヤーやデバッガーも、そのゲームに慣れてゆくと、次第に感覚が一般プレイヤーとずれていき、適切なバランス側が分からなくなっていく。 このことに関して「ティッシュ テスター」(tissue tester)という言葉があるらしい。つまりティッシュは一度きりの使い捨て、新鮮にゲームを見てバランスを判断できるテスターも、最初の一回きりということ。最もテスターも仕事としてそれをやっているのだから、使い捨てにされたらたまったもんじゃあないけどね。 「フレッシュミート」(新鮮な肉、fresh meat)とも言うようですね。 どちらにしろゲーム業界の連中が、他人を雇うということをどう見て考えているか、よくわかる言い草だね。 === 要素の相互関係 === ==== 概要 ==== 文献『ゲームデザイン プロフェッショナル』によると、調整は、関連あるものを、まとめて同時期に、ただし1個ずつ調整していきます<ref>『ゲームデザイン プロフェッショナル』、P.182</ref>。 このため、まだ関連ある要素を実装しきっていない段階では、調整しません。だから開発の最初から調整することは、まず無いでしょう。 しかし、場合によっては、要素の実装をそろうの待つと調整開始の時期が遅くなりすぎてしまい、計画に支障が出る場合があります。そういう場合、ある程度のまとまりのある実装ができた段階で、調整をするようです。 具体的な調整の判断基準については、参考文献『ゲームデザイン プロフェッショナル』を買ってお読みください。 もし読者が練習として、てっとり早くレベルデザイン・バランス調整の経験を積みたい場合、角川書店(現: KADOKAWA)の『RPGツクール』という制作ツールで実際にゲームを作ってみるのが良いでしょう。文献『レベルデザイン徹底指南書』(大久保磨 著)でも、RPGツクールによる練習・勉強を進めています<ref>大久保磨『レベルデザイン徹底指南書』、2016年12月14日 初版 第1刷発行、P81</ref>。 ==== マップと敵の相互関係 ==== ゲームバランスを決めるのは、敵の強さだけでなく、マップの構成、さらにRPGのダンジョンなら宝箱の中にあるアイテムや装備品の強さ、などなどのさまざまな要素が加わります。 宝箱もマップの構成要素ですから、広い意味では宝箱もマップだとすると、つまり敵そのもののの強さだけでなく、マップもバランス調整に大きく影響します。だから、もし仮に時間が無限にあるのなら、理想的には、ダンジョンなど各ステージののマップが実装されてからバランス調整を行うのが理想でしょう。 しかし、実際には、マップの実装は、なかなか時間の掛かることです。特に、マップを考えることは、そのステージの世界観などを考えることでもあるので、そういった理系的ではない文系的なことも考えなければなりません。 マップに敵を組み込む方式で調整する場合だとマップの実装を待っている間にはバランス調整が出来ないのも、なかなか難しい問題です。 だからマップと敵の調整の順序は、おそらく人や会社によって色々な方式があると思います。たとえば、 :マップを作ってからそのマップに敵を組み込んでみてプレイしてみて、敵の強さを決めるのか、 :それとも敵の強さを決めてから、マップを決めるのか、 :あるいはマップと敵を別々に決めてから、最後に組み合わせて微調整するのか、 などなどです。 ご自身の作品にあった方式をお選びください。 ===== 始めよければ全てよし ===== さて、ゲームが長編になる場合、まずはプロトタイプ的に、序盤をやや多めに通しプレイをして、とりあえず序盤のバランスがゲームとして面白くなるように調整すると良いでしょう。 書籍『ゲームプランナー集中講座』でも、ゲームの初めと終わりの印象がよければ、途中のバランスが少しくらい悪くても楽しんでもらえると述べています<ref>『ゲームプランナー集中講座』、P236</ref>。 :※ なお、アニメ産業でも、実はテレビアニメは、第1話と最終話だけ、他のエピソードよりも予算が多めに作られるのが普通です(特に公言はされてないが、多くの作品で明らかにクオリティが違う場合が多い)。 とはいえ、ゲーム制作当初は、そもそも終盤のストーリーがまだ未完成だったりするので、意図せずとも、こういったプロトタイプ的に序盤をやや多めに調整する方法が自然に行われる事になるでしょう。 商業作品でも、たとえば攻略本やファンブックなどに書いてあるゲーム開発裏話などを見ると、RPGでは、(プレイヤーからは数値の見えない)敵の強さのほうを動かすことで、バランスを調整するという事例などもよく紹介されています。よくある話が、最終ボスなどの能力値です。原理的には、敵側の能力値ではなく、味方の能力値で調整したり、あるいは装備品で調整したりしてもイイはずですが、しかしよく開発裏話に出てくるのは、なぜか敵側の能力値の話題ばかりです。 たとえば、スーファミRPG『新 桃太郎伝説』では、最終ボスのパラメータのほうを調整していることが、KKベストセラーズ(出版社名)から出た攻略本『新桃太郎伝説究極本』に書かれています。(調整前はボスはもっとHPが多かった。) :※ただし、あくまでRPG限定の話題。アクションゲームなどでは、違うかもしれない。 また、こういった調整順序の前提として、調整はゲーム序盤から順番に、ゲーム後半に向かって調整していくしかありません。 そのため、古いゲームなどでは、よくゲーム後半で、調整不足のために、極端に難しかったり、あるいは逆にあっけなく簡単すぎる後半だったりなどの話題も、よく聞きます。ドラクエ2の後半ダンジョンであるロンダルキア洞窟とその次ステージが典型です。 さて、プレイヤーに目立つ部分(たとえば味方キャラの能力値や装備品の性能など)を基準にして調整するといって、けっして全く数値をイジラないというワケではないのです。あくまで、(調整による変動幅の大きい敵能力値と比べたら、)「比較的には、味方キャラ関連の数値は、調整による数値の変動の幅が小さめ。敵の能力値は、調整による変動の幅が大きい。」という事にすぎません。 {{コラム|ノイマン「ゲーム理論」で説明できないのがテレビゲーム| 日本の人類学者の中沢新一は、ノイマンのゲーム理論で説明できないのが昨今のコンピュータゲームの特徴だと言っています。その発言の出典は忘れたのですが、人類学者で有名な中沢新一は近年、ゲーム産業に関心を持ち、たとえばナムコ出身の遠藤雅信などとも対談しています<ref>https://news.denfaminicogamer.jp/kikakuthetower/nakagawa-endo_bb/2 『ゼビウスからポケモンGOまで… 国内ゲーム史を遠藤雅伸氏と『現代ゲーム全史』著者が振り返る。中沢新一氏も壇上に登場!【イベントレポ】』 2017年4月12日 12:30 公開 ] 2022年1月18日に確認. </ref>。(なお、リンク先イベント記事の司会役の「中川」氏とゲストの「中沢」氏は別人なので、混同しないように) ゲーム理論の用途としては、現代日本の学問では、政治的局面での外交戦略などを語る際によく政治学書で用いられたりします。ただし、そのゲーム理論でも、中沢新一によると、それでコンピュータゲームを語るのは不足だという事です。 中沢は特に言及していないですが、数学的にモデル化するなら、政策応用なら「国際情勢」など外交的な制約によって出力にとりうる値1個あたりの幅や個数が2~3個に限定されたりのような、値の個数が十分に小さくて有限の整数個の場合でないと、なかなかゲーム理論の応用は効果を発揮しません。 (20世紀の天才数学者 フォン・ノイマンの)『ゲーム理論』のような出力値に選べる個数が極端に少ない理論は、コンピュータゲームの調整では不足でしょう。本ページでも、ノイマンのゲーム理論については、版にもよりますが、このコラム以外では特に言及していないだろうと思います(2022年1月までの時点では、ノイマンのゲーム理論には言及していない)。 さて中沢の意見ではないですが、そもそもゲーム理論についてノイマンについての出典として、たしか数学者の森毅(もり つよし)のエッセイ本だったと思いますが、ゲーム理論はもともとノイマンが第二次大戦中の亡命中か何かにトランプのポーカーを参考に考えついたらしいです。 ネット上のゲーム評論では、経済由来の表現でよく使われる表現は、ゲーム理論ではなく「インフレ」「デフレ」などといった表現です。 経済学を知らなくてもゲームは製作できるでしょうが、どうしても経済学を参考にするなら、ゲーム理論よりも物価政策のほうを勉強したほうが良いかもしれません。 一応、書籍『ゲーム作りの発想法と企画書の作り方』ではゲーム理論も紹介されていますが、しかし具体的にどうゲーム作りにゲーム理論を応用するかは書かれていません<ref>『ゲーム作りの発想法と企画書の作り方』、P64</ref>。 }} === 各論(デザイン的なこと) === どの程度、レベル上昇でキャラクターを強くすればいいかについては、ハドソン社あたりでの有名な慣習があり、新しく訪れたダンジョンなどでは「レベルが3上がると、敵を1撃で倒せるようにすべし」という有名な基準があります<ref>『ゲームプランとデザインの教科書』、P.94、 ※ 著者のひとりの「平川らいあん」氏はハドソン出身</ref>。他社ゲームでは別かもしれませんが、だいたいスーファミ時代の桃太郎伝説シリーズはこんな感じに調整されているはずです。 == RPGのダメージ計算式 == === 特化型が有利になりやすい === 文献『ゲームプランとデザインの教科書』によると、ファミコン時代のゲームに限らず、21世紀の現代的なゲームでも、「なんでも平均的にできる」キャラクターよりも「○○だけなら自分が一番強い」といった感じの特化型のキャラクターが戦闘では強くなりやすい傾向があります<ref>川上大典 ほか著『ゲームプランとデザインの教科書』、秀和システム、2018年11月1日 第1版 第1刷、P.227</ref>。対して、バランス型は「器用貧乏」になりやすいのが現状です<ref>川上大典 ほか著『ゲームプランとデザインの教科書』、秀和システム、、2018年11月1日 第1版 第1刷、P.227</ref>。 なお文献『ゲーム作りの発想法と企画書の作り方』によると、ダメージ計算式を考えるのは(プログラマーの仕事ではなく)ゲームデザイナーの仕事です<ref>『ゲーム作りの発想法と企画書の作り方』、P145</ref>。 では、特化型が有利になりやすい原理を、これから説明していきます。 たとえば、キャラクターに能力をプレイヤーが自由に選んで振り分け配分できるシステムのゲームがあったとしましょう。(商業ゲームでも、いくつかの作品で、似たようなシステムのRPGがあります。) 説明の単純化のため、合計値が必ず100だとしましょう。 つまり、たとえば下記のようになります。 ;作成キャラの能力例 :(※ 合計100) ちから: 10 たいりょく: 30 しゅびりょく: 10 すばやさ: 40 きようさ: 10 さて、別の作成キャラ例を考えます。 ;平均型キャラA ちから: 20 たいりょく:20 しゅびりょく: 20 すばやさ: 20 きようさ: 20 :(※ 合計100) のように、能力値を平均にふりわけたキャラクターと 合計値は同じですが、特定のパラメータに特化して能力値を振り分けした ;特化型キャラB ちから: 40 たいりょく:20 しゅびりょく: 30 すばやさ: 5 きようさ: 5 :(※ 合計100) のようなキャラクターを、 コンピュータ上でRPGの戦闘システムのアルゴリズム上で対戦させた場合、 ほとんどの20世紀のRPGのアルゴリズムでは、特化型のキャラBのほうが勝ち、つまり特化型のほうが強くなってしまいます。 さらに言うと、たいてい「攻撃力」のような、敵にダメージを与える意味のパラメーターに振り割ったほうが、キャラクターが強くなるゲームのほうが多いです。(ファミコン時代から、ウィザードリィ1の攻略本でそういわれていました。敵モンスター『ワイバーン』あたりの攻略法として「攻撃は最大の防御」という格言を出しています。表紙の黒かった攻略本なので、たぶんゲームアーツの本。『ウィザードリィ攻略の手引き』(MIA BOOKS)かと思われます。) なぜこうなるかと言うと、なぜなら、もし攻撃力が上がると、敵を倒すのに要するターン数も減少するので、結果的に敵を倒すまでに自キャラの受けるダメージ量も減るからです。(なお、現実の軍事学でも、似たような事が言われており、戦術論ですが、クラウゼヴィッツ(近代ドイツの軍事学者の一人)は防御重視の作戦よりも攻撃重視の作戦のほうが有利だと述べています。防御だけで攻撃しなければ、現実でもゲ-ムでも戦闘では絶対に勝てません。) 裏を返せば、平均型能力のキャラは、多くのゲームシステムでは弱くなりがちです。 パラメータの振り分けは自由ではないですが、ドラクエ2(ファミコン版)でいう、サマルトリア王子が弱くなる現象です。ファイナルファンタジー3・5の赤魔導師も、似たような弱点を抱えています。 理由はいろいろとありますが、バランス側の弱くなりやすい理由のひとつとして、参考文献などは特には無いですが、 :・ウィザードリィやドラクエなどの古いRPGのアルゴリズムが、特化型に有利になっているという歴史的な経緯。 :・命中率などの確率に関わるパラメータ(「器用さ」)のある場合、パラメータ割り振り前から既にある程度の底上げ補正がされている場合が多いので、わざわざ命中率を上げると割り損になる。 :・「すばやさ」(素早さ)が攻撃の順番にしか影響しない場合、素早さが低くても1ターンに1度は攻撃できるので、素早さを上げると損。 などの理由があるでしょうか。 命中率に関しては、多くのRPGで、攻撃が外れるのは、プレイヤーに不満感を与えるので、たいていのゲームでは、ゲーム序盤のレベル1のキャラであっても、数値上での「命中率」や「器用さ」などの表向きの命中率が低くても、たとえば「命中率 40」と表示されていても、実際のゲーム内部での命中率はたとえば+20%されてて本当の命中率が60%だったりするような場合もあります。 このような底上げ命中率のあるシステムだと、20%底上げされる場合、命中率を80%以上に育てるのは損です。なぜなら100%以上には上がりようが無いからです。 命中率が101%以上の場合に特殊な追加スキルなどを獲得できるなら別ですが(たとえば、クリティカルヒットの確率がけっこう増えるとか)、たいていの古いゲームでは、そこまでの手入れをしていません。おそらく調整に時間が掛かるからでしょう。 === ダメージ計算式 === さて、RPGの戦闘におけるダメージの計算式(「ダメージ計算式」といいます)に、アルテリオス計算式というのがあります。これは、昔のゲーム『アルテリオス』で採用された計算式なのですが、 攻撃側の攻撃力 - 守備側の守備力 = 守備側のダメージ という計算式です。 ドラクエやファイナルファンタジーのシリーズの計算式はもっと複雑なのですが、どのRPGでもダメージ計算式の基本的な設計思想・方針はアルテリオス計算式と同じです。 アルテリオス以外のダメージ計算式でも、たとえば :1.3×攻撃側の攻撃力 - 0.75 × 守備側の守備力 = 守備側のダメージ というような感じの計算式である作品も多いです。 せいぜい、変数の前に定数係数が掛かっている程度です。 なぜ、どの会社のRPGでも、この程度の中学校レベルの単純な計算式なのかというと、バランス調整が簡単だからです。 バランス調整するのは人間なので、もし、ダメージ計算式があまりに複雑な方程式であると(たとえば量子物理のシュレーディンガー方程式みたいなのだったりすると)、そもそもバランス調整担当の社員が理解できません。 そして、このアルテリオス式を見ると分かるのですが、 :攻撃側の攻撃力 - 守備側の守備力 = 守備側のダメージ もし自軍の攻撃力が0の場合、敵にダメージを与えられないので(ダメージが0)、絶対に負けてしまいます。つまり、攻撃力が敵の守備力を下回る場合も、絶対に負けるのです。 一方、「すばやさ」パラメータが戦闘の先攻/後攻の順番にしか影響しない場合、素早さが0であっても、勝つことは可能です。 また、守備力が0であっても、勝つことは可能です。 このように、パラメータの種類ごとに、そのゲームにおいて重視・軽視の差があり、不公平になっている事が多いのです。 また、バランス型の能力値のキャラクターの場合、せっかく「ちから」を上げて攻撃力を上げても、守備側の守備力を下回っていると、ダメージ0になってしまい、絶対に負けます。 つまり、 自分の攻撃力 > 敵の守備力 でないと、アルテリオス式では必ず負けるのです。 一方、 :1.3×攻撃側の攻撃力 - 0.75 × 守備側の守備力 = 守備側のダメージ のように係数を掛けた計算式の場合、 守備力を1ポイント増やしても、その効果は25%減少されます。(たとえばレベルアップの際に上昇パラメータを一種類選べるシステムの場合、守備力を選ぶと損になる場合が多い。) いっぽう、攻撃力を1ポイント増やすと、効果は30%増しです。 このように、計算式によって、有利/不利なパラメータという格差が生じます。 === DPS (Damage Per Second) の概念 === :※ 出典は無いが、あまりに有名な概念なので、さすがに消さない。 最近のRPGゲームには攻撃コマンド選択時に「二段斬り」などのスキル選択ができます。 スキルを設計するとき、昔の初心者のやりがちなミスとして、最近は減ってきましたが、スキルの結果の見かけの数値にゴマかされて、実はスキルが強くなってない特技を設計してしまうミスが時々ありました。 たとえば典型的なのは特技『ためる』です。これは、次回ターン時のダメージを数倍に倍増し、次回ターンの1回だけ、ダメージを倍増させる特技です。 この『ためる』は必ず、次回ターン時のダメージが2倍を超えないと(たとえば2.5倍にならないと)、無意味です。 なぜなら、『ためる』コマンドを選択したターンは、攻撃をしてないからです。 つまり、スキルを使わずに普通に2ターン通常攻撃した場合、ダメージ量は単純計算で :1+1=2 より、2ターンぶんのダメージです。 いっぽう、『ためる』コマンドを使えば、それがもし2倍しかダメージが倍増しない場合、 :0+2=2 で、結果は同じ通常攻撃2発ぶんのダメージのままです。 計算すれば子供でも分かる理屈ですが、しかしファミコン時代には市販の商業ゲームですら、こういうミスがありました。たとえばファイナルファンタジー3の職業『空手家』のスキル『ためる』です。 このようなミスを犯さないために必要な概念としては、'''DPS''' ('''D'''amage '''P'''er '''S'''econd) の概念が便利でしょう。DPS とは1秒あたりのダメージ量、という意味です。 もともと欧米のアクションゲームについての理論研究に由来する用語なので、単位が 秒 (second)になっていますが、RPGに応用する場合には単位をターンに変えるなどして工夫しましょう。 このDPSの概念を使って、上述の『ためる』コマンドの設計ミスを説明すれば、つまり、1ターンあたりのダメージ量(DPS)が上昇していないのが問題点です。 では、私たちが改善策を考えましょう。数学的に考えれば中学レベルで充分で、 : 0 + x > 2 を満たす変数xを設計するだけの問題です。 なので、たとえば、『ためる』後の攻撃ダメージ量を「2.5倍」とか「3倍」とかの数値に設計すればいいのです。 では、次に応用問題を考えましょう。 「『ためる』を2回続けると、さらにダメージ量がアップ」などのシステムを導入するときも、必ずDPSが増えるようにしましょう。 たとえば、この場合、ダメージを与えるのに最低3ターンが必要なので、不等式を考えれば、 変数xについての :0 + 0 + x > 3 を満たさないといけません。 つまり、『ためる』2回後のダメージ量は、最低でも「3.5倍」のように3を超える数値、あるいは整数に限定すれば、たとえば「4倍」とか「5倍」とかになっている必要があります。 == KPI == Key Performance Indicator という経営的な指標があり、『レベルデザイン徹底指南書』P140 および 『ゲームプランとデザインの教科書』P70 によると、共通しているのは後述の内容です。なお、『ゲームプランとデザインの教科書』P67 によると、オンラインゲームの運営などで使われる用語ですが、別にゲーム業界限定の用語ではありません。 ;DAU(Daily Active User) :デイリー・アクティブ・ユーザー DAUとは、その日に遊んでくれたユーザーの人数です。 ;MAU(Mathly Active User) :マンスリー・アクティブ・ユーザー MAUとは、その月に遊んでくれたユーザーの人数です。 ;WAU(Weekly Active User) :ウィークリー・アクティブ・ユーザー WAUとは、その週に遊んでくれたユーザーの人数です。 ;PU(Paying User) :ペイング・ユーザー 課金ユーザーの人数のことです。その日を課金ユーザー人数をDPU、その月の課金ユーザー人数をMPUと言います<ref>『レベルデザイン徹底指南書』、P140</ref>。 ;課金率 たとえば、ある月のユーザ数のうちの課金ユーザーの割合など、 一定期間中の課金ユーザーの割合を言ったりしますす<ref>『レベルデザイン徹底指南書』、P140</ref>。 あるいは、全ユーザーのうちの課金ユーザーのことだったりしますす<ref>『ゲームプランとデザインの教科書』、P70</ref>。(書籍によって、内容が微妙に違う) ;継続率 前月と比べて今月はどんだけユーザーが残っているかとか、あるいは前週と比べて今週はどんだけユーザーが残っているかのことを、 継続率といいます。 (以上) このほかにも、色々な指標があります。 == 参考文献・脚注など == 46z60qrkqgryfodnommz69ko966nppw 民法第520条の13 0 30201 206663 173166 2022-08-16T23:50:32Z Rhkmk 66092 wikitext text/x-wiki [[法学]]>[[民事法]]>[[コンメンタール民法]]>[[第3編 債権 (コンメンタール民法)]] ==条文== (記名式所持人払証券の譲渡) ;第520条の13 :記名式所持人払証券(債権者を指名する記載がされている証券であって、その所持人に弁済をすべき旨が付記されているものをいう。以下同じ。)の譲渡は、その証券を交付しなければ、その効力を生じない。 ==解説== 2017年改正にて新設。 類似の条文 *[[民法第520条の2|第520条の2]](指図証券の譲渡) ==参照条文== ==判例== ---- {{前後 |[[コンメンタール民法|民法]] |[[第3編 債権 (コンメンタール民法)|第3編 債権]]<br> [[第3編 債権 (コンメンタール民法)#1|第1章 総則]]<br> [[第3編 債権 (コンメンタール民法)#1-7|第7節 有価証券]] |[[民法第520条の12]]<br>(指図証券喪失の場合の権利行使方法) |[[民法第520条の14]]<br>(記名式所持人払証券の所持人の権利の推定) }} {{stub}} [[category:民法|520の13]] [[category:民法 2017年改正|520の13]] 9eb57h3qmgplqs8pbyse6n7vcn94nox 民法第520条の14 0 30202 206664 173167 2022-08-16T23:51:21Z Rhkmk 66092 wikitext text/x-wiki [[法学]]>[[民事法]]>[[コンメンタール民法]]>[[第3編 債権 (コンメンタール民法)]] ==条文== (記名式所持人払証券の所持人の権利の推定) ;第520条の14 :記名式所持人払証券の所持人は、証券上の権利を適法に有するものと推定する。 ==解説== 2017年改正にて新設。 類似の条文 *[[民法第520条の4|第520条の4]](指図証券の所持人の権利の推定) ==参照条文== ==判例== ---- {{前後 |[[コンメンタール民法|民法]] |[[第3編 債権 (コンメンタール民法)|第3編 債権]]<br> [[第3編 債権 (コンメンタール民法)#1|第1章 総則]]<br> [[第3編 債権 (コンメンタール民法)#1-7|第7節 有価証券]] |[[民法第520条の13]]<br>(記名式所持人払証券の譲渡) |[[民法第520条の15]]<br>(記名式所持人払証券の善意取得) }} {{stub}} [[category:民法|520の14]] [[category:民法 2017年改正|520の14]] mf2qv74cdps0hfv7iik4hg2wrw926kj 民法第520条の15 0 30203 206665 173168 2022-08-16T23:52:14Z Rhkmk 66092 wikitext text/x-wiki [[法学]]>[[民事法]]>[[コンメンタール民法]]>[[第3編 債権 (コンメンタール民法)]] ==条文== (記名式所持人払証券の善意取得) ;第520条の15 :何らかの事由により記名式所持人払証券の占有を失った者がある場合において、その所持人が前条の規定によりその権利を証明するときは、その所持人は、その証券を返還する義務を負わない。ただし、その所持人が悪意又は重大な過失によりその証券を取得したときは、この限りでない。 ==解説== 2017年改正にて新設。 類似の条文 *[[民法第520条の5|第520条の5]](指図証券の善意取得) ==参照条文== ==判例== ---- {{前後 |[[コンメンタール民法|民法]] |[[第3編 債権 (コンメンタール民法)|第3編 債権]]<br> [[第3編 債権 (コンメンタール民法)#1|第1章 総則]]<br> [[第3編 債権 (コンメンタール民法)#1-7|第7節 有価証券]] |[[民法第520条の14]]<br>(記名式所持人払証券の所持人の権利の推定) |[[民法第520条の16]]<br>(記名式所持人払証券の譲渡における債務者の抗弁の制限) }} {{stub}} [[category:民法|520の15]] [[category:民法 2017年改正|520の15]] eg2jx2tcx78r26hv29ce4owg0refphu 民法第520条の16 0 30204 206666 173169 2022-08-16T23:52:51Z Rhkmk 66092 wikitext text/x-wiki [[法学]]>[[民事法]]>[[コンメンタール民法]]>[[第3編 債権 (コンメンタール民法)]] ==条文== (記名式所持人払証券の譲渡における債務者の抗弁の制限) ;第520条の16 :記名式所持人払証券の債務者は、その証券に記載した事項及びその証券の性質から当然に生ずる結果を除き、その証券の譲渡前の債権者に対抗することができた事由をもって善意の譲受人に対抗することができない。 ==解説== 2017年改正にて新設。 類似の条文 *[[民法第520条の6|第520条の6]](指図証券の譲渡における債務者の抗弁の制限) ==参照条文== ==判例== ---- {{前後 |[[コンメンタール民法|民法]] |[[第3編 債権 (コンメンタール民法)|第3編 債権]]<br> [[第3編 債権 (コンメンタール民法)#1|第1章 総則]]<br> [[第3編 債権 (コンメンタール民法)#1-7|第7節 有価証券]] |[[民法第520条の15]]<br>(記名式所持人払証券の善意取得) |[[民法第520条の17]]<br>(記名式所持人払証券の質入れ) }} {{stub}} [[category:民法|520の16]] [[category:民法 2017年改正|520の16]] 6ily01qysxor9yconjhy8g4eym8pfhr 民法第520条の17 0 30205 206667 193081 2022-08-16T23:54:23Z Rhkmk 66092 wikitext text/x-wiki [[法学]]>[[民事法]]>[[コンメンタール民法]]>[[第3編 債権 (コンメンタール民法)]] ==条文== (記名式所持人払証券の質入れ) ;第520条の17 :[[民法第520条の13|第520条の13]]から[[民法第520条の16|前条]]までの規定は、記名式所持人払証券を目的とする質権の設定について準用する。 ==解説== 2017年改正にて新設。 *[[民法第520条の13|第520条の13]] *:→「証券の交付」が質権設定の効力要件となる。 *[[民法第520条の14|第520条の14]] *:→所持人は質権者と推定される。 *[[民法第520条の15|第520条の15]] *:→善意取得 *[[民法第520条の16|第520条の16]] *:→人的抗弁の制限。 類似の条文 *[[民法第520条の7|第520条の7]](指図証券の質入れ) *[[民法第520条の2|第520条の2]] *:→「裏書」及び「証券の交付」が質権設定の効力要件となる。 *[[民法第520条の3|第520条の3]] *:→手形法中裏書の方式に関する規定を準用する。 *::[[手形法第19条]] *[[民法第520条の4|第520条の4]] *:→「裏書」の連続ある所持人は質権者と推定される。 *[[民法第520条の5|第520条の5]] *:→善意取得 *[[民法第520条の6|第520条の6]] *:→人的抗弁の制限。 ==参照条文== ==判例== ---- {{前後 |[[コンメンタール民法|民法]] |[[第3編 債権 (コンメンタール民法)|第3編 債権]]<br> [[第3編 債権 (コンメンタール民法)#1|第1章 総則]]<br> [[第3編 債権 (コンメンタール民法)#1-7|第7節 有価証券]] |[[民法第520条の16]]<br>(記名式所持人払証券の譲渡における債務者の抗弁の制限) |[[民法第520条の18]]<br>(指図証券の規定の準用) }} {{stub}} [[category:民法|520の17]] [[category:民法 2017年改正|520の17]] r8tbf8jm6ox0mz8ot5zg6zjljd9vb64 Wikibooks:GUS2Wiki 4 35248 206658 206375 2022-08-16T12:15:17Z Alexis Jazz 56315 Updating gadget usage statistics from [[Special:GadgetUsage]] ([[phab:T121049]]) wikitext text/x-wiki {{#ifexist:Project:GUS2Wiki/top|{{/top}}|This page provides a historical record of [[Special:GadgetUsage]] through its page history. To get the data in CSV format, see wikitext. To customize this message or add categories, create [[/top]].}} 以下のデータは 2022-08-14T03:18:38Z に最終更新されたキャッシュです。 {| class="sortable wikitable" ! ガジェット !! data-sort-type="number" | 利用者の数 !! data-sort-type="number" | 活動中の利用者 |- |Blackskin || 7 || 0 |- |Navigation popups || 80 || 3 |- |UTCLiveClock || 44 || 1 |- |edittop || 53 || 1 |- |exlinks || 45 || 0 |- |removeAccessKeys || 7 || 0 |- |wikEd || 42 || 1 |} * [[特別:GadgetUsage]] * [[m:Meta:GUS2Wiki/Script|GUS2Wiki]] <!-- data in CSV format: Blackskin,7,0 Navigation popups,80,3 UTCLiveClock,44,1 edittop,53,1 exlinks,45,0 removeAccessKeys,7,0 wikEd,42,1 --> p1mn8y2d8kjarh6gh5ztv8ef8z83cv7 ChromeOS/Chromebrew 0 35280 206668 206634 2022-08-17T01:18:13Z Ef3 694 ChromeOS Flex の場合、grubの設定ファイルに cros_debug を追加します。 wikitext text/x-wiki Chromebrewは、[[ChromeOS]]で動作するソースビルド指向のパッケージ管理システムです。 ChromeOSは、Linuxカーネルの上にChromeウェブブラウザーを中心としてネットワーククライアント昨日を提供しますが、所謂GNU/Linuxのディストリビューションに観られるパッケージマネージャーを含まず、GNU/Linuxの環境を手に入れるには # Crostini {{---}} LXCコンテナー上で、GNU/Linuxディストリビューションを実行する(設定 > “Linux (Beta)” として知られる) # Crouton {{---}} chroot 環境で、GNU/Linuxディストリビューションを実行する(サポート終了しました) # Chromebrew {{---}} デベローパーモードのシェル環境に独自バイナリーをインストールする(GNU/Linuxディストリビューションとのパッケージ互換性はない) の3つがあります。 Chromebrewは、その名の通り[[w:Homebrew|Homebrew]]の影響を受けていますが、完全にRubyで記述され(Homebrewは一部 bash スクリプト)、ユーザーが書込みも実行もできるファイルシステムは <code>/usr/local</code> に限られるなどのChoromeOS固有の事情に適応しています。 Chromebrewは、仮想環境やchrootのオーバーヘッドはなく、ユーティリティーや共有ライブラリーなどChromeOSのものを使えるのでフットプリントは、この中で一番小さくなります。 Chromebrewは、BSD Unixの package source や ports collection の様にソースコードからのビルドをユーザーが気軽に行え、たとえばCコンパイラーに -march=native オプションを与えホスト環境のプロセッサーで実行可能な命令セットからコード生成をすることができるなど、資源の少ない環境にも好適です。 == インストール == インストールする前に、Chromebook をデベロッパーモードにする必要があります。 :Chromebook をデベロッパーモードにすると、工場出荷時の設定に戻されます。 :Chromebook をデベロッパーモードにすると、工場出荷時の設定に戻されます。 大切なので二回言いました。 === デベロッパーモード === Chromebookを「デベロッパーモード<ref>''Developer mode'' を「開発者モード」とする資料もありますが、定訳がないので「デベロッパーモード」とカタカナ表記にしました。</ref>」にすると、Chromebookのシステムファイルを変更できるなど、完全なルートアクセスを取得できます。 デベロッパーモードには、一部のファイルを変更したり、外部USBデバイスからChromebookを起動したりするなど他の使い道もあります。 ; デベローパーモードへ切替える方法 # Chromebookの電源をオフにする # ESC + 更新(F3)ボタンを押しながら、電源ボタンを押します。その後、電源ボタンを離します。 # リカバリー画面が表示されます。ここで、Ctrl + Dキーを押して開発者モードをオンにします。その後、数分待ちます。 === Chromebrewのオンザフライインストール === <ol> <li> まず、 https://chromebrew.github.io/ にアクセスして、インストール方法が変わっていないか確認してください。 <li> crosh を開きます。 * Chrome で、ctrl+alt+T で crosh を開きます。 <div style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:black solid 0.5rem"> Welcome to crosh, the Chrome OS developer shell. If you got here by mistake, don't panic! Just close this tab and carry on. Type 'help' for a list of commands. If you want to customize the look/behavior, you can use the options page.<br> Load it by using the Ctrl-Shift-P keyboard shortcut. <span style="color:yellow">crosh></span> </div> : Chrome に新しいタブが開き、上のような表示が現れます。 crosh> shell [ERROR:src/main.rs:184] ERROR: unknown command: shell :と表示された場合は、デベローパーモードになっていません。デベローパーモードへの切替え手順を確認しましょう<ref>ChromeOS Flex の場合、grubの設定ファイルに cros_debug を追加します。</ref>。 <li>shellの起動。 * croshのプロンプトで shell とタイプします <div style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:black solid 0.5rem"> <span style="color:yellow">crosh></span> shell<br> <span style="color:green">chronos@localhost</span> <span style="color:cyan">/ $</span> </div> : shell が、開きました。初期状態では bash です。 <li> インストールスクリプトのオンザフライ実行。 * chromebrew のインストールスクリプトをファイルに落とさず、そのまま bash の標準入力に流します。 <div style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:black solid 0.5rem"> <span style="color:green">chronos@localhost</span> <span style="color:cyan">/ $</span> curl -Ls git.io/vddgY | bash <pre style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:black solid 0.5rem"> Welcome to Chromebrew! Please enter the developer mode password We trust you have received the usual lecture from the local System Administrator. It usually boils down to these three things: #1) Respect the privacy of others. #2) Think before you type. #3) With great power comes great responsibility. Password: Doing initial setup for install in /usr/local. This may take a while if there are preexisting files in /usr/local... Downloading information for Bootstrap packages... [1/15]: https://raw.githubusercontent.com/chromebrew/chromebrew/master/packages/musl_zstd.rb --> musl_zstd.rb --_curl_--https://raw.githubusercontent.com/chromebrew/chromebrew/master/packages/musl_zstd.rb [2/15]: https://raw.githubusercontent.com/chromebrew/chromebrew/master/packages/pixz.rb --> pixz.rb --_curl_--https://raw.githubusercontent.com/chromebrew/chromebrew/master/packages/pixz.rb : : : </pre> </div> * しばらく基礎的なパッケージのダウンロードとインストールが続き... <div style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:black solid 0.5rem"> <pre style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:black solid 0.5rem"> . . ..,:;;;::'.. .':lllllllool,. ...cl;..... ,::;'. .'oc...;::::..0KKo. .'od: .:::::, lolc. .'lNMMMO ;ooc.,XMMWx;:;. .dMMMMMMXkMMMMxoMMMMMMMMO. .:O0NMMMMMMMMMM0MMMMMN0Oc. .:xdloddddddoXMMMk:x:.... .xMNOKX0OOOOxcodlcXMN0O0XKc. .OMXOKXOOOOOk;ol:OXMK...;N0. 'XMKOXXOOOOOk:docOKMW, .kW; .cMMKOXXOOOOOOOOOOO0MM; .lMc. .cMM00XKOOOOkkkkkkOOWMl. .cMo. .lMWO0XKOOOkkkkkkkkONMo. ;Wk. .oMNO0X0OOkkkkkkkkkOXMd..,oW0' .xMNO0X0OOkkkkkkkkkkXMWKXKOx;. .0MXOOOOOOkkkkkkkkkOKM0.. 'NMWNXXKK000000KKXNNMMX. .;okk0XNWWMMMMWWNKOkdc'. .....'cc:cc:''... ___ _ _ / (_)|\ |\\ | ||__ ,_ __ _ _ _ __ |/_ ,_ __ _ _ _ | |/ | / | / \/ |/ |/ | |_/ | \/ | |_/ /| | |\_ \___/| |_/ |_/\__/ | | |_/|__/\__/ |_/|__/ \_/ \_/ Edit /usr/local/etc/env.d/02-pager to change the default PAGER. more is used by default You may wish to edit the /usr/local/etc/env.d/01-editor file for an editor default. Chromebrew provides nano, vim and emacs as default TUI editor options. Chromebrew installed successfully and package lists updated. </pre> <span style="color:green">chronos@localhost</span> <span style="color:cyan">/ $</span> </div> :のようなアスキーアートとメッセージが表示されたら chromebrew のインストールは完了です。 </ol> === インストール結果の確認 === chromebrew のインストールが終わったら、基本的な動作を確認します。 * shellプロンプトで crew とタイプします(crew が chromebrew のコマンド名です) <div style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:black solid 0.5rem"> <span style="color:green">chronos@localhost</span> <span style="color:cyan">/ $</span> crew <pre style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:0;margin:0:text-indent:0"> Usage: crew autoremove [options] crew build [options] [-k|--keep] <name> ... crew const [options] [<name> ...] crew deps [options] [-t|--tree] [-b|--include-build-deps] [--exclude-buildessential] <name> ... crew download [options] <name> ... crew files [options] <name> ... crew help [<command>] crew install [options] [-k|--keep] [-s|--build-from-source] [-S|--recursive-build] <name> ... crew list [options] (available|installed|compatible|incompatible) crew postinstall [options] <name> ... crew reinstall [options] [-k|--keep] [-s|--build-from-source] [-S|--recursive-build] <name> ... crew remove [options] <name> ... crew search [options] [<name> ...] crew sysinfo [options] crew update [options] [<compatible>] crew upgrade [options] [-k|--keep] [-s|--build-from-source] [<name> ...] crew whatprovides [options] <pattern> ...</pre> <span style="color:green">chronos@localhost</span> <span style="color:cyan">/ $</span> crew sysinfo <pre style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:0;margin:0:text-indent:0"> - Architecture: `x86_64` (`x86_64`) - Kernel version: `4.14.282-19192-g19e8c55302db` - Chromebrew version: `1.24.0` - Chromebrew prefix: `/usr/local` - Chromebrew libdir: `/usr/local/lib64` - Last update in local repository: `e01f130: Edge 103.0.1264.77-1 => 104.0.1293.47-1 (#7254)` - OS variant: `Chrome OS` - OS version: `octopus-release/R104-14909.100.0` - OS channel: `stable-channel`</pre> </div> :サブコマンドとオプションの一覧が表示されます。 : sysinfo サブコマンドは、OSとchromebrew自身の情報を表示します。 :: 内容はバージョンによって異なります。 === パッケージのインストール === tree コマンドをインストールしてみます。 $ <b>crew install tree</b> tree: Tree is a recursive directory listing command that produces a depth indented listing of files, which is colorized ala dircolors if the LS_COLORS environment variable is set and output is to tty. http://mama.indstate.edu/users/ice/tree/ Version: 2.0.2 License: GPL-2 Performing pre-flight checks... Precompiled binary available, downloading... Cannot find cached archive. 😔 Will download. [####################################################################################################################################] 51.52 KB 100% Tree archive downloaded. Unpacking archive using 'tar', this may take a while... Performing pre-install... Performing install... Using rdfind to convert duplicate files to hard links. Now scanning ".", found 2 files. Now have 2 files in total. Removed 0 files due to nonunique device and inode. Total size is 177860 bytes or 174 KiB Removed 2 files due to unique sizes from list. 0 files left. Now eliminating candidates based on first bytes: removed 0 files from list. 0 files left. Now eliminating candidates based on last bytes: removed 0 files from list. 0 files left. Now eliminating candidates based on sha1 checksum: removed 0 files from list. 0 files left. It seems like you have 0 files that are not unique Totally, 0 B can be reduced. Now making hard links. Making 0 links. Tree installed! chronos@localhost /usr/local/lib/crew/packages $ <b>tree -d /usr/local/lib/crew/</b> /usr/local/lib/crew/ ├── bin ├── lib ├── packages └── tools 4 directories chronos@localhost /usr/local/lib/crew/packages $ treeはディレクトリー構造をツリー表示するコマンドで、階層構造の把握の役に立ちます。 crew install パッケージ名 の形式では、バイナリーパッケージがインストールされますが、chromebrew では同程度の手間でソースからインストールすることができます。 chronos@localhost /usr/local/lib/crew/packages $ <b>crew reinstall -s tree</b> tree: Tree is a recursive directory listing command that produces a depth indented listing of files, which is colorized ala dircolors if the LS_COLORS environment variable is set and output is to tty. Performing pre-flight checks... Downloading source... Archive found in cache Unpacking archive using 'tar', this may take a while... Building from source, this may take a while... gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o tree.o tree.c gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o unix.o unix.c gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o html.o html.c gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o xml.o xml.c gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o json.o json.c gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o hash.o hash.c gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o color.o color.c gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o file.o file.c gcc -o tree tree.o unix.o html.o xml.o json.o hash.o color.o file.o Preconfiguring package... install -d /usr/local/tmp/crew/dest/usr/local/bin install -d /usr/local/tmp/crew/dest/usr/local/share/man/man1 if [ -e tree ]; then \ install tree /usr/local/tmp/crew/dest/usr/local/bin/tree; \ fi install doc/tree.1 /usr/local/tmp/crew/dest/usr/local/share/man/man1/tree.1 Rename all *.la_tmp files back to *.la Checking for FHS3 compliance... Checking for conflicts with files from installed packages... Stripping libraries... Stripping binaries... Running patchelf Running patchelf to patch binaries for library paths Using rdfind to convert duplicate files to hard links. Now scanning ".", found 4 files. Now have 4 files in total. Removed 0 files due to nonunique device and inode. Total size is 95387 bytes or 93 KiB Removed 4 files due to unique sizes from list. 0 files left. Now eliminating candidates based on first bytes: removed 0 files from list. 0 files left. Now eliminating candidates based on last bytes: removed 0 files from list. 0 files left. Now eliminating candidates based on sha1 checksum: removed 0 files from list. 0 files left. It seems like you have 0 files that are not unique Totally, 0 B can be reduced. Now making hard links. Making 0 links. Removing since upgrade or reinstall... Tree removed! Performing pre-install... Performing install... Using rdfind to convert duplicate files to hard links. Now scanning ".", found 2 files. Now have 2 files in total. Removed 0 files due to nonunique device and inode. Total size is 95236 bytes or 93 KiB Removed 2 files due to unique sizes from list. 0 files left. Now eliminating candidates based on first bytes: removed 0 files from list. 0 files left. Now eliminating candidates based on last bytes: removed 0 files from list. 0 files left. Now eliminating candidates based on sha1 checksum: removed 0 files from list. 0 files left. It seems like you have 0 files that are not unique Totally, 0 B can be reduced. Now making hard links. Making 0 links. Tree installed! chronos@localhost /usr/local/lib/crew/packages $ :既にtreeパッケージはインストールされているので、 crew install が crew reinstall になっています(crew reinstall は、crew remove パッケージ名 したあと crew install と同義) :また、 -s オプションがついていることが違います。これが「ソースからビルドしてインストールする」指示で、依存パッケージのインストールやソースコードの取得を(必要であれば)確認を求めつつ実行します。 ==== バイナリーパッケージに対する、ソースコードからのビルドの得失 ==== ;短所:ネットワークから取得し展開するだけのバイナリーパッケージよりインストールに時間がかかる。 ;長所 :新しいコンパイラでコンパイルされるので、生成されるコードの質が高い。 :コンパイル条件を変えることで、LTOやPGOを使ったり、ターゲットCPUの命令セットに最適化することなどができる。 === システムとパッケージのアップデート === === パッケージのビルド === === パッケージの作り方 === == 脚註 == <references /> == 外部リンク == * 公式サイト {{---}} https://chromebrew.github.io/ * 公式リポジトリ {{---}} https://github.com/chromebrew/chromebrew.git dbmpqiey2r1m4w0vt1bj7u54kzn72tu 206671 206668 2022-08-17T04:24:14Z Ef3 694 /* Chromebrewのオンザフライインストール */ <pre style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:0;margin:0;padding:0"> wikitext text/x-wiki Chromebrewは、[[ChromeOS]]で動作するソースビルド指向のパッケージ管理システムです。 ChromeOSは、Linuxカーネルの上にChromeウェブブラウザーを中心としてネットワーククライアント昨日を提供しますが、所謂GNU/Linuxのディストリビューションに観られるパッケージマネージャーを含まず、GNU/Linuxの環境を手に入れるには # Crostini {{---}} LXCコンテナー上で、GNU/Linuxディストリビューションを実行する(設定 > “Linux (Beta)” として知られる) # Crouton {{---}} chroot 環境で、GNU/Linuxディストリビューションを実行する(サポート終了しました) # Chromebrew {{---}} デベローパーモードのシェル環境に独自バイナリーをインストールする(GNU/Linuxディストリビューションとのパッケージ互換性はない) の3つがあります。 Chromebrewは、その名の通り[[w:Homebrew|Homebrew]]の影響を受けていますが、完全にRubyで記述され(Homebrewは一部 bash スクリプト)、ユーザーが書込みも実行もできるファイルシステムは <code>/usr/local</code> に限られるなどのChoromeOS固有の事情に適応しています。 Chromebrewは、仮想環境やchrootのオーバーヘッドはなく、ユーティリティーや共有ライブラリーなどChromeOSのものを使えるのでフットプリントは、この中で一番小さくなります。 Chromebrewは、BSD Unixの package source や ports collection の様にソースコードからのビルドをユーザーが気軽に行え、たとえばCコンパイラーに -march=native オプションを与えホスト環境のプロセッサーで実行可能な命令セットからコード生成をすることができるなど、資源の少ない環境にも好適です。 == インストール == インストールする前に、Chromebook をデベロッパーモードにする必要があります。 :Chromebook をデベロッパーモードにすると、工場出荷時の設定に戻されます。 :Chromebook をデベロッパーモードにすると、工場出荷時の設定に戻されます。 大切なので二回言いました。 === デベロッパーモード === Chromebookを「デベロッパーモード<ref>''Developer mode'' を「開発者モード」とする資料もありますが、定訳がないので「デベロッパーモード」とカタカナ表記にしました。</ref>」にすると、Chromebookのシステムファイルを変更できるなど、完全なルートアクセスを取得できます。 デベロッパーモードには、一部のファイルを変更したり、外部USBデバイスからChromebookを起動したりするなど他の使い道もあります。 ; デベローパーモードへ切替える方法 # Chromebookの電源をオフにする # ESC + 更新(F3)ボタンを押しながら、電源ボタンを押します。その後、電源ボタンを離します。 # リカバリー画面が表示されます。ここで、Ctrl + Dキーを押して開発者モードをオンにします。その後、数分待ちます。 === Chromebrewのオンザフライインストール === <ol> <li> まず、 https://chromebrew.github.io/ にアクセスして、インストール方法が変わっていないか確認してください。 <li> crosh を開きます。 * Chrome で、ctrl+alt+T で crosh を開きます。 <div style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:black solid 0.5rem"> Welcome to crosh, the Chrome OS developer shell. If you got here by mistake, don't panic! Just close this tab and carry on. Type 'help' for a list of commands. If you want to customize the look/behavior, you can use the options page.<br> Load it by using the Ctrl-Shift-P keyboard shortcut. <span style="color:yellow">crosh></span> </div> : Chrome に新しいタブが開き、上のような表示が現れます。 : : もし、 <div style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:black solid 0.5rem"> <span style="color:yellow">crosh></span> shell<br> [ERROR:src/main.rs:184] ERROR: unknown command: shell </div> :と表示された場合は、デベローパーモードになっていません。デベローパーモードへの切替え手順を確認しましょう<ref>ChromeOS Flex の場合、grubの設定ファイルに cros_debug を追加します。</ref>。 <li>shellの起動。 * croshのプロンプトで shell とタイプします <div style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:black solid 0.5rem"> <span style="color:yellow">crosh></span> shell<br> <span style="color:green">chronos@localhost</span> <span style="color:cyan">/ $</span> </div> : shell が、開きました。初期状態では bash です。 <li> インストールスクリプトのオンザフライ実行。 * chromebrew のインストールスクリプトをファイルに落とさず、そのまま bash の標準入力に流します。 <div style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:black solid 0.5rem"> <span style="color:green">chronos@localhost</span> <span style="color:cyan">/ $</span> curl -Ls git.io/vddgY | bash <pre style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:0;margin:0;padding:0"> Welcome to Chromebrew! Please enter the developer mode password We trust you have received the usual lecture from the local System Administrator. It usually boils down to these three things: #1) Respect the privacy of others. #2) Think before you type. #3) With great power comes great responsibility. Password: Doing initial setup for install in /usr/local. This may take a while if there are preexisting files in /usr/local... Downloading information for Bootstrap packages... [1/15]: https://raw.githubusercontent.com/chromebrew/chromebrew/master/packages/musl_zstd.rb --> musl_zstd.rb --_curl_--https://raw.githubusercontent.com/chromebrew/chromebrew/master/packages/musl_zstd.rb [2/15]: https://raw.githubusercontent.com/chromebrew/chromebrew/master/packages/pixz.rb --> pixz.rb --_curl_--https://raw.githubusercontent.com/chromebrew/chromebrew/master/packages/pixz.rb : : : </pre> </div> * しばらく基礎的なパッケージのダウンロードとインストールが続き... <div style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:black solid 0.5rem"> <pre style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:0;margin:0;padding:0"> . . ..,:;;;::'.. .':lllllllool,. ...cl;..... ,::;'. .'oc...;::::..0KKo. .'od: .:::::, lolc. .'lNMMMO ;ooc.,XMMWx;:;. .dMMMMMMXkMMMMxoMMMMMMMMO. .:O0NMMMMMMMMMM0MMMMMN0Oc. .:xdloddddddoXMMMk:x:.... .xMNOKX0OOOOxcodlcXMN0O0XKc. .OMXOKXOOOOOk;ol:OXMK...;N0. 'XMKOXXOOOOOk:docOKMW, .kW; .cMMKOXXOOOOOOOOOOO0MM; .lMc. .cMM00XKOOOOkkkkkkOOWMl. .cMo. .lMWO0XKOOOkkkkkkkkONMo. ;Wk. .oMNO0X0OOkkkkkkkkkOXMd..,oW0' .xMNO0X0OOkkkkkkkkkkXMWKXKOx;. .0MXOOOOOOkkkkkkkkkOKM0.. 'NMWNXXKK000000KKXNNMMX. .;okk0XNWWMMMMWWNKOkdc'. .....'cc:cc:''... ___ _ _ / (_)|\ |\\ | ||__ ,_ __ _ _ _ __ |/_ ,_ __ _ _ _ | |/ | / | / \/ |/ |/ | |_/ | \/ | |_/ /| | |\_ \___/| |_/ |_/\__/ | | |_/|__/\__/ |_/|__/ \_/ \_/ Edit /usr/local/etc/env.d/02-pager to change the default PAGER. more is used by default You may wish to edit the /usr/local/etc/env.d/01-editor file for an editor default. Chromebrew provides nano, vim and emacs as default TUI editor options. Chromebrew installed successfully and package lists updated. </pre> <span style="color:green">chronos@localhost</span> <span style="color:cyan">/ $</span> </div> :のようなアスキーアートとメッセージが表示されたら chromebrew のインストールは完了です。 </ol> === インストール結果の確認 === chromebrew のインストールが終わったら、基本的な動作を確認します。 * shellプロンプトで crew とタイプします(crew が chromebrew のコマンド名です) <div style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:black solid 0.5rem"> <span style="color:green">chronos@localhost</span> <span style="color:cyan">/ $</span> crew <pre style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:0;margin:0:text-indent:0"> Usage: crew autoremove [options] crew build [options] [-k|--keep] <name> ... crew const [options] [<name> ...] crew deps [options] [-t|--tree] [-b|--include-build-deps] [--exclude-buildessential] <name> ... crew download [options] <name> ... crew files [options] <name> ... crew help [<command>] crew install [options] [-k|--keep] [-s|--build-from-source] [-S|--recursive-build] <name> ... crew list [options] (available|installed|compatible|incompatible) crew postinstall [options] <name> ... crew reinstall [options] [-k|--keep] [-s|--build-from-source] [-S|--recursive-build] <name> ... crew remove [options] <name> ... crew search [options] [<name> ...] crew sysinfo [options] crew update [options] [<compatible>] crew upgrade [options] [-k|--keep] [-s|--build-from-source] [<name> ...] crew whatprovides [options] <pattern> ...</pre> <span style="color:green">chronos@localhost</span> <span style="color:cyan">/ $</span> crew sysinfo <pre style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:0;margin:0:text-indent:0"> - Architecture: `x86_64` (`x86_64`) - Kernel version: `4.14.282-19192-g19e8c55302db` - Chromebrew version: `1.24.0` - Chromebrew prefix: `/usr/local` - Chromebrew libdir: `/usr/local/lib64` - Last update in local repository: `e01f130: Edge 103.0.1264.77-1 => 104.0.1293.47-1 (#7254)` - OS variant: `Chrome OS` - OS version: `octopus-release/R104-14909.100.0` - OS channel: `stable-channel`</pre> </div> :サブコマンドとオプションの一覧が表示されます。 : sysinfo サブコマンドは、OSとchromebrew自身の情報を表示します。 :: 内容はバージョンによって異なります。 === パッケージのインストール === tree コマンドをインストールしてみます。 $ <b>crew install tree</b> tree: Tree is a recursive directory listing command that produces a depth indented listing of files, which is colorized ala dircolors if the LS_COLORS environment variable is set and output is to tty. http://mama.indstate.edu/users/ice/tree/ Version: 2.0.2 License: GPL-2 Performing pre-flight checks... Precompiled binary available, downloading... Cannot find cached archive. 😔 Will download. [####################################################################################################################################] 51.52 KB 100% Tree archive downloaded. Unpacking archive using 'tar', this may take a while... Performing pre-install... Performing install... Using rdfind to convert duplicate files to hard links. Now scanning ".", found 2 files. Now have 2 files in total. Removed 0 files due to nonunique device and inode. Total size is 177860 bytes or 174 KiB Removed 2 files due to unique sizes from list. 0 files left. Now eliminating candidates based on first bytes: removed 0 files from list. 0 files left. Now eliminating candidates based on last bytes: removed 0 files from list. 0 files left. Now eliminating candidates based on sha1 checksum: removed 0 files from list. 0 files left. It seems like you have 0 files that are not unique Totally, 0 B can be reduced. Now making hard links. Making 0 links. Tree installed! chronos@localhost /usr/local/lib/crew/packages $ <b>tree -d /usr/local/lib/crew/</b> /usr/local/lib/crew/ ├── bin ├── lib ├── packages └── tools 4 directories chronos@localhost /usr/local/lib/crew/packages $ treeはディレクトリー構造をツリー表示するコマンドで、階層構造の把握の役に立ちます。 crew install パッケージ名 の形式では、バイナリーパッケージがインストールされますが、chromebrew では同程度の手間でソースからインストールすることができます。 chronos@localhost /usr/local/lib/crew/packages $ <b>crew reinstall -s tree</b> tree: Tree is a recursive directory listing command that produces a depth indented listing of files, which is colorized ala dircolors if the LS_COLORS environment variable is set and output is to tty. Performing pre-flight checks... Downloading source... Archive found in cache Unpacking archive using 'tar', this may take a while... Building from source, this may take a while... gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o tree.o tree.c gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o unix.o unix.c gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o html.o html.c gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o xml.o xml.c gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o json.o json.c gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o hash.o hash.c gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o color.o color.c gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o file.o file.c gcc -o tree tree.o unix.o html.o xml.o json.o hash.o color.o file.o Preconfiguring package... install -d /usr/local/tmp/crew/dest/usr/local/bin install -d /usr/local/tmp/crew/dest/usr/local/share/man/man1 if [ -e tree ]; then \ install tree /usr/local/tmp/crew/dest/usr/local/bin/tree; \ fi install doc/tree.1 /usr/local/tmp/crew/dest/usr/local/share/man/man1/tree.1 Rename all *.la_tmp files back to *.la Checking for FHS3 compliance... Checking for conflicts with files from installed packages... Stripping libraries... Stripping binaries... Running patchelf Running patchelf to patch binaries for library paths Using rdfind to convert duplicate files to hard links. Now scanning ".", found 4 files. Now have 4 files in total. Removed 0 files due to nonunique device and inode. Total size is 95387 bytes or 93 KiB Removed 4 files due to unique sizes from list. 0 files left. Now eliminating candidates based on first bytes: removed 0 files from list. 0 files left. Now eliminating candidates based on last bytes: removed 0 files from list. 0 files left. Now eliminating candidates based on sha1 checksum: removed 0 files from list. 0 files left. It seems like you have 0 files that are not unique Totally, 0 B can be reduced. Now making hard links. Making 0 links. Removing since upgrade or reinstall... Tree removed! Performing pre-install... Performing install... Using rdfind to convert duplicate files to hard links. Now scanning ".", found 2 files. Now have 2 files in total. Removed 0 files due to nonunique device and inode. Total size is 95236 bytes or 93 KiB Removed 2 files due to unique sizes from list. 0 files left. Now eliminating candidates based on first bytes: removed 0 files from list. 0 files left. Now eliminating candidates based on last bytes: removed 0 files from list. 0 files left. Now eliminating candidates based on sha1 checksum: removed 0 files from list. 0 files left. It seems like you have 0 files that are not unique Totally, 0 B can be reduced. Now making hard links. Making 0 links. Tree installed! chronos@localhost /usr/local/lib/crew/packages $ :既にtreeパッケージはインストールされているので、 crew install が crew reinstall になっています(crew reinstall は、crew remove パッケージ名 したあと crew install と同義) :また、 -s オプションがついていることが違います。これが「ソースからビルドしてインストールする」指示で、依存パッケージのインストールやソースコードの取得を(必要であれば)確認を求めつつ実行します。 ==== バイナリーパッケージに対する、ソースコードからのビルドの得失 ==== ;短所:ネットワークから取得し展開するだけのバイナリーパッケージよりインストールに時間がかかる。 ;長所 :新しいコンパイラでコンパイルされるので、生成されるコードの質が高い。 :コンパイル条件を変えることで、LTOやPGOを使ったり、ターゲットCPUの命令セットに最適化することなどができる。 === システムとパッケージのアップデート === === パッケージのビルド === === パッケージの作り方 === == 脚註 == <references /> == 外部リンク == * 公式サイト {{---}} https://chromebrew.github.io/ * 公式リポジトリ {{---}} https://github.com/chromebrew/chromebrew.git 6ue7zrkysckp9ci35o8xv7a4q2666ue 206672 206671 2022-08-17T04:52:30Z Ef3 694 /*システムとパッケージのアップデート*/crew 自身のアップデート chronos@localhost ~ $ crew update crewを更新します。 これはcrew本体のみをアップデートします。 パッケージのアップデート chronos@localhost ~ $ crew upgrade パッケージのアップデートを行います。 使用法: crew upgrade [-v|--verbose] [-s|--build-from-source] <package1> [<package2> ...]。 パッケージが省略された場合、全てのパッケージが更新されます。 そうでなければ、特定のパッケージが更新されます。 s` または `--build-from-source` がある場合、パッケージはバイナリでアップグレードされるのではなく、コンパイルされます。 v` または `--verbose` を指定すると、特別な情報が表示されます。 wikitext text/x-wiki Chromebrewは、[[ChromeOS]]で動作するソースビルド指向のパッケージ管理システムです。 ChromeOSは、Linuxカーネルの上にChromeウェブブラウザーを中心としてネットワーククライアント昨日を提供しますが、所謂GNU/Linuxのディストリビューションに観られるパッケージマネージャーを含まず、GNU/Linuxの環境を手に入れるには # Crostini {{---}} LXCコンテナー上で、GNU/Linuxディストリビューションを実行する(設定 > “Linux (Beta)” として知られる) # Crouton {{---}} chroot 環境で、GNU/Linuxディストリビューションを実行する(サポート終了しました) # Chromebrew {{---}} デベローパーモードのシェル環境に独自バイナリーをインストールする(GNU/Linuxディストリビューションとのパッケージ互換性はない) の3つがあります。 Chromebrewは、その名の通り[[w:Homebrew|Homebrew]]の影響を受けていますが、完全にRubyで記述され(Homebrewは一部 bash スクリプト)、ユーザーが書込みも実行もできるファイルシステムは <code>/usr/local</code> に限られるなどのChoromeOS固有の事情に適応しています。 Chromebrewは、仮想環境やchrootのオーバーヘッドはなく、ユーティリティーや共有ライブラリーなどChromeOSのものを使えるのでフットプリントは、この中で一番小さくなります。 Chromebrewは、BSD Unixの package source や ports collection の様にソースコードからのビルドをユーザーが気軽に行え、たとえばCコンパイラーに -march=native オプションを与えホスト環境のプロセッサーで実行可能な命令セットからコード生成をすることができるなど、資源の少ない環境にも好適です。 == インストール == インストールする前に、Chromebook をデベロッパーモードにする必要があります。 :Chromebook をデベロッパーモードにすると、工場出荷時の設定に戻されます。 :Chromebook をデベロッパーモードにすると、工場出荷時の設定に戻されます。 大切なので二回言いました。 === デベロッパーモード === Chromebookを「デベロッパーモード<ref>''Developer mode'' を「開発者モード」とする資料もありますが、定訳がないので「デベロッパーモード」とカタカナ表記にしました。</ref>」にすると、Chromebookのシステムファイルを変更できるなど、完全なルートアクセスを取得できます。 デベロッパーモードには、一部のファイルを変更したり、外部USBデバイスからChromebookを起動したりするなど他の使い道もあります。 ; デベローパーモードへ切替える方法 # Chromebookの電源をオフにする # ESC + 更新(F3)ボタンを押しながら、電源ボタンを押します。その後、電源ボタンを離します。 # リカバリー画面が表示されます。ここで、Ctrl + Dキーを押して開発者モードをオンにします。その後、数分待ちます。 === Chromebrewのオンザフライインストール === <ol> <li> まず、 https://chromebrew.github.io/ にアクセスして、インストール方法が変わっていないか確認してください。 <li> crosh を開きます。 * Chrome で、ctrl+alt+T で crosh を開きます。 <div style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:black solid 0.5rem"> Welcome to crosh, the Chrome OS developer shell. If you got here by mistake, don't panic! Just close this tab and carry on. Type 'help' for a list of commands. If you want to customize the look/behavior, you can use the options page.<br> Load it by using the Ctrl-Shift-P keyboard shortcut. <span style="color:yellow">crosh></span> </div> : Chrome に新しいタブが開き、上のような表示が現れます。 : : もし、 <div style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:black solid 0.5rem"> <span style="color:yellow">crosh></span> shell<br> [ERROR:src/main.rs:184] ERROR: unknown command: shell </div> :と表示された場合は、デベローパーモードになっていません。デベローパーモードへの切替え手順を確認しましょう<ref>ChromeOS Flex の場合、grubの設定ファイルに cros_debug を追加します。</ref>。 <li>shellの起動。 * croshのプロンプトで shell とタイプします <div style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:black solid 0.5rem"> <span style="color:yellow">crosh></span> shell<br> <span style="color:green">chronos@localhost</span> <span style="color:cyan">/ $</span> </div> : shell が、開きました。初期状態では bash です。 <li> インストールスクリプトのオンザフライ実行。 * chromebrew のインストールスクリプトをファイルに落とさず、そのまま bash の標準入力に流します。 <div style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:black solid 0.5rem"> <span style="color:green">chronos@localhost</span> <span style="color:cyan">/ $</span> curl -Ls git.io/vddgY | bash <pre style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:0;margin:0;padding:0"> Welcome to Chromebrew! Please enter the developer mode password We trust you have received the usual lecture from the local System Administrator. It usually boils down to these three things: #1) Respect the privacy of others. #2) Think before you type. #3) With great power comes great responsibility. Password: Doing initial setup for install in /usr/local. This may take a while if there are preexisting files in /usr/local... Downloading information for Bootstrap packages... [1/15]: https://raw.githubusercontent.com/chromebrew/chromebrew/master/packages/musl_zstd.rb --> musl_zstd.rb --_curl_--https://raw.githubusercontent.com/chromebrew/chromebrew/master/packages/musl_zstd.rb [2/15]: https://raw.githubusercontent.com/chromebrew/chromebrew/master/packages/pixz.rb --> pixz.rb --_curl_--https://raw.githubusercontent.com/chromebrew/chromebrew/master/packages/pixz.rb : : : </pre> </div> * しばらく基礎的なパッケージのダウンロードとインストールが続き... <div style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:black solid 0.5rem"> <pre style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:0;margin:0;padding:0"> . . ..,:;;;::'.. .':lllllllool,. ...cl;..... ,::;'. .'oc...;::::..0KKo. .'od: .:::::, lolc. .'lNMMMO ;ooc.,XMMWx;:;. .dMMMMMMXkMMMMxoMMMMMMMMO. .:O0NMMMMMMMMMM0MMMMMN0Oc. .:xdloddddddoXMMMk:x:.... .xMNOKX0OOOOxcodlcXMN0O0XKc. .OMXOKXOOOOOk;ol:OXMK...;N0. 'XMKOXXOOOOOk:docOKMW, .kW; .cMMKOXXOOOOOOOOOOO0MM; .lMc. .cMM00XKOOOOkkkkkkOOWMl. .cMo. .lMWO0XKOOOkkkkkkkkONMo. ;Wk. .oMNO0X0OOkkkkkkkkkOXMd..,oW0' .xMNO0X0OOkkkkkkkkkkXMWKXKOx;. .0MXOOOOOOkkkkkkkkkOKM0.. 'NMWNXXKK000000KKXNNMMX. .;okk0XNWWMMMMWWNKOkdc'. .....'cc:cc:''... ___ _ _ / (_)|\ |\\ | ||__ ,_ __ _ _ _ __ |/_ ,_ __ _ _ _ | |/ | / | / \/ |/ |/ | |_/ | \/ | |_/ /| | |\_ \___/| |_/ |_/\__/ | | |_/|__/\__/ |_/|__/ \_/ \_/ Edit /usr/local/etc/env.d/02-pager to change the default PAGER. more is used by default You may wish to edit the /usr/local/etc/env.d/01-editor file for an editor default. Chromebrew provides nano, vim and emacs as default TUI editor options. Chromebrew installed successfully and package lists updated. </pre> <span style="color:green">chronos@localhost</span> <span style="color:cyan">/ $</span> </div> :のようなアスキーアートとメッセージが表示されたら chromebrew のインストールは完了です。 </ol> === インストール結果の確認 === chromebrew のインストールが終わったら、基本的な動作を確認します。 * shellプロンプトで crew とタイプします(crew が chromebrew のコマンド名です) <div style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:black solid 0.5rem"> <span style="color:green">chronos@localhost</span> <span style="color:cyan">/ $</span> crew <pre style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:0;margin:0;padding:0"> Usage: crew autoremove [options] crew build [options] [-k|--keep] <name> ... crew const [options] [<name> ...] crew deps [options] [-t|--tree] [-b|--include-build-deps] [--exclude-buildessential] <name> ... crew download [options] <name> ... crew files [options] <name> ... crew help [<command>] crew install [options] [-k|--keep] [-s|--build-from-source] [-S|--recursive-build] <name> ... crew list [options] (available|installed|compatible|incompatible) crew postinstall [options] <name> ... crew reinstall [options] [-k|--keep] [-s|--build-from-source] [-S|--recursive-build] <name> ... crew remove [options] <name> ... crew search [options] [<name> ...] crew sysinfo [options] crew update [options] [<compatible>] crew upgrade [options] [-k|--keep] [-s|--build-from-source] [<name> ...] crew whatprovides [options] <pattern> ...</pre> <span style="color:green">chronos@localhost</span> <span style="color:cyan">/ $</span> crew sysinfo <pre style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:0;margin:0;padding:0"> - Architecture: `x86_64` (`x86_64`) - Kernel version: `4.14.282-19192-g19e8c55302db` - Chromebrew version: `1.24.0` - Chromebrew prefix: `/usr/local` - Chromebrew libdir: `/usr/local/lib64` - Last update in local repository: `e01f130: Edge 103.0.1264.77-1 => 104.0.1293.47-1 (#7254)` - OS variant: `Chrome OS` - OS version: `octopus-release/R104-14909.100.0` - OS channel: `stable-channel`</pre> </div> :サブコマンドとオプションの一覧が表示されます。 : sysinfo サブコマンドは、OSとchromebrew自身の情報を表示します。 :: 内容はバージョンによって異なります。 === パッケージのインストール === tree コマンドをインストールしてみます。 :<syntaxhighlight lang=console> $ crew install tree tree: Tree is a recursive directory listing command that produces a depth indented listing of files, which is colorized ala dircolors if the LS_COLORS environment variable is set and output is to tty. http://mama.indstate.edu/users/ice/tree/ Version: 2.0.2 License: GPL-2 Performing pre-flight checks... Precompiled binary available, downloading... Cannot find cached archive. 😔 Will download. [####################################################################################################################################] 51.52 KB 100% Tree archive downloaded. Unpacking archive using 'tar', this may take a while... Performing pre-install... Performing install... Using rdfind to convert duplicate files to hard links. Now scanning ".", found 2 files. Now have 2 files in total. Removed 0 files due to nonunique device and inode. Total size is 177860 bytes or 174 KiB Removed 2 files due to unique sizes from list. 0 files left. Now eliminating candidates based on first bytes: removed 0 files from list. 0 files left. Now eliminating candidates based on last bytes: removed 0 files from list. 0 files left. Now eliminating candidates based on sha1 checksum: removed 0 files from list. 0 files left. It seems like you have 0 files that are not unique Totally, 0 B can be reduced. Now making hard links. Making 0 links. Tree installed! chronos@localhost ~ $ tree -d /usr/local/lib/crew/ /usr/local/lib/crew/ ├── bin ├── lib ├── packages └── tools 4 directories chronos@localhost ~ $ </syntaxhighlight> treeはディレクトリー構造をツリー表示するコマンドで、階層構造の把握の役に立ちます。 :<syntaxhighlight lang=text> crew install パッケージ名 </syntaxhighlight> の形式では、バイナリーパッケージがインストールされますが、chromebrew では同程度の手間でソースからインストールすることができます。 :<syntaxhighlight lang=console> chronos@localhost ~ $ crew reinstall -s tree tree: Tree is a recursive directory listing command that produces a depth indented listing of files, which is colorized ala dircolors if the LS_COLORS environment variable is set and output is to tty. Performing pre-flight checks... Downloading source... Archive found in cache Unpacking archive using 'tar', this may take a while... Building from source, this may take a while... gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o tree.o tree.c gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o unix.o unix.c gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o html.o html.c gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o xml.o xml.c gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o json.o json.c gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o hash.o hash.c gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o color.o color.c gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o file.o file.c gcc -o tree tree.o unix.o html.o xml.o json.o hash.o color.o file.o Preconfiguring package... install -d /usr/local/tmp/crew/dest/usr/local/bin install -d /usr/local/tmp/crew/dest/usr/local/share/man/man1 if [ -e tree ]; then \ install tree /usr/local/tmp/crew/dest/usr/local/bin/tree; \ fi install doc/tree.1 /usr/local/tmp/crew/dest/usr/local/share/man/man1/tree.1 Rename all *.la_tmp files back to *.la Checking for FHS3 compliance... Checking for conflicts with files from installed packages... Stripping libraries... Stripping binaries... Running patchelf Running patchelf to patch binaries for library paths Using rdfind to convert duplicate files to hard links. Now scanning ".", found 4 files. Now have 4 files in total. Removed 0 files due to nonunique device and inode. Total size is 95387 bytes or 93 KiB Removed 4 files due to unique sizes from list. 0 files left. Now eliminating candidates based on first bytes: removed 0 files from list. 0 files left. Now eliminating candidates based on last bytes: removed 0 files from list. 0 files left. Now eliminating candidates based on sha1 checksum: removed 0 files from list. 0 files left. It seems like you have 0 files that are not unique Totally, 0 B can be reduced. Now making hard links. Making 0 links. Removing since upgrade or reinstall... Tree removed! Performing pre-install... Performing install... Using rdfind to convert duplicate files to hard links. Now scanning ".", found 2 files. Now have 2 files in total. Removed 0 files due to nonunique device and inode. Total size is 95236 bytes or 93 KiB Removed 2 files due to unique sizes from list. 0 files left. Now eliminating candidates based on first bytes: removed 0 files from list. 0 files left. Now eliminating candidates based on last bytes: removed 0 files from list. 0 files left. Now eliminating candidates based on sha1 checksum: removed 0 files from list. 0 files left. It seems like you have 0 files that are not unique Totally, 0 B can be reduced. Now making hard links. Making 0 links. Tree installed! chronos@localhost ~ $ </syntaxhighlight> :既にtreeパッケージはインストールされているので、 crew install が crew reinstall になっています(crew reinstall は、crew remove パッケージ名 したあと crew install と同義) :また、 -s オプションがついていることが違います。これが「ソースからビルドしてインストールする」指示で、依存パッケージのインストールやソースコードの取得を(必要であれば)確認を求めつつ実行します。 ==== バイナリーパッケージに対する、ソースコードからのビルドの得失 ==== ;短所:ネットワークから取得し展開するだけのバイナリーパッケージよりインストールに時間がかかる。 ;長所 :新しいコンパイラでコンパイルされるので、生成されるコードの質が高い。 :コンパイル条件を変えることで、LTOやPGOを使ったり、ターゲットCPUの命令セットに最適化することなどができる。 === システムとパッケージのアップデート === ;crew 自身のアップデート:<syntaxhighlight lang=console> chronos@localhost ~ $ crew update </syntaxhighlight> :crewを更新します。 :これはcrew本体のみをアップデートします。 ;パッケージのアップデート:<syntaxhighlight lang=console> chronos@localhost ~ $ crew upgrade </syntaxhighlight> :パッケージのアップデートを行います。 ::使用法: crew upgrade [-v|--verbose] [-s|--build-from-source] <package1> [<package2> ...] ::パッケージが省略された場合、全てのパッケージが更新されます。 そうでなければ、特定のパッケージが更新されます。 ::-s または --build-from-source を指定すると、パッケージはバイナリでアップグレードされるのではなく、コンパイルされます。 ::-v または --verbose を指定すると、より多くの情報が表示されます。 === パッケージの作り方 === == 脚註 == <references /> == 外部リンク == * 公式サイト {{---}} https://chromebrew.github.io/ * 公式リポジトリ {{---}} https://github.com/chromebrew/chromebrew.git pqqtrplks1ncn2ecqytywpthbujytx4 206673 206672 2022-08-17T05:31:18Z Ef3 694 /* パッケージの作り方 */ crew のパッケージのレシピは、/usr/local/lib/crew/patches/ にある1つのrubyスクリプトです。 wikitext text/x-wiki Chromebrewは、[[ChromeOS]]で動作するソースビルド指向のパッケージ管理システムです。 ChromeOSは、Linuxカーネルの上にChromeウェブブラウザーを中心としてネットワーククライアント昨日を提供しますが、所謂GNU/Linuxのディストリビューションに観られるパッケージマネージャーを含まず、GNU/Linuxの環境を手に入れるには # Crostini {{---}} LXCコンテナー上で、GNU/Linuxディストリビューションを実行する(設定 > “Linux (Beta)” として知られる) # Crouton {{---}} chroot 環境で、GNU/Linuxディストリビューションを実行する(サポート終了しました) # Chromebrew {{---}} デベローパーモードのシェル環境に独自バイナリーをインストールする(GNU/Linuxディストリビューションとのパッケージ互換性はない) の3つがあります。 Chromebrewは、その名の通り[[w:Homebrew|Homebrew]]の影響を受けていますが、完全にRubyで記述され(Homebrewは一部 bash スクリプト)、ユーザーが書込みも実行もできるファイルシステムは <code>/usr/local</code> に限られるなどのChoromeOS固有の事情に適応しています。 Chromebrewは、仮想環境やchrootのオーバーヘッドはなく、ユーティリティーや共有ライブラリーなどChromeOSのものを使えるのでフットプリントは、この中で一番小さくなります。 Chromebrewは、BSD Unixの package source や ports collection の様にソースコードからのビルドをユーザーが気軽に行え、たとえばCコンパイラーに -march=native オプションを与えホスト環境のプロセッサーで実行可能な命令セットからコード生成をすることができるなど、資源の少ない環境にも好適です。 == インストール == インストールする前に、Chromebook をデベロッパーモードにする必要があります。 :Chromebook をデベロッパーモードにすると、工場出荷時の設定に戻されます。 :Chromebook をデベロッパーモードにすると、工場出荷時の設定に戻されます。 大切なので二回言いました。 === デベロッパーモード === Chromebookを「デベロッパーモード<ref>''Developer mode'' を「開発者モード」とする資料もありますが、定訳がないので「デベロッパーモード」とカタカナ表記にしました。</ref>」にすると、Chromebookのシステムファイルを変更できるなど、完全なルートアクセスを取得できます。 デベロッパーモードには、一部のファイルを変更したり、外部USBデバイスからChromebookを起動したりするなど他の使い道もあります。 ; デベローパーモードへ切替える方法 # Chromebookの電源をオフにする # ESC + 更新(F3)ボタンを押しながら、電源ボタンを押します。その後、電源ボタンを離します。 # リカバリー画面が表示されます。ここで、Ctrl + Dキーを押して開発者モードをオンにします。その後、数分待ちます。 === Chromebrewのオンザフライインストール === <ol> <li> まず、 https://chromebrew.github.io/ にアクセスして、インストール方法が変わっていないか確認してください。 <li> crosh を開きます。 * Chrome で、ctrl+alt+T で crosh を開きます。 <div style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:black solid 0.5rem"> Welcome to crosh, the Chrome OS developer shell. If you got here by mistake, don't panic! Just close this tab and carry on. Type 'help' for a list of commands. If you want to customize the look/behavior, you can use the options page.<br> Load it by using the Ctrl-Shift-P keyboard shortcut. <span style="color:yellow">crosh></span> </div> : Chrome に新しいタブが開き、上のような表示が現れます。 : : もし、 <div style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:black solid 0.5rem"> <span style="color:yellow">crosh></span> shell<br> [ERROR:src/main.rs:184] ERROR: unknown command: shell </div> :と表示された場合は、デベローパーモードになっていません。デベローパーモードへの切替え手順を確認しましょう<ref>ChromeOS Flex の場合、grubの設定ファイルに cros_debug を追加します。</ref>。 <li>shellの起動。 * croshのプロンプトで shell とタイプします <div style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:black solid 0.5rem"> <span style="color:yellow">crosh></span> shell<br> <span style="color:green">chronos@localhost</span> <span style="color:cyan">/ $</span> </div> : shell が、開きました。初期状態では bash です。 <li> インストールスクリプトのオンザフライ実行。 * chromebrew のインストールスクリプトをファイルに落とさず、そのまま bash の標準入力に流します。 <div style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:black solid 0.5rem"> <span style="color:green">chronos@localhost</span> <span style="color:cyan">/ $</span> curl -Ls git.io/vddgY | bash <pre style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:0;margin:0;padding:0"> Welcome to Chromebrew! Please enter the developer mode password We trust you have received the usual lecture from the local System Administrator. It usually boils down to these three things: #1) Respect the privacy of others. #2) Think before you type. #3) With great power comes great responsibility. Password: Doing initial setup for install in /usr/local. This may take a while if there are preexisting files in /usr/local... Downloading information for Bootstrap packages... [1/15]: https://raw.githubusercontent.com/chromebrew/chromebrew/master/packages/musl_zstd.rb --> musl_zstd.rb --_curl_--https://raw.githubusercontent.com/chromebrew/chromebrew/master/packages/musl_zstd.rb [2/15]: https://raw.githubusercontent.com/chromebrew/chromebrew/master/packages/pixz.rb --> pixz.rb --_curl_--https://raw.githubusercontent.com/chromebrew/chromebrew/master/packages/pixz.rb : : : </pre> </div> * しばらく基礎的なパッケージのダウンロードとインストールが続き... <div style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:black solid 0.5rem"> <pre style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:0;margin:0;padding:0"> . . ..,:;;;::'.. .':lllllllool,. ...cl;..... ,::;'. .'oc...;::::..0KKo. .'od: .:::::, lolc. .'lNMMMO ;ooc.,XMMWx;:;. .dMMMMMMXkMMMMxoMMMMMMMMO. .:O0NMMMMMMMMMM0MMMMMN0Oc. .:xdloddddddoXMMMk:x:.... .xMNOKX0OOOOxcodlcXMN0O0XKc. .OMXOKXOOOOOk;ol:OXMK...;N0. 'XMKOXXOOOOOk:docOKMW, .kW; .cMMKOXXOOOOOOOOOOO0MM; .lMc. .cMM00XKOOOOkkkkkkOOWMl. .cMo. .lMWO0XKOOOkkkkkkkkONMo. ;Wk. .oMNO0X0OOkkkkkkkkkOXMd..,oW0' .xMNO0X0OOkkkkkkkkkkXMWKXKOx;. .0MXOOOOOOkkkkkkkkkOKM0.. 'NMWNXXKK000000KKXNNMMX. .;okk0XNWWMMMMWWNKOkdc'. .....'cc:cc:''... ___ _ _ / (_)|\ |\\ | ||__ ,_ __ _ _ _ __ |/_ ,_ __ _ _ _ | |/ | / | / \/ |/ |/ | |_/ | \/ | |_/ /| | |\_ \___/| |_/ |_/\__/ | | |_/|__/\__/ |_/|__/ \_/ \_/ Edit /usr/local/etc/env.d/02-pager to change the default PAGER. more is used by default You may wish to edit the /usr/local/etc/env.d/01-editor file for an editor default. Chromebrew provides nano, vim and emacs as default TUI editor options. Chromebrew installed successfully and package lists updated. </pre> <span style="color:green">chronos@localhost</span> <span style="color:cyan">/ $</span> </div> :のようなアスキーアートとメッセージが表示されたら chromebrew のインストールは完了です。 </ol> === インストール結果の確認 === chromebrew のインストールが終わったら、基本的な動作を確認します。 * shellプロンプトで crew とタイプします(crew が chromebrew のコマンド名です) <div style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:black solid 0.5rem"> <span style="color:green">chronos@localhost</span> <span style="color:cyan">/ $</span> crew <pre style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:0;margin:0;padding:0"> Usage: crew autoremove [options] crew build [options] [-k|--keep] <name> ... crew const [options] [<name> ...] crew deps [options] [-t|--tree] [-b|--include-build-deps] [--exclude-buildessential] <name> ... crew download [options] <name> ... crew files [options] <name> ... crew help [<command>] crew install [options] [-k|--keep] [-s|--build-from-source] [-S|--recursive-build] <name> ... crew list [options] (available|installed|compatible|incompatible) crew postinstall [options] <name> ... crew reinstall [options] [-k|--keep] [-s|--build-from-source] [-S|--recursive-build] <name> ... crew remove [options] <name> ... crew search [options] [<name> ...] crew sysinfo [options] crew update [options] [<compatible>] crew upgrade [options] [-k|--keep] [-s|--build-from-source] [<name> ...] crew whatprovides [options] <pattern> ...</pre> <span style="color:green">chronos@localhost</span> <span style="color:cyan">/ $</span> crew sysinfo <pre style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:0;margin:0;padding:0"> - Architecture: `x86_64` (`x86_64`) - Kernel version: `4.14.282-19192-g19e8c55302db` - Chromebrew version: `1.24.0` - Chromebrew prefix: `/usr/local` - Chromebrew libdir: `/usr/local/lib64` - Last update in local repository: `e01f130: Edge 103.0.1264.77-1 => 104.0.1293.47-1 (#7254)` - OS variant: `Chrome OS` - OS version: `octopus-release/R104-14909.100.0` - OS channel: `stable-channel`</pre> </div> :サブコマンドとオプションの一覧が表示されます。 : sysinfo サブコマンドは、OSとchromebrew自身の情報を表示します。 :: 内容はバージョンによって異なります。 === パッケージのインストール === tree コマンドをインストールしてみます。 :<syntaxhighlight lang=console> $ crew install tree tree: Tree is a recursive directory listing command that produces a depth indented listing of files, which is colorized ala dircolors if the LS_COLORS environment variable is set and output is to tty. http://mama.indstate.edu/users/ice/tree/ Version: 2.0.2 License: GPL-2 Performing pre-flight checks... Precompiled binary available, downloading... Cannot find cached archive. 😔 Will download. [####################################################################################################################################] 51.52 KB 100% Tree archive downloaded. Unpacking archive using 'tar', this may take a while... Performing pre-install... Performing install... Using rdfind to convert duplicate files to hard links. Now scanning ".", found 2 files. Now have 2 files in total. Removed 0 files due to nonunique device and inode. Total size is 177860 bytes or 174 KiB Removed 2 files due to unique sizes from list. 0 files left. Now eliminating candidates based on first bytes: removed 0 files from list. 0 files left. Now eliminating candidates based on last bytes: removed 0 files from list. 0 files left. Now eliminating candidates based on sha1 checksum: removed 0 files from list. 0 files left. It seems like you have 0 files that are not unique Totally, 0 B can be reduced. Now making hard links. Making 0 links. Tree installed! chronos@localhost ~ $ tree -d /usr/local/lib/crew/ /usr/local/lib/crew/ ├── bin ├── lib ├── packages └── tools 4 directories chronos@localhost ~ $ </syntaxhighlight> treeはディレクトリー構造をツリー表示するコマンドで、階層構造の把握の役に立ちます。 :<syntaxhighlight lang=text> crew install パッケージ名 </syntaxhighlight> の形式では、バイナリーパッケージがインストールされますが、chromebrew では同程度の手間でソースからインストールすることができます。 :<syntaxhighlight lang=console> chronos@localhost ~ $ crew reinstall -s tree tree: Tree is a recursive directory listing command that produces a depth indented listing of files, which is colorized ala dircolors if the LS_COLORS environment variable is set and output is to tty. Performing pre-flight checks... Downloading source... Archive found in cache Unpacking archive using 'tar', this may take a while... Building from source, this may take a while... gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o tree.o tree.c gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o unix.o unix.c gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o html.o html.c gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o xml.o xml.c gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o json.o json.c gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o hash.o hash.c gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o color.o color.c gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o file.o file.c gcc -o tree tree.o unix.o html.o xml.o json.o hash.o color.o file.o Preconfiguring package... install -d /usr/local/tmp/crew/dest/usr/local/bin install -d /usr/local/tmp/crew/dest/usr/local/share/man/man1 if [ -e tree ]; then \ install tree /usr/local/tmp/crew/dest/usr/local/bin/tree; \ fi install doc/tree.1 /usr/local/tmp/crew/dest/usr/local/share/man/man1/tree.1 Rename all *.la_tmp files back to *.la Checking for FHS3 compliance... Checking for conflicts with files from installed packages... Stripping libraries... Stripping binaries... Running patchelf Running patchelf to patch binaries for library paths Using rdfind to convert duplicate files to hard links. Now scanning ".", found 4 files. Now have 4 files in total. Removed 0 files due to nonunique device and inode. Total size is 95387 bytes or 93 KiB Removed 4 files due to unique sizes from list. 0 files left. Now eliminating candidates based on first bytes: removed 0 files from list. 0 files left. Now eliminating candidates based on last bytes: removed 0 files from list. 0 files left. Now eliminating candidates based on sha1 checksum: removed 0 files from list. 0 files left. It seems like you have 0 files that are not unique Totally, 0 B can be reduced. Now making hard links. Making 0 links. Removing since upgrade or reinstall... Tree removed! Performing pre-install... Performing install... Using rdfind to convert duplicate files to hard links. Now scanning ".", found 2 files. Now have 2 files in total. Removed 0 files due to nonunique device and inode. Total size is 95236 bytes or 93 KiB Removed 2 files due to unique sizes from list. 0 files left. Now eliminating candidates based on first bytes: removed 0 files from list. 0 files left. Now eliminating candidates based on last bytes: removed 0 files from list. 0 files left. Now eliminating candidates based on sha1 checksum: removed 0 files from list. 0 files left. It seems like you have 0 files that are not unique Totally, 0 B can be reduced. Now making hard links. Making 0 links. Tree installed! chronos@localhost ~ $ </syntaxhighlight> :既にtreeパッケージはインストールされているので、 crew install が crew reinstall になっています(crew reinstall は、crew remove パッケージ名 したあと crew install と同義) :また、 -s オプションがついていることが違います。これが「ソースからビルドしてインストールする」指示で、依存パッケージのインストールやソースコードの取得を(必要であれば)確認を求めつつ実行します。 ==== バイナリーパッケージに対する、ソースコードからのビルドの得失 ==== ;短所:ネットワークから取得し展開するだけのバイナリーパッケージよりインストールに時間がかかる。 ;長所 :新しいコンパイラでコンパイルされるので、生成されるコードの質が高い。 :コンパイル条件を変えることで、LTOやPGOを使ったり、ターゲットCPUの命令セットに最適化することなどができる。 === システムとパッケージのアップデート === ;crew 自身のアップデート:<syntaxhighlight lang=console> chronos@localhost ~ $ crew update </syntaxhighlight> :crewを更新します。 :これはcrew本体のみをアップデートします。 ;パッケージのアップデート:<syntaxhighlight lang=console> chronos@localhost ~ $ crew upgrade </syntaxhighlight> :パッケージのアップデートを行います。 ::使用法: crew upgrade [-v|--verbose] [-s|--build-from-source] <package1> [<package2> ...] ::パッケージが省略された場合、全てのパッケージが更新されます。 そうでなければ、特定のパッケージが更新されます。 ::-s または --build-from-source を指定すると、パッケージはバイナリでアップグレードされるのではなく、コンパイルされます。 ::-v または --verbose を指定すると、より多くの情報が表示されます。 === パッケージの作り方 === crew のパッケージのレシピは、/usr/local/lib/crew/patches/ にある1つのrubyスクリプトです。 [[Crystal]]言語のパッケージが crew になかったので作ってみました。 ;/usr/local/lib/crew/patches/crystal.rb:<syntaxhighlight lang=ruby line> require 'package' class Crystal < Package description 'Programming language Crystal official binary' homepage 'https://crystal-lang.org/' version '1.5.0' license 'Apache License 2.0' compatibility 'x86_64' source_url 'https://github.com/crystal-lang/crystal/releases/download/1.5.0/crystal-1.5.0-1-linux-x86_64.tar.gz' source_sha256 '627360f0fc805202d80310007d503c7a2fc0745b1db2211537d7f54e9a994347' def self.build system 'git clone --single-branch --depth=1 https://github.com/crystal-lang/crystal' Dir.chdir 'crystal' do system "sed -i 's@^@15.0 @' src/llvm/ext/llvm-versions.txt" system %|SHELL=sh PATH=../bin/:$PATH \ FLAGS="--release --no-debug --progress --threads=1" \ CRYSTAL_CACHE_DIR="#{Dir.getwd}/cache" \ make interpreter=true verbose=true| end end def self.install Dir.chdir 'crystal' do system "make", "DESTDIR=#{CREW_DEST_DIR}", "install" end end def self.postinstall puts "\nType 'crystal' to get started.\n".lightblue end end </syntaxhighlight> # class Package とユーティリティ関数を定義した 'package' を読み込みます。 #  # <code>class パッケージ名 < Package</code>の「パッケージ名」は、レシピファイルから拡張子を取り先頭を大文字にしたものになります。 #: 逆に言うと、レシピファイル名にはRubyの識別子に使えない - を含めたり、数字で始めることが出ません。 #: このため - は _ に置換え、数字で始まる場合は pkg を前置します。 # description、パッケージの説明。crew search などで参照されます。 # homepage、ホームページのURL文字列。 # version、バージョンを表す文字列。スクリプトの中で @version で参照できます。 # license、ライセンスを表す文字列。 # compatibility、対応しているアーキテクチャーを表す文字列。'aarch64' 'armv7l' 'i686' 'x86_64' または 'all'。複数の場合は , で区切ります。 # source_url、ソースコードのURL文字列 # source_sha256 ソースコードのSHA256チェックサム。わからないあるいは不定の場合は :SKIP #;self.patch: 展開されたソースコードにパッチを当てるメソッド #;self.build: ビルドを行うメソッド #;self.install: DESTDIR=#{CREW_DEST_DIR}を仮の /usr/local としてインストールを行う #;self.postinstall: インストール完了後に行う処理 #;self.check: crew build の実行時に行われるテスト ==== パッケージリストへの反映 ==== 自分の作ったレシピを有効にするには、/usr/local/lib/crew/patches/にスクリプトを用意したあと ;パッケージリストの更新:<syntaxhighlight lang=console> $ crew update '<compatible>' </syntaxhighlight> を実行します。 == 脚註 == <references /> == 外部リンク == * 公式サイト {{---}} https://chromebrew.github.io/ * 公式リポジトリ {{---}} https://github.com/chromebrew/chromebrew.git bgiorbeu9fa2x2b5lnuizo8xsi71yh9 206674 206673 2022-08-17T05:50:12Z Ef3 694 /* システムとパッケージのアップデート */ crewを更新すると自分で行った /usr/local/lib/crew 以下の変更が書き戻されるので、変更を行っている場合は、事前にバックアップを取りv git diff の差分を保存するようにしてください。 wikitext text/x-wiki Chromebrewは、[[ChromeOS]]で動作するソースビルド指向のパッケージ管理システムです。 ChromeOSは、Linuxカーネルの上にChromeウェブブラウザーを中心としてネットワーククライアント昨日を提供しますが、所謂GNU/Linuxのディストリビューションに観られるパッケージマネージャーを含まず、GNU/Linuxの環境を手に入れるには # Crostini {{---}} LXCコンテナー上で、GNU/Linuxディストリビューションを実行する(設定 > “Linux (Beta)” として知られる) # Crouton {{---}} chroot 環境で、GNU/Linuxディストリビューションを実行する(サポート終了しました) # Chromebrew {{---}} デベローパーモードのシェル環境に独自バイナリーをインストールする(GNU/Linuxディストリビューションとのパッケージ互換性はない) の3つがあります。 Chromebrewは、その名の通り[[w:Homebrew|Homebrew]]の影響を受けていますが、完全にRubyで記述され(Homebrewは一部 bash スクリプト)、ユーザーが書込みも実行もできるファイルシステムは <code>/usr/local</code> に限られるなどのChoromeOS固有の事情に適応しています。 Chromebrewは、仮想環境やchrootのオーバーヘッドはなく、ユーティリティーや共有ライブラリーなどChromeOSのものを使えるのでフットプリントは、この中で一番小さくなります。 Chromebrewは、BSD Unixの package source や ports collection の様にソースコードからのビルドをユーザーが気軽に行え、たとえばCコンパイラーに -march=native オプションを与えホスト環境のプロセッサーで実行可能な命令セットからコード生成をすることができるなど、資源の少ない環境にも好適です。 == インストール == インストールする前に、Chromebook をデベロッパーモードにする必要があります。 :Chromebook をデベロッパーモードにすると、工場出荷時の設定に戻されます。 :Chromebook をデベロッパーモードにすると、工場出荷時の設定に戻されます。 大切なので二回言いました。 === デベロッパーモード === Chromebookを「デベロッパーモード<ref>''Developer mode'' を「開発者モード」とする資料もありますが、定訳がないので「デベロッパーモード」とカタカナ表記にしました。</ref>」にすると、Chromebookのシステムファイルを変更できるなど、完全なルートアクセスを取得できます。 デベロッパーモードには、一部のファイルを変更したり、外部USBデバイスからChromebookを起動したりするなど他の使い道もあります。 ; デベローパーモードへ切替える方法 # Chromebookの電源をオフにする # ESC + 更新(F3)ボタンを押しながら、電源ボタンを押します。その後、電源ボタンを離します。 # リカバリー画面が表示されます。ここで、Ctrl + Dキーを押して開発者モードをオンにします。その後、数分待ちます。 === Chromebrewのオンザフライインストール === <ol> <li> まず、 https://chromebrew.github.io/ にアクセスして、インストール方法が変わっていないか確認してください。 <li> crosh を開きます。 * Chrome で、ctrl+alt+T で crosh を開きます。 <div style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:black solid 0.5rem"> Welcome to crosh, the Chrome OS developer shell. If you got here by mistake, don't panic! Just close this tab and carry on. Type 'help' for a list of commands. If you want to customize the look/behavior, you can use the options page.<br> Load it by using the Ctrl-Shift-P keyboard shortcut. <span style="color:yellow">crosh></span> </div> : Chrome に新しいタブが開き、上のような表示が現れます。 : : もし、 <div style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:black solid 0.5rem"> <span style="color:yellow">crosh></span> shell<br> [ERROR:src/main.rs:184] ERROR: unknown command: shell </div> :と表示された場合は、デベローパーモードになっていません。デベローパーモードへの切替え手順を確認しましょう<ref>ChromeOS Flex の場合、grubの設定ファイルに cros_debug を追加します。</ref>。 <li>shellの起動。 * croshのプロンプトで shell とタイプします <div style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:black solid 0.5rem"> <span style="color:yellow">crosh></span> shell<br> <span style="color:green">chronos@localhost</span> <span style="color:cyan">/ $</span> </div> : shell が、開きました。初期状態では bash です。 <li> インストールスクリプトのオンザフライ実行。 * chromebrew のインストールスクリプトをファイルに落とさず、そのまま bash の標準入力に流します。 <div style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:black solid 0.5rem"> <span style="color:green">chronos@localhost</span> <span style="color:cyan">/ $</span> curl -Ls git.io/vddgY | bash <pre style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:0;margin:0;padding:0"> Welcome to Chromebrew! Please enter the developer mode password We trust you have received the usual lecture from the local System Administrator. It usually boils down to these three things: #1) Respect the privacy of others. #2) Think before you type. #3) With great power comes great responsibility. Password: Doing initial setup for install in /usr/local. This may take a while if there are preexisting files in /usr/local... Downloading information for Bootstrap packages... [1/15]: https://raw.githubusercontent.com/chromebrew/chromebrew/master/packages/musl_zstd.rb --> musl_zstd.rb --_curl_--https://raw.githubusercontent.com/chromebrew/chromebrew/master/packages/musl_zstd.rb [2/15]: https://raw.githubusercontent.com/chromebrew/chromebrew/master/packages/pixz.rb --> pixz.rb --_curl_--https://raw.githubusercontent.com/chromebrew/chromebrew/master/packages/pixz.rb : : : </pre> </div> * しばらく基礎的なパッケージのダウンロードとインストールが続き... <div style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:black solid 0.5rem"> <pre style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:0;margin:0;padding:0"> . . ..,:;;;::'.. .':lllllllool,. ...cl;..... ,::;'. .'oc...;::::..0KKo. .'od: .:::::, lolc. .'lNMMMO ;ooc.,XMMWx;:;. .dMMMMMMXkMMMMxoMMMMMMMMO. .:O0NMMMMMMMMMM0MMMMMN0Oc. .:xdloddddddoXMMMk:x:.... .xMNOKX0OOOOxcodlcXMN0O0XKc. .OMXOKXOOOOOk;ol:OXMK...;N0. 'XMKOXXOOOOOk:docOKMW, .kW; .cMMKOXXOOOOOOOOOOO0MM; .lMc. .cMM00XKOOOOkkkkkkOOWMl. .cMo. .lMWO0XKOOOkkkkkkkkONMo. ;Wk. .oMNO0X0OOkkkkkkkkkOXMd..,oW0' .xMNO0X0OOkkkkkkkkkkXMWKXKOx;. .0MXOOOOOOkkkkkkkkkOKM0.. 'NMWNXXKK000000KKXNNMMX. .;okk0XNWWMMMMWWNKOkdc'. .....'cc:cc:''... ___ _ _ / (_)|\ |\\ | ||__ ,_ __ _ _ _ __ |/_ ,_ __ _ _ _ | |/ | / | / \/ |/ |/ | |_/ | \/ | |_/ /| | |\_ \___/| |_/ |_/\__/ | | |_/|__/\__/ |_/|__/ \_/ \_/ Edit /usr/local/etc/env.d/02-pager to change the default PAGER. more is used by default You may wish to edit the /usr/local/etc/env.d/01-editor file for an editor default. Chromebrew provides nano, vim and emacs as default TUI editor options. Chromebrew installed successfully and package lists updated. </pre> <span style="color:green">chronos@localhost</span> <span style="color:cyan">/ $</span> </div> :のようなアスキーアートとメッセージが表示されたら chromebrew のインストールは完了です。 </ol> === インストール結果の確認 === chromebrew のインストールが終わったら、基本的な動作を確認します。 * shellプロンプトで crew とタイプします(crew が chromebrew のコマンド名です) <div style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:black solid 0.5rem"> <span style="color:green">chronos@localhost</span> <span style="color:cyan">/ $</span> crew <pre style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:0;margin:0;padding:0"> Usage: crew autoremove [options] crew build [options] [-k|--keep] <name> ... crew const [options] [<name> ...] crew deps [options] [-t|--tree] [-b|--include-build-deps] [--exclude-buildessential] <name> ... crew download [options] <name> ... crew files [options] <name> ... crew help [<command>] crew install [options] [-k|--keep] [-s|--build-from-source] [-S|--recursive-build] <name> ... crew list [options] (available|installed|compatible|incompatible) crew postinstall [options] <name> ... crew reinstall [options] [-k|--keep] [-s|--build-from-source] [-S|--recursive-build] <name> ... crew remove [options] <name> ... crew search [options] [<name> ...] crew sysinfo [options] crew update [options] [<compatible>] crew upgrade [options] [-k|--keep] [-s|--build-from-source] [<name> ...] crew whatprovides [options] <pattern> ...</pre> <span style="color:green">chronos@localhost</span> <span style="color:cyan">/ $</span> crew sysinfo <pre style="background:black;color:#f0f0f0;font-family: monospace;font-size:18px;font-weight:bold;border:0;margin:0;padding:0"> - Architecture: `x86_64` (`x86_64`) - Kernel version: `4.14.282-19192-g19e8c55302db` - Chromebrew version: `1.24.0` - Chromebrew prefix: `/usr/local` - Chromebrew libdir: `/usr/local/lib64` - Last update in local repository: `e01f130: Edge 103.0.1264.77-1 => 104.0.1293.47-1 (#7254)` - OS variant: `Chrome OS` - OS version: `octopus-release/R104-14909.100.0` - OS channel: `stable-channel`</pre> </div> :サブコマンドとオプションの一覧が表示されます。 : sysinfo サブコマンドは、OSとchromebrew自身の情報を表示します。 :: 内容はバージョンによって異なります。 === パッケージのインストール === tree コマンドをインストールしてみます。 :<syntaxhighlight lang=console> $ crew install tree tree: Tree is a recursive directory listing command that produces a depth indented listing of files, which is colorized ala dircolors if the LS_COLORS environment variable is set and output is to tty. http://mama.indstate.edu/users/ice/tree/ Version: 2.0.2 License: GPL-2 Performing pre-flight checks... Precompiled binary available, downloading... Cannot find cached archive. 😔 Will download. [####################################################################################################################################] 51.52 KB 100% Tree archive downloaded. Unpacking archive using 'tar', this may take a while... Performing pre-install... Performing install... Using rdfind to convert duplicate files to hard links. Now scanning ".", found 2 files. Now have 2 files in total. Removed 0 files due to nonunique device and inode. Total size is 177860 bytes or 174 KiB Removed 2 files due to unique sizes from list. 0 files left. Now eliminating candidates based on first bytes: removed 0 files from list. 0 files left. Now eliminating candidates based on last bytes: removed 0 files from list. 0 files left. Now eliminating candidates based on sha1 checksum: removed 0 files from list. 0 files left. It seems like you have 0 files that are not unique Totally, 0 B can be reduced. Now making hard links. Making 0 links. Tree installed! chronos@localhost ~ $ tree -d /usr/local/lib/crew/ /usr/local/lib/crew/ ├── bin ├── lib ├── packages └── tools 4 directories chronos@localhost ~ $ </syntaxhighlight> treeはディレクトリー構造をツリー表示するコマンドで、階層構造の把握の役に立ちます。 :<syntaxhighlight lang=text> crew install パッケージ名 </syntaxhighlight> の形式では、バイナリーパッケージがインストールされますが、chromebrew では同程度の手間でソースからインストールすることができます。 :<syntaxhighlight lang=console> chronos@localhost ~ $ crew reinstall -s tree tree: Tree is a recursive directory listing command that produces a depth indented listing of files, which is colorized ala dircolors if the LS_COLORS environment variable is set and output is to tty. Performing pre-flight checks... Downloading source... Archive found in cache Unpacking archive using 'tar', this may take a while... Building from source, this may take a while... gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o tree.o tree.c gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o unix.o unix.c gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o html.o html.c gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o xml.o xml.c gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o json.o json.c gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o hash.o hash.c gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o color.o color.c gcc -ggdb -pedantic -Wall -DLINUX -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -c -o file.o file.c gcc -o tree tree.o unix.o html.o xml.o json.o hash.o color.o file.o Preconfiguring package... install -d /usr/local/tmp/crew/dest/usr/local/bin install -d /usr/local/tmp/crew/dest/usr/local/share/man/man1 if [ -e tree ]; then \ install tree /usr/local/tmp/crew/dest/usr/local/bin/tree; \ fi install doc/tree.1 /usr/local/tmp/crew/dest/usr/local/share/man/man1/tree.1 Rename all *.la_tmp files back to *.la Checking for FHS3 compliance... Checking for conflicts with files from installed packages... Stripping libraries... Stripping binaries... Running patchelf Running patchelf to patch binaries for library paths Using rdfind to convert duplicate files to hard links. Now scanning ".", found 4 files. Now have 4 files in total. Removed 0 files due to nonunique device and inode. Total size is 95387 bytes or 93 KiB Removed 4 files due to unique sizes from list. 0 files left. Now eliminating candidates based on first bytes: removed 0 files from list. 0 files left. Now eliminating candidates based on last bytes: removed 0 files from list. 0 files left. Now eliminating candidates based on sha1 checksum: removed 0 files from list. 0 files left. It seems like you have 0 files that are not unique Totally, 0 B can be reduced. Now making hard links. Making 0 links. Removing since upgrade or reinstall... Tree removed! Performing pre-install... Performing install... Using rdfind to convert duplicate files to hard links. Now scanning ".", found 2 files. Now have 2 files in total. Removed 0 files due to nonunique device and inode. Total size is 95236 bytes or 93 KiB Removed 2 files due to unique sizes from list. 0 files left. Now eliminating candidates based on first bytes: removed 0 files from list. 0 files left. Now eliminating candidates based on last bytes: removed 0 files from list. 0 files left. Now eliminating candidates based on sha1 checksum: removed 0 files from list. 0 files left. It seems like you have 0 files that are not unique Totally, 0 B can be reduced. Now making hard links. Making 0 links. Tree installed! chronos@localhost ~ $ </syntaxhighlight> :既にtreeパッケージはインストールされているので、 crew install が crew reinstall になっています(crew reinstall は、crew remove パッケージ名 したあと crew install と同義) :また、 -s オプションがついていることが違います。これが「ソースからビルドしてインストールする」指示で、依存パッケージのインストールやソースコードの取得を(必要であれば)確認を求めつつ実行します。 ==== バイナリーパッケージに対する、ソースコードからのビルドの得失 ==== ;短所:ネットワークから取得し展開するだけのバイナリーパッケージよりインストールに時間がかかる。 ;長所 :新しいコンパイラでコンパイルされるので、生成されるコードの質が高い。 :コンパイル条件を変えることで、LTOやPGOを使ったり、ターゲットCPUの命令セットに最適化することなどができる。 === システムとパッケージのアップデート === crewを更新すると自分で行った /usr/local/lib/crew 以下の変更が書き戻されるので、変更を行っている場合は、事前にバックアップを取りv git diff の差分を保存するようにしてください。 ;crew 自身のアップデート:<syntaxhighlight lang=console> chronos@localhost ~ $ crew update </syntaxhighlight> :crewを更新します。 :これはcrew本体のみをアップデートします。 ;パッケージのアップデート:<syntaxhighlight lang=console> chronos@localhost ~ $ crew upgrade </syntaxhighlight> :パッケージのアップデートを行います。 ::使用法: crew upgrade [-v|--verbose] [-s|--build-from-source] <package1> [<package2> ...] ::パッケージが省略された場合、全てのパッケージが更新されます。 そうでなければ、特定のパッケージが更新されます。 ::-s または --build-from-source を指定すると、パッケージはバイナリでアップグレードされるのではなく、コンパイルされます。 ::-v または --verbose を指定すると、より多くの情報が表示されます。 === パッケージの作り方 === crew のパッケージのレシピは、/usr/local/lib/crew/patches/ にある1つのrubyスクリプトです。 [[Crystal]]言語のパッケージが crew になかったので作ってみました。 ;/usr/local/lib/crew/patches/crystal.rb:<syntaxhighlight lang=ruby line> require 'package' class Crystal < Package description 'Programming language Crystal official binary' homepage 'https://crystal-lang.org/' version '1.5.0' license 'Apache License 2.0' compatibility 'x86_64' source_url 'https://github.com/crystal-lang/crystal/releases/download/1.5.0/crystal-1.5.0-1-linux-x86_64.tar.gz' source_sha256 '627360f0fc805202d80310007d503c7a2fc0745b1db2211537d7f54e9a994347' def self.build system 'git clone --single-branch --depth=1 https://github.com/crystal-lang/crystal' Dir.chdir 'crystal' do system "sed -i 's@^@15.0 @' src/llvm/ext/llvm-versions.txt" system %|SHELL=sh PATH=../bin/:$PATH \ FLAGS="--release --no-debug --progress --threads=1" \ CRYSTAL_CACHE_DIR="#{Dir.getwd}/cache" \ make interpreter=true verbose=true| end end def self.install Dir.chdir 'crystal' do system "make", "DESTDIR=#{CREW_DEST_DIR}", "install" end end def self.postinstall puts "\nType 'crystal' to get started.\n".lightblue end end </syntaxhighlight> # class Package とユーティリティ関数を定義した 'package' を読み込みます。 #  # <code>class パッケージ名 < Package</code>の「パッケージ名」は、レシピファイルから拡張子を取り先頭を大文字にしたものになります。 #: 逆に言うと、レシピファイル名にはRubyの識別子に使えない - を含めたり、数字で始めることが出ません。 #: このため - は _ に置換え、数字で始まる場合は pkg を前置します。 # description、パッケージの説明。crew search などで参照されます。 # homepage、ホームページのURL文字列。 # version、バージョンを表す文字列。スクリプトの中で @version で参照できます。 # license、ライセンスを表す文字列。 # compatibility、対応しているアーキテクチャーを表す文字列。'aarch64' 'armv7l' 'i686' 'x86_64' または 'all'。複数の場合は , で区切ります。 # source_url、ソースコードのURL文字列 # source_sha256 ソースコードのSHA256チェックサム。わからないあるいは不定の場合は :SKIP #;self.patch: 展開されたソースコードにパッチを当てるメソッド #;self.build: ビルドを行うメソッド #;self.install: DESTDIR=#{CREW_DEST_DIR}を仮の /usr/local としてインストールを行う #;self.postinstall: インストール完了後に行う処理 #;self.check: crew build の実行時に行われるテスト ==== パッケージリストへの反映 ==== 自分の作ったレシピを有効にするには、/usr/local/lib/crew/patches/にスクリプトを用意したあと ;パッケージリストの更新:<syntaxhighlight lang=console> $ crew update '<compatible>' </syntaxhighlight> を実行します。 == 脚註 == <references /> == 外部リンク == * 公式サイト {{---}} https://chromebrew.github.io/ * 公式リポジトリ {{---}} https://github.com/chromebrew/chromebrew.git 9m8xt04mth3opuc6kdfzcbymaxheh0g