main.h
#include <stdint.h>
#include <stdio.h>
void put_string(uint8_t x, uint8_t y, char* str);
void put_player(uint8_t visible);
main.c
#include "main.h"
#include "bios.c"
uint8_t lv = 1;
uint8_t px = 8;
uint8_t py = 10;
uint8_t is_wait = 0;
void main() {
BIOS_CHGMOD(1); // スクリーン・モード1に変更
while (1) {
BIOS_CLS();
// カタカナは半角カタカナで入力し、ファイルをShift-JISで保存する
uint8_t buf[10];
sprintf(buf, "ユウシャ Lv %d", lv);
put_string(1, 1, buf);
put_string(1, 4, "マウガ セメコンデ キマシタ");
put_string(7, 6, "タタカウ");
put_string(1, 10, "ニゲル");
put_string(13, 10, "キタエル");
put_player(1);
while (1) {
uint8_t key = BIOS_GTSTCK(0);
if (key == 0) {
key = BIOS_GTSTCK(1);
}
if (is_wait) {
if (key != 0) {
// キーの押下が解除されるまでスキップ
continue;
}
if (BIOS_GTTRIG(0) == 0xff || BIOS_GTTRIG(1) == 0xff) {
// スペースキーかジョイスティック1のボタンが押された場合
is_wait = 0;
break;
}
continue;
}
if (key == 0) {
continue;
}
put_player(0);
if (key == 1) {
// 上キーが押された場合
py--;
put_player(1);
if (lv < 5) {
put_string(1, 12, "マオウニ ハイボク シマシタ");
put_string(1, 14, "GAME OVER");
return;
}
put_string(1, 11, "マオウニショウリシ ヘイワガ オトズレマシタ");
put_string(1, 13, "GAME CLER!");
return;
}
if (key == 7) {
// 左キーが押された場合
px--;
put_player(1);
put_string(1, 11, "マオウガ セカイヲ ホロボシマシタ");
put_string(1, 13, "GAME OVER");
return;
}
if (key == 3) {
// 右キーが押された場合
px++;
put_player(1);
px--;
put_string(1, 11, "ユウシャハ レベルガ アガッタ");
put_string(1, 13, "hit [space] key");
lv++;
is_wait = 1;
}
}
}
}
void put_string(uint8_t x, uint8_t y, char* str) {
// 0x1800は、スクリーン・モード1の、VRAMのパターンネームテーブルの開始アドレス
// 32は、スクリーン・モード1の1行あたりのバイト数
BIOS_LDIRVM(str, 0x1800 + 32 * y + x, strlen(str));
}
void put_player(uint8_t visible) {
if (visible) {
put_string(px, py, "@");
} else {
put_string(px, py, " ");
}
}
bios.c
#include <stdint.h>
/*
現在押下されているキーマトリクスの値が格納されているワークエリアのアドレス
0行:0xFBE5~10行:0xFBF5
参考URL: キースキャン
https://ngs.no.coocan.jp/doc/wiki.cgi/TechHan?page=3%BE%CF+%A5%AD%A1%BC%A5%DC%A1%BC%A5%C9%A1%A6%A5%A4%A5%F3%A5%BF%A1%BC%A5%D5%A5%A7%A5%A4%A5%B9
*/
#define NEWKEY 0xFBE5
// 機能 スクリーン・モードを変える。パレットは初期化しない。
// 入力 A にスクリーンモード (0~8)
void BIOS_CHGMOD(uint8_t mode) {
#asm
LD IX, 2
ADD IX, SP
LD A, (IX) ;// A = mode
CALL 005FH
#endasm
}
// 機能 画面クリア
void BIOS_CLS() {
#asm
XOR A ;//ゼロフラグをセット
CALL 00C3H
#endasm
}
// 機能 メモリから VRAM へブロック転送
// 入力 HL にソース・アドレス (メモリ)、DE にデスティネーション・アドレス (VRAM)、BC に長さ。指定する VRAM のアドレスは全ビット有効
void BIOS_LDIRVM(char* src, uint16_t* dst, uint16_t len) {
#asm
LD IX, 2
ADD IX, SP
LD BC,(IX) ;// len
LD DE,(IX+2) ;// dst
LD HL,(IX+4) ;// src
CALL 005CH
#endasm
}
// 機能 ジョイスティックの状態を返す
// 入力 A に調べるジョイスティックの番号
// 出力 A にジョイスティックの方向
uint8_t BIOS_GTSTCK(uint8_t triger) {
#asm
LD IX, 2
ADD IX, SP
LD A, (IX)
CALL 00D5H
LD L, A ; 戻り値を L レジスタにセット
LD H, 0
#endasm
}
// 機能 トリガボタンの状態を返す
// 入力 A に調べるトリガボタンの番号
// 0: キーボードのスペースキー
// 1: ジョイスティック1のボタン
// 出力 A が 0 ならばトリガボタンは押されていない
// A が 0FFH ならトリガボタンは押されている
uint8_t BIOS_GTTRIG(uint8_t triger) {
#asm
LD IX, 2
ADD IX, SP
LD A, (IX) ; A = triger
CALL 00D8H
LD L, A ; 戻り値を L レジスタにセット
LD H, 0
#endasm
}