歩いたら休め

なんでこんな模様をしているのですか?

【NES】C言語でファミコンソフトをコンパイルして通す

ゲームボーイとりあえずキャラクターを動かす程度の実装はできるようになったのですが、ファミコンのほうが面白いんじゃないかと思って調べてみました。将来的には自作のファミコンプログラムでVJやるとかできたらかっこいいです。

こちらの記事によると、cc65というコンパイラ(?)を使えばC言語でソフトを作れるそうです。

blog.akiym.com

というわけで、↑の引用元であるこちらのサイトを参考にしつつ、とりあえずコンパイルを通してみます。

OSXへのコンパイラのインストールは brew install cc65 で済んでしまいました。

www34.atwiki.jp

#include <conio.h>


int main(void) {
    clrscr();
    cprintf("hello cc65");
    while(1);
    return 0;
}

Makefileはこんな風に記述しています。あまり記述方法わかっていない…。

main:
  cc65 -t nes main.c
  ca65 -t nes main.s
  ld65 -t nes main.o nes.lib atmos.lib -o main.nes

clean:
  rm main.o main.nes main.s

エミュレータで動かしてみます。

今回のプログラムです。

github.com

【Rust】簡単なcliを作る

少しずつRustの勉強も進めていきたいです。

以前数値計算のシミュレーションを実装しようとしていたのですが、ハミルトニアンの復習のほうが自分にとって難しくなって来てしまったので止まってしまっています。

そちらは今後気が向いたときに進めることにして、せっかくなので日常的に使えるものを作りたいと考え、GB USB SMART CARDにMacからゲームボーイソフトを書き込む際に利用するems-flasherを再現することを目標にしてみました。

github.com

というわけで「コマンドライン引数をパースする」「ファイルを読み込む」「USBの接続先に書き込む」という機能が必要そうです。

Rustのコマンドラインパーサーには clapというライブラリを使いました。

github.com

若干文字列周りで詰まりました。文字列は「サイズが固定されていない」というのはその通りで、ゲームボーイソフトのC言語プログラミングをしていた際は、「ユーザーからの文字列入力を行う必要がない」ので意図的に入門書も読み飛ばしていましたが、少しは気張らないといけませんね。

qiita.com

doc.rust-jp.rs

他にも画像処理のコードをRustで書くことにもチャレンジしたいのですが、opencvのインストールに手こずったのでこれまた後回しにしています。

【Django】GAEでとりあえずアプリケーションを立ち上げる その2

docs.djangoproject.com

私はpipenvを利用したいので、GAEのPython3.7のサンプルアプリケーションにある .gcloudignore を参考にしつつ、PipfilePipfile.lock などを追記します。

# This file specifies files that are *not* uploaded to Google Cloud Platform
# using gcloud. It follows the same syntax as .gitignore, with the addition of
# "#!include" directives (which insert the entries of the given .gitignore-style
# file at that point).
#
# For more information, run:
#   $ gcloud topic gcloudignore
#
.gcloudignore
# If you would like to upload your .git directory, .gitignore file or files
# from your .gitignore file, remove the corresponding line
# below:
.git
.gitignore
Pipfile
Pipfile.lock

# Python pycache:
__pycache__/

また、 mysite/settigs.py に ALLOWED_HOSTSを追記しました。今のところ公開するつもりの無いアプリケーションなので DEBUG=True などを指定して適当にやってしまっていますが、セキュリティ関連もちゃんと設定しなきゃいけないですね。

# See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'qr1q-b3u&hogehoge'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

【Django】GAEでとりあえずアプリケーションを立ち上げる

久しぶりに会社でWEBアプリケーションを書くことになりそうです。レポーティング用アプリケーションで凝ったシステムは必要ない(はず)なので、分析担当のメンバーも理解しやすいPythonDjango)を選ぼうと思っています。

ひとまず、こちらのチュートリアルをやってみました。コードの内容は全く理解していないものの、GAEでとりあえずアプリケーションを立ち上げるところまで完了しました。

cloud.google.com

あとはDjango公式サイトを見つつシンプルなものを作るのと、JSのフレームワークの簡単なやつを試そうと思っています。

ちょっと意外だったのが、仮想環境としてpipenvを利用していたことで Pipfile is not supported と出てきたことです。Pipfileを無視してrequirements.txtを読んでほしいんですけどね…。

あと、これをGithubにpushしたところ、いくつかのセキュリティアラートが出ました。

f:id:takeshi0406:20190426200452p:plain

どうやらライブラリのバージョンが古いかなにかで脆弱性を自動で検知してくれたようです。便利ですねこれ。

f:id:takeshi0406:20190426200510p:plain

【メモ】Githubの草を剥がさずにリポジトリを移行(結合)した

Rustの練習用にいくつかリポジトリを作って書き捨てのプログラムを書いていたのですが、あまり「〇〇-test」とかリポジトリが乱立してるのは見栄えがいいものではありません。

というわけでこんなディレクトリ構成で一つのリポジトリで管理し、過去のリポジトリは削除してしまうことにしたのですが、最近「毎日とりあえずコード書いてGithubに草を生やす(コミット履歴を残す)」ことにハマっていて、普通にリポジトリを消してしまうとせっかく生やした草が剥げてしまいます。

$ tree
.
├── README.md
├── duplex-pendulum
│   ├── Cargo.lock
│   ├── Cargo.toml
│   └── src
│       └── main.rs
└── python-rust-linkage-test
    ├── Cargo.toml
    ├── main.py
    └── src
        └── lib.rs

4 directories, 7 files

こちらの記事を参考に、gitのUpstream機能でなんとかできました。まあ本質的じゃないのでこだわらなくてもいいですが一応…。

qiita.com

コミットログを見るとひどいので見ないでください。

github.com

【GB】複数スプライトのキャラクターを動かす

こちらの実装を元にしていますが、「複数スプライトを利用していること(それをなんちゃってオブジェクト指向で隠蔽していること)」「斜め移動に対応していること」が工夫した点です。

github.com

こんな感じのコードを実装しています。

const unsigned char sprite[] = {
    0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00,
    0x00, 0x1F, 0x00, 0x3F,
    0x00, 0x7F, 0x00, 0x77,
    0x08, 0x6B, 0x40, 0x77,
    0x80, 0xFF, 0x00, 0x7F,
    0x00, 0x3F, 0x00, 0x1F,
    0x10, 0x1F, 0x30, 0x30
};


typedef struct _Player {
    UBYTE i, x, y;
} Player;


void Player_init(Player* player, UBYTE i, UBYTE x, UBYTE y) {
    // copyのため?
    player->i = i * 1;
    player->x = x * 1;
    player->y = y * 1;
    SPRITES_8x16;
    set_sprite_data(player->i, 0, sprite);
    set_sprite_data(player->i + 2, 0, sprite);
    // スプライトを反転させる(キャラクターが左右対称のため)
    set_sprite_prop(player->i + 2, S_FLIPX);
    set_sprite_tile(player->i, 0);
    set_sprite_tile(player->i + 2, 0);
    move_sprite(player->i, player->x, player->y);
    // 横にずらして配置
    move_sprite(player->i + 2, player->x + 7, player->y);
    SHOW_SPRITES;
}

void Player_move(Player* player, UBYTE joystate) {
    if (!joystate) {
        return;
    }

    if (joystate & J_RIGHT) player->x++;
    else if (joystate & J_LEFT) player->x--;

    if (joystate & J_UP) player->y--;
    else if (joystate & J_DOWN) player->y++;

    move_sprite(player->i, player->x, player->y);
    move_sprite(player->i + 2, player->x + 7, player->y);
    delay(10);
}

こういう副作用多くて、なんとか隠蔽しなきゃいけないときオブジェクト指向的な発想って便利ですね。また、自分自身は組み込みプログラミングに慣れていないので joystate & J_DOWN みたいな「共通するビットが立っているとき実行する」ような発想のコードはちょっと新鮮でした。

kiito.hatenablog.com

また、割り込みでBGM出してみています。というか実はこちらが主目的です。

sakana38.hatenablog.com

こちらで実装中です。

github.com

組込み開発のための実践的プログラミング

組込み開発のための実践的プログラミング

【GB】TODO:: C言語の関数内での構造体への値のセットについて調べる

gbdkでのプログラミング中、次のようなコードを書いていたところ、「 Player_init 関数内では player->x などに50がセットしたつもりなのに、main 関数に戻ると0という値になる」という事象が発生しました。

typedef struct _Player {
    UBYTE i, x, y;
} Player;

void Player_init(Player* player, UBYTE i, UBYTE x, UBYTE y) {
    player->i = i;
    player->x = x;
    player->y = y;
    // spriteの表示は略
}

void Player_move(Player* player, UBYTE joystate) {
  // 略
}

int main(void) {
    Player player;
    Player_init(&player, 0, 50, 75);
    for (;;) {
        Player_move(&player, joypad());
    }
}

「引数にセットされた値をそのまま構造体のメンバに代入しているのが悪いんじゃないか」と思い、 player->x = x * 1; とするときちんと main 関数内でも player->x などの値がセットされたままでした。このためゲーム(?)の制作自体は続けられそうです。

C言語の仕様なのか、コンパイラの仕様なのかも今の自分には分からないため、一度アセンブラのレベルで見ていくべきなのかもしれません。