ファミコンROM作ってみた:開発編(コーディング前準備）

#cc65コンパイラにおけるコーディングの注意点
以下、Cc65サイトのドキュメント内容がさしあたりの注意点になりますので、コードを書く前にチェックしておきましょう。
https://cc65.github.io/doc/cc65.html#s4

###データ型「float」および「double」は使用できません。 
*The datatypes "float" and "double" are not available.*
cc65では浮動小数点が使えないという事になります。
ですので、位置情報を細かく動かしたいという場合等は、short形で取得して>>2などで、数値を丸める固定小数点の手法を利用しましょう。（※ゲーム内では地面に降りたときの横の移動量でその手法を使っています）

###関数の引数や返り値で構造体（または共用体）は利用できません。ただし、構造体のポインタ割り当ては可能です。
_C Functions may not return structs (or unions), and structs may not be passed as parameters by value. However, struct assignment \*is\* possible._
コンパイラの使用もそうですが、そもそもスタックも小さいので、構造体はポインタ渡しで使用するのが望ましいかと思われます。

###fastcall呼び出し規約のみ使用できます。呼び出し規約には互換性がありませんので、cdecl関数へのポインターと混在させてはいけません。
*Most of the C library is available with only the fastcall calling convention ( see below). It means that you must not mix pointers to those functions with pointers to user-written, cdecl functions (the calling conventions are incompatible).*
正確には使えないという事ではないのですが、最新バージョンのデフォルトはfastcallになっているようですので、関数ポインタを利用する際には気を付けておきましょう。

###volatileキーワードは、ほとんど影響を及ぼしません。
*The volatile keyword has almost no effect. That is not as bad as it sounds, since the 6502 has so few registers that it isn't possible to keep values in registers anyway.*
レジスタが少ないため、持っておけないという事みたいです。基本的にシングルスレッドでしか記載されないかと思いますが、割り込みやマルチスレッド処理で数値が変わらないように注意しておきましょう。


#コンパイルスイッチの補足
以下、Cc65サイトのドキュメント内容のうち、コーディングに密接にかかわってきそうなものをピックアップしておきます。
https://cc65.github.io/doc/cc65.html#ss2.2
###-j, --signed-chars
*Using this option, you can make the default characters signed. Since the 6502 has no provisions for sign extending characters (which is needed on almost any load operation), this will make the code larger and slower. A better way is to declare characters explicitly as "signed" if needed. You can also use #pragma signed-chars for better control of this option.*
コードのデフォルト（省略した際）をsignedにするのか、unsignedでの定義とするのかを指定しています。
各コードで変更したい場合は、#pragmaもあるみたいですが、複数プロジェクトにかかわる共通コードでもない限り、コンパイルオプションで指定しておくほうが無難かと思います。一般的（？）にはsignedがデフォルトかと思いますので、定義しておくほうが無難かと思われます。

###--standard std
*This option allows to set the language standard supported. ...*
コーディング規約を変更するものですが、デフォルトのcc65で問題ありません。（というか、変更するとnes.hでエラーが出る…）
ちなみに、"//"のコメントはデフォルトでも利用できます。

###-I dir, --include-dir dir
*Set a directory where the compiler searches for include files. You may use this option multiple times to add more than one directory to the search list.*
別フォルダに共通コードを入れてある場合、こちらの指定をしておくとヘッダーファイルを”#include <???.h>”で定義できて、パス階層を意識しない書き方が可能になります。

#コーディングヒント
こちらに処理スピードアップの手法が記載されています。
もちろん、コンパイルオプションで諸々インライン化するようなオプションもあり、pragmaも指定できるようになっているみたいですので、ざっと見ておくといいと思います。
https://cc65.github.io/doc/coding.html

こちらに日本語で説明されているサイトもありましたので、ご参考に。
ムトー研究所
http://muto.world.coocan.jp/nesapp/nesapp-tech.html

特に上記サイト内ではポインタ操作のアセンブラの検証が行われていますので、頭に入れておくといいかもしれません。
簡単に要約すると下記になります。

・定数値に設定するのが最もアセンブラコードが短くなる（早い）

```
#define RAM ((char *)0x6000)
*(RAM +  0) = 1;   
```
・ポインタを利用する場合は静的ポインタを利用したほうが良い

```
static char *static_ptr;
static_ptr = RAM; 
 unsigned char i;
i =   0; static_ptr[i] = 1;  
```

・さらにいうと大域変数（ゼロページ変数）を使ったほうが良い
※ただ、大域変数はstart.asmとかでzeroページに_Workのような形で変数の記載が必要。

```
extern Work zpw;
#pragma zpsym ("zpw");  /* zpw is in the zeropage */
pw.i =   0; zpw.ptr[zpw.i] = 1;
```

コーディングヒントについては、無理にそうする必要はないと思いますが、作っていって重くなったら毎回呼び出されているような処理を軽くしていくようなイメージでよいのではないかと思います。

#int型サイズ
ムトー研究所様の[記事](http://muto.world.coocan.jp/nesapp/nesapp-cui.html)から抜粋
*8ビットCPUですがint型のサイズは2バイトです。*

#メモリ関連
こちらもムトー研究所様の[記事](http://muto.world.coocan.jp/nesapp/nesapp-cui.html)から抜粋
*大域変数でconst修飾子付き、あるいは局所変数でconst staticな変数はROM領域、
大域変数でconst修飾子なし、あるいは局所変数でstaticな変数はバッテリーバックアップなどで使われる拡張RAM領域、
その他の局所変数はRAM領域にマッピングされています。*

*mem系は普通に使えますが、alloc系の関数はNULLポインタを返却しますので使えません。*

#参考
CC65ユーザーズガイド
https://cc65.github.io/doc/cc65.html
CC65コーディングヒント
https://cc65.github.io/doc/coding.html

ムトー研究所
C言語でNESアプリを作成（技術的な話題）
http://muto.world.coocan.jp/nesapp/nesapp-tech.html
C言語でNESアプリを作成（標準関数を使ったサンプル）
http://muto.world.coocan.jp/nesapp/nesapp-cui.html

#関連記事
[ファミコンROM作ってみた](https://qiita.com/tmori/items/a130fb0364dc5f757d67)
[ファミコンROM作ってみた:開発編(画像コンバーター）](https://qiita.com/tmori/items/e952a9d5e150e60af393)
[ファミコンROM作ってみた:開発編(環境）](https://qiita.com/tmori/items/14e250c52d362a403cbe)
[ファミコンROM作ってみた:開発編(ビルド）](https://qiita.com/tmori/items/ab1f163667878a7c9bf5)
[ファミコンROM作ってみた:開発編(コード設計）](https://qiita.com/tmori/items/d49fd2b261fcab86f0a4)
[ファミコンROM作ってみた:開発編(共通関数ライブラリ）](https://qiita.com/tmori/items/bc0cebefe64959337428)
[ファミコンROM作ってみた:開発編(プロダクト用関数ライブラリ）](https://qiita.com/tmori/items/ad667c6dd8cd2c27f80b)
[ファミコンROM作ってみた:開発編(mainとフローの処理コード）](https://qiita.com/tmori/items/ed9f4d85fb7fcc99ccae)
[ファミコンROM作ってみた:開発編(キャラクター制御コード）](https://qiita.com/tmori/items/ddf96075f05d0a1f710d)