歩いたら休め

If the implementation is easy to explain, it may be a good idea.

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

【GB】C言語でオブジェクト指向風のプログラミングを試してみる

C言語によるオブジェクト指向プログラミング入門』を参考に、以下のようなコードを書いています。「第一引数に構造体を与える関数を用意してあげれば、オブジェクト指向っぽくプログラミングできるだろう」という発想です。

ポリモルフィズム的なのを考えると、マクロでがんばるとか、自前でトレイトオブジェクト的な実装するとか必要そうな気がしているのですが、今のところややこしそうなので目を瞑ります。

C言語によるオブジェクト指向プログラミング入門

C言語によるオブジェクト指向プログラミング入門

#include "Player.h"
#include <gb/gb.h>

int main(void) {
    Player player;
    // 初期値 
    Player_Init(&player, 0, 0);
    for (;;) {
        Player_Move(&player, 1, 1);
        delay(100);
    }
}

実は以下のように「 Player の構造体を返す関数」を書こうとしたのですが、 Function cannot return aggregate. Func body ignored というようなエラーが出てしまいました。

Player player = Player_Init(0, 0);

以下のページを見る限り、「gbdkを利用するために利用しているコンパイラが古すぎて、構造体を返す関数に対応していない」ようですね。これはつらい。

sourceforge.net

$ lcc -v
lcc $Id: lcc.c,v 1.6 2001/10/28 18:38:13 michaelh Exp $

【雑記】組み込み機器のC言語プログラミングと、最近読んだ本

今日はいろいろやりたいことあった(掃除とか)んですが、結局カフェでプログラミングの本とか読んでしてしまっていました。

組み込み機器のC言語プログラミング

kiito.hatenablog.com

まず、ゲームボーイ上の実装の参考になるかと思って『組み込み開発の実践的プログラミング』という本を読んでました。

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

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

この中のいくつかの処理を自分でも再現しながら勉強に使えそうです。

ただ、やはりmain関数が「繰り返し処理の中で、switch文で切り替える」ような処理になって、プログラミングが煩雑になってしまうようです。こういう場合にやっぱりオブジェクト指向的な設計したいです。

C言語によるオブジェクト指向プログラミング入門

C言語によるオブジェクト指向プログラミング入門

以前買ったこの本も参考にしようと思います。

あと最近後輩とC++の画像処理のバッチ処理の高速化の話になって、立ち読みしてなんとなく面白そうだった『Optimized c++』って本を買ってみたのですが、今の自分のレベルでは気合入れないと読めない感じの本でした。

Optimized C++ ―最適化、高速化のためのプログラミングテクニック

Optimized C++ ―最適化、高速化のためのプログラミングテクニック

遠藤雅伸ゲームデザイン講義実況中継

遠藤雅伸のゲームデザイン講義実況中継

遠藤雅伸のゲームデザイン講義実況中継

最近仕事で「WEBサービスのプロトタイプ」を作っているんですが、自分で試していても「なんだか面白くないもの」が出来上がってしまいました。

うまくゲーム性を取り込んで実装できないかと思って、以下の記事で薦められていた本も読んでいました。ゲームとして見ると何か発展させるアイデアが出るんじゃないかと。

という話を友達にしていたら、「ラジオに出てた」といって遠藤雅伸さんの本を薦められました。

note.mu

直接役立ちそうなアイデアは出ませんでしたが、「数学系パズル」などの項目には、試しにゲームボーイで実装してみるには面白そうなものもありました。セレンディピティ

Puppeteerを試した

雑な運用をしているクローラーがいくつかあるのでちゃんとコード書こうと思っています。あとはGAEのnode.jsとPuppeteerでHeadless Chromeを試してました。

cloud.google.com

一時期Pythonのpyppeteerを利用していたのですが、やはりGCPでも公式でサポートされているのでnode.jsのほうが楽そうだと判断しています。

kiito.hatenablog.com

文化社会学入門

文化社会学入門―テーマとツール

文化社会学入門―テーマとツール

社会学周辺ジャンルを紹介するディスクガイドみたいな本でした。私は今は「発信している思想がコミュニティに与える影響」について興味があるので、『宗教社会学』の分野が興味湧きました。

ja.wikipedia.org

【GB】gbdkで割り込み処理を実装しました

ボタンを押すたびにカウントアップする実装です。

github.com

といっても大したことはなく、CPUにボタン押下時の割り込み処理が存在するので、そのときに実行する関数を指定しているだけです。

私は今までOSが存在しない低レイヤーのプログラミングをしたことがなく、「割り込み」の機能がOSレイヤーで実装されていると思いこんでいた(もしかしたらOSレイヤーでも実装されているのかもしれませんが)ので、CPUの機能として実装されていることがちょっと意外でした。

低レベルプログラミング

低レベルプログラミング

『低レベルプログラミング』から引用すると、フォン・ノイマンアーキテクチャから現代のCPU(書籍ではIntel 64が例ですが)いくつかの拡張があるようです。

このうち「割り込み」によって、対話的なプログラミングできるようになったそうです。このうちゲームボーイでは「プロテクションリング」「仮想メモリ」のような、プログラムの機構は無さそうですね。また、以前海外の記事で「GBのアーキテクチャがGBA以前は"register-oriented strategy"向けに設計されていて、関数でスタックを利用するC言語では遅い場合がある」というような話を読んだことあるのですが、それはハードウェアスタックが存在しないことを指しているのかもしれません。

ただ、割り込みの実装自体はできたものの、ライフゲームの実装をするためにはいくつか困った点があります。

kiito.hatenablog.com

割り込み処理中に joypad() でボタンの情報を取得できない

もともと、以下のようにグローバル変数joypad_state )を書き換え、ボタンの処理によって分岐しようとしていました。

int main(void) {
    disable_interrupts();
    add_JOY(onjoy);
    enable_interrupts();
    set_interrupts(JOY_IFLAG);

    while (1) {
        switch (joypad_state) {
            // 分岐
        }
    }
}

void onjoy(void) {
    joypad_state = joypad();
}

ただ、公式ドキュメントにもある通り、 add_JOY の処理中には、ボタンの状態を受け取れません( joypad 関数が動作しません)でした。これは少し工夫する必要があります。

gbdk.sourceforge.net

Interrupts in GBDK are handled using the functions disable_interrupts(), enable_interrupts(), set_interrupts(UBYTE ier) and the interrupt service routine (ISR) linkers add_VBL, add_TIM, add_LCD, add_SIO and add_JOY which add interrupt handlers for the vertical blank, timer, LCD, serial and joypad interrupts respectively.

set_interrupts をした場合に画面の表示がズレてしまう

#include <gb/gb.h>
#include <gb/drawing.h>

void onjoy(void);

int main(void) {
    disable_interrupts();
    add_JOY(onjoy);
    enable_interrupts();
    // set_interrupts(JOY_IFLAG); // <- ここをコメントアウトしたりする
    line(16, 4, 16, 140);
}

コメントアウトした場合はこうなのですが、

コメントアウトを外し、 set_interrupts を行うとこうなります。

こういう場合のデバッグ方法が分からずに困っています。コンパイル後のアセンブリを見ていくしかないと思うんですが、どういう観点で見れば良いのか分かりません。