ZX Spectrum 向けのデモシーンイントロを作成する

2026/10/13 4:40

ZX Spectrum 向けのデモシーンイントロを作成する

RSS: https://news.ycombinator.com/rss

要約▶

Japanese Translation:

著者は、標準的な 128KB の ZX Spectrum にて手書きのレトロなイントロを成功裏に作成し、高度に最適化されたアセンブリ言語プログラミングにより複雑なビジュアルとオーディオを実現した。2 ヵ月間(2025 年 12 月から開始)にわたり、約 19KB のコード(具体的には 10287 バイトのメインルーチン)を書き下し、内蔵 ROM を書き換えることでカスタムフォント「Cartoon」を用いたスムーズなスクロールテキストを作成し、また Amiga モジュール「Milkman」を変換して 3 チャネル AY サウンドトラックを生成した。限られたメモリ制限を管理するため、アセットは BASIC ロードに分割され、ルーチンはオーバーヘッドを避けるために特定のアドレスでハードコーディングされた。技術的な最適化としては、Z80 RL 命令を用いてスクロールテキストの回転を実現し、スキャンライン衝突を避けるために Ruby で生成した座標テーブルを事前計算してスターフィールド効果を再現し、さらにサウンドチップから直接振幅レジスタを読み取ってバウンス VU メーターを実装している。プロジェクトは 1980 年代後半の Amiga クrack イントロに触発され、本物の Spectrum +3上でローカル TNFS サポートのある Makefile 駆動のビルドシステムを用いて開発された。最終的な.tap ファイルは Web ブラウザまたは pouet.net を経由して入手でき、レトロなハードウェア上で高忠実度な体験を提供し、極限を効率的に達成したコーディングの実証として立っている。

本文

レトロ風の『クラック・イントロ』開発記録:Speccy, Z80 アセンブリと 3 チャンネル AY サウンドの冒険

更新日: 2026 年 10 月 12 日


今すぐダウンロード


イントロダクション

  • 開発経緯

    • 80 年代後半に Sinclair BASIC や雑誌の汇编(アセンブリ)プログラムをタイピングし、友人宅の Amiga クラック・イントロを ZX スペクトラムで再現しようとした過去がある。
    • 当時多大な時間を費やしたが成功せず、現在はようやく実現できた。
    • 開発期間: 約 1 年(2025 年 12 月 13 日以降)。
    • コード生産速度: 平均約 455 バイト/週。
  • 作品概要

    • プラットフォーム: 標準仕様の 128KB スペクトラム(Sinclair ZX Spectrum)。
    • サイズ: コード約 10,287 バイト、フル・タペイメージ 19,552 バイト。
    • 特徴: 80 年代後半の流行語をすべて盛り込んだレトロ風デモシーン・イントロ。
      • スムーズなスクロールテキスト & 「leet」カスタムフォント
      • 3 チャンネル AY サウンドトラック
      • VU メーターによるバウンス効果
      • パララックス星空

Be Kind, Rewind(背景と着想)

  • Amiga クラックトロの衝撃

    • 8 ビット機のカセットロード時代、Amiga のグラフィック・サウンド・ゲームライブラリに圧倒された。
    • 特に違法コピーされたゲームの冒頭にある**「イントロ(クラックトロ)」**に魅了された。
    • 音楽、グラフィック、エフェクトが組み合わさったミニチュア芸術作品としての側面がある。
  • 当時のトレンド要素

    • スクリーン上部のクールなロゴ(血液垂れ流しやメタル風など)。
    • エフェクト上に浮かぶ誇らしげなテキスト(スクロールするパララックス星空や 3D オブジェクトなど)。
    • 仲間へのオマージュ、クラッカーたちへの挨拶、違法 BBS システムの広告。
  • 音楽的インスピレーション

    • 『レミングス』のような 90 年代初頭の流行楽曲(Skid Row など)が典型的な Amiga クラックトロとして定着した。
    • 「サイン波スクリーン」「星空」「自慢げなテキスト」 の融合が最高だったと振り返る。
  • プロジェクトのきっかけ

    • Amiga からスペクトラムへ機種変更、Z80 コードの手応えを再び感じたい。
    • 友人「Desertkun」(新しい WiFi ネットワークカード開発者)から、「なぜ Z80 アセンブリを書かないか?」という挑戦を受けたことがトリガーになった。
    • 独立したイントロを作成し、「シーン」系の作品作家になりたいと決意した。

開発環境

  • 基本スタック

    • Pasmo アセンブラを Makefile で駆動するビルドシステム。
    • zmakebas
      のフォーク版(BASIC ファイル向け)。
    • テスト用 FUSE エミュレーター。
  • ハードウェアテスト

    • .tap
      ファイルをローカル TNFS サーバーにアップロードし、+3 で実行。
  • 重要ツール

    • Web ベースのアセンブルエディタ
      • Z80 命令の参照、サンプルコードの実行、レジスタ状態確認が可能。
      • djnz
        のステップ実行や、ビットシフト時の Carry フラグ動作などを視覚的に理解できた。
    • メモ帳とペン(デバッグツール)
      • 上位言語とは異なる構造のため、バイトとビットマップを手書き図に描画。
      • レジスタフラグの表を作成し、画面メモリーのチャンクを作業範囲で追跡。
      • 犬たちによる「ガチョウの代わり役(Rubber Ducking)」: デバッグ中の独り言を聞きながら思考整理を行った。

スタート地点と Hello World

  • 初期設定

    • Hello, world!
      を確認し、ロゴと背景(ステージ)の読み込みを実装。
    • TNFS サイトのヘッダー風デザインを採用し、青いガイドバーを追加。
    • 画面メモリー: アドレス
      $8000
      から開始(16384 進)、長さは 6912 バイト。
  • 基本命令の理解

    • out
      : ULA を介してボーダー色を設定。
    • incbin
      : Pasmo でバイナリファイルを読み込み。
    • ldir
      : Z80 のブロックコピー命令による画面描画。
org $8000

screen  EQU $4000 ; 画面メモリーの先頭アドレス
scrlen  EQU 6912
ula     EQU $FE   ; ULA I/O ポート
black   EQU 0     ; コーナーカラー

start:
  ld a,black      ; ボーダーを黒に設定
  out (ula),a

  ; ロゴヘッダー画像をコピー
  ld hl,header    ; ソースアドレス
  ld de,screen    ; デスティネーション
  ld bc,scrlen
  ldir            ; ブロックコピー

hold:
  halt            ; 次のフレームへ待機
  jr hold

header:
  incbin "assets/header.scr"

end start
  • ROM ルーチンの活用
    • カーソル制御 (
      at
      ,
      row
      ,
      col
      ) と ROM の
      pr_string
      ルーチンを使用してテキスト表示を実現。
    • PR_STRING は各文字へのループ処理を示しており、レジスタの動きを追う練習となった。

スタイル追加:フォントと「leet」感

  • 問題点: 標準フォントがデモシーンの雰囲気不足だった。
  • 解決策: Jim Blimey 氏のコレクションから「カートゥーン風フォント」を採用。
  • 実装ポイント:
    • ROM のフォント参照アドレス(
      $5C36
      )を書き換え、独自のフォントデータを読み込み。
chars   EQU $5C36 ; フォント参照アドレス

  ld hl,myfont-256 ; HL = フォントアドレス(256 オフセット調整)
  ld (chars),hl    ; ROM を新しいフォントに指示

; ... コードの続き ...

myfont:
  include "textfont.asm" ; カートゥーン風フォント
  • 成果: 「31337(leet)」な雰囲気になり、2 週間での進展が感じられた。

呪われた画面レイアウトとスクロールテキスト

  • Speccy の奇妙なメモリー配置

    • ビットマップ部分は交互行(interleaved rows)で構成され、1 ピクセル進めるごとに 8 ライン下がる構造になっている。
    • このため、X/Y アドレスをメモリーアドレスに変換する複雑な処理が必要となる。
  • 画面移動の「安易な手」(Tricks)

    • 交互行の特性を活かし、
      inc l
      /
      dec l
      で横方向、
      inc h
      /
      dec h
      で縦方向を素早く移動可能。
    • キャラクターセル(32 ピクセル)の全移動には、HL レジスタの High バイトに 32 を加算する処理を追加。
  • 滑らかなスクロールの実装

    • ROM の印刷ルーチンを使わず、フォントデータを直接読み込み、ピクセルごとにストリーミング描画。
    • 「回転左(Rotate Left)」命令 (
      rl
      )
      を活用:
      • バイトを左へシフトし、最下位ビット(Carry フラグ)に新たなピクセルを挿入。
      • 32 ビット分ループして、画面全体を 1 ピクセル移動させる。
dot       EQU %00000001     ; 右端のピクセルのみ点灯
newdot:
  ld a,dot                 ; ドット形状を読み込み
  ld (lineend),a           ; ライン末尾に保存

frame:
  halt                     ; フレーム待機
  
  ld hl,lineend            ; HL = ライン末尾(右端)
shift:
  rl (hl)                  ; バイトを左に回転(ピクセルを左へ移動)
  dec hl                   ; 次のバイトへ指す
  djnz shift               ; 32 ピクセル分ループ
  
  jr c,newdot              ; Carry フラグがセット=ドットが画面外に出たのでリセット
  jr frame                 // カードに描画中の位置にピクセルが移動し、次のフレームへ

  • 描画ロジックの効率化
    • ASCII コードからフォントデータを取得し、
      add a,a
      (左シフト)でビット操作を高速化。
    • フレームごとに 256 バイトを再描画するため、アセンブリ言語特有の処理速度の重要性を実感した。

音楽:Amiga モジュールから 3 チャンネル AY へ

  • ハードウェアの制約

    • Speccy は初期モデルでは単なる「ビーパ」だが、128KB モデルには 3 チャンネル AY-3-8912 サウンドチップが搭載。
    • Amiga の多チャンネル音楽(モジュール)を移植する必要があるため、工夫が必要だった。
  • 楽曲の選定:「Milkman」

    • 1989 年リリースの「Sounds Of Gnome」から、短くコード進行が単純なトラックを選び。
    • 4 チャンネルの Amiga モデルを 3 チャンネルへ圧縮し、VU メーターやグラウンディングサウンドを追加。
  • コンバート手法:Vortex Tracker II

    • OpenMPT で元のモジュールを読み込み、チャンネルと音高スライドダウン(例:A#からベースノートへ)を調整。
    • 「装飾(Ornaments)」: ノートを高速切り替えさせ、2 チャンネルで 3 和音(トリアド)を構築する技術を使用。
      • 例: C メジャーコードを C(1 チャン)、D#(2 チャン)+G(装飾) で再現。
  • 再生ルーチンの実装

    • アーカイブから取得したバイナリオブジェクト(PT3Play)をアドレス
      $C000
      に読み込み、ハードコーディングして使用。
player EQU $C000      ; プレイヤー起動アドレス
plinit EQU player+3
plplay EQU player+5

  ld hl,moduleimg      ; モジュールファイルアドレス
  call plinit          ; 初期化
  halt                 ; フレーム待機
  
hold:
  call plplay          ; 1 フレームごとの再生
  call scroll          ; スクロール処理(他)
  jr hold              ; ループ

moduleimg:
  incbin "assets/music.pt3"

星空:パララックスと衝突回避

  • 古典的アプローチの問題

    • ライン全体をシフトすると他のオブジェクトがぼやけ(smear)、フレーム速度が遅くなる。
    • テキスト描画との兼ね合いで、星を描画する前に「占有セル」を確認する必要があった。
  • 事前計算された座標テーブル

    • Ruby スクリプトを使用して、重複しない Y 座標の配置を生成し、ランダム数値(RNG)を排除。
    • 画面アドレス直接指定により、フレームごとの変換コストを削減。
stdata:
  defb 109, 25,  88,182,  42, 96, ... ; X,Y 座標とマスクのテーブル
  ; 32 つの星分のデータを定義
  • 衝突チェックと移動

    • 「タイプライター」ルーチン: テキスト描画時に占有セルをマーキング(1 に設定)。
    • 星を描画前に
      OR
      演算で占有確認を行い、被っている場合はスキップ。
    • rlca
      でビットパターンを左へシフトし、Carry フラグから新しいピクセルを投入。
  • 視覚的効果

    • スペース文字(空白)は描画せず、星がテキストの隙間をすり抜ける演出を実現。
    • 全大文字フォントを使用することで、ブロック状のキャラクタと星空のコントラストを強調。

雑記:VU メーターとその他のエフェクト

  • VU メーター

    • 複雑なイコライザーではなく、振幅値を読み取ってバーの高さを変動させるシンプルな実装。
    • AY チップのレジスタ
      $FFFD
      を書き出して読み込み、チャンネル A/B/C の振幅を取得。
  • Twinkle, Twinkle(ロゴ背景の星)

    • ランダムな瞬き効果を実現。
    • 擬似乱数生成器として、ROM の初期部分からアドレスをインクリメントして「ランダム」バイトを選択するテクニックを使用。
  • スペースアウト(メモリ管理)

    • アセット(画像・バイナリ)をプログラム内に
      incbin
      で読み込むとメモリー不足に陥る問題が発生。
    • 解決策として、多段階 BASIC テープローダーを採用し、個別のコードブロックに分けてロードした。
10 CLEAR 32767
20 BORDER 0: PAPER 0: INK 0: CLS
30 LOAD "" CODE         ; メインプログラム
40 LOAD "" CODE         ; プレイヤー($C000)
50 LOAD "" CODE         ; 背景画像
60 RANDOMIZE USR 32768

Z80 の禅:総括と感謝

  • プロジェクトの特性

    • 子供時代の夢をかなえ、ハードウェアに近いレベルでのコーディングを楽しめた。
    • バイナリ操作やレジスタ処理を通じて、「機械そのもの」として思考する訓練になった。
    • 挫折と再挑戦を繰り返した longest(最長)な開発プロジェクトとなった。
  • 学びの重要性

    • 現代のツールや GitHub リポジトリ、YouTube チューターがあったからこその達成感がある。
    • もしカセットレコーダーとメモ帳のみで実現していたら、どれほど長期化いただろうかと想像する。
  • アセンブリ言語への敬意

    • 精神衛生を優先し、日常業務での使用は控えるが、ハードウェアハッキングや極限の試みとしては最適。
    • 80 年代の子供たち(寝室コーディング)やシーネラーたちの情熱に感謝し、グラスを持ち上げて敬意を表す。

「ハッカー、グラフィシャン、プロトラッカーたちにアピールします」

同じ日のほかのニュース

一覧に戻る →

2026/10/13 6:40

AI は道具です。それを巧みに使うには技術が必要です。

## 日本語翻訳: 本稿の核心的な論点は、大規模言語モデルは自律的な「自動化」ではなく、人間の技量が必要なツールであるというものである。これは、AI が独立した意思あるいは悪意を持って行動するという考え方を否定するものであり、ソフトウェアが「反逆する(rogue)」ように振る舞うなど、業界特有の成り行きや陰謀論的なナラティブに煽られておりやすい。物理的な器具が悪用され得るように、LLM もエンジニアリング上の制限によって予期せぬ出力を生み出すに過ぎず、エージェント性の喪失によるものではない。人間による判断が依然として中核をなすのは、ユーザーが盲目的に制御権を委ねるのではなく、フィードバックループ内で結果を検証し、プロンプトを見直し、変更を検証するからです。本稿は AI を記述するために使用される擬人化された言語を批判しており、「陰謀」などの用語は技術的な問題が存在する場所に人間の動意を不当に暗示することを示唆しているとしています。 今後の議論では、AI を別個の存在として描く枠組みから転じ、解釈への問いかけや誤りへの認識においてユーザーの専門性を育むことに焦点を移すべきです。開発者および企業に対しては、恐怖を煽る比喩ではなく正確な工学用語を採用することで、より良いリスク管理と説明責任を実現できます。真の熟達とは、どのような質問が重要かを理解し、熟練した運用と盲目的な委任を見極めることであり、不完全なパフォーマンスがツールの有用性や作業者の責任を否定するものではありません。

2026/10/13 1:13

C で構築されたモダンな Web アプリ

## Japanese Translation: 本テキストは、2026 年に C と CGI を OpenBSD 上で構築された独自の商用 Web アプリケーション「marketyour.games」について説明しています。このプロジェクトは現代のフレームワークよりも極度な簡潔性とセキュリティを優先しており、「BCHS」スタック(OpenBSD、C、httpd、SQLite)を採用し、外部のフレームワークや独立したデータベースサーバーは一切使用しません。核心的な革新点は、アプリケーション全体が静的にリンクされた単一のバイナリとして動作し、ランタイム依存関係がゼロであるというアーキテクチャにあります。デプロイはファイルを 1 つだけフォルダに配置するだけであり、古いバージョンを置き換えるだけで済みます。再起動やダウンタイムも不要です。 セキュリティは OpenBSD のデフォルト設定を通じて強制されており、httpd に対して `chroot` を適用し、C プログラムに対して `pledge` および `unveil` などのツールを使用して制約を課します。アーキテクチャは、すべての HTTP リクエストごとに新しいプロセスをフォークし、コードから直接アセットを提供することでメモリ内に完全に収まり、すべてのトラフィックを httpd を介して CGI バイナリにルーティングするという方式に基づいています。このアプローチでは JavaScript テンプレート言語を使用しない(プログレッシブ改善に従う)とともに、安定した CGI 1.1 規格に準拠しますが、使いやすさを犠牲にして制御性を追求します。 主な利点としては、サプライチェーンリスクが著しく低減すること—依存するのは C コンパイラーと 3 つのライブラリ(`libcurl`、`libsodium`、組み込み済みの `libcjson`)のみ—、そして GDB のような標準ツールによるデバッグが容易であることです。アプリケーションは通常の実行ファイルだからです。しかしながら、この手法では開発者がデータを解析するためのロジック(クッキー、クエリ、フォーム)やカスタムヘッダーの管理を自ら実装する必要があり、複雑な依存関係グラフではなく、基本的な HTTP 概念と Vim のような古典的なツール(プラグインなし)を活用する姿勢を選択します。

2026/10/12 21:16

欧州のスーパーマーケット向け冷凍庫でハッカーが自動除霜機能を作動させた件

## Japanese Translation: 重大なサイバー攻撃が、欧州主要スーパーマーケットの冷凍管理システムを深刻に混乱させ、単位が危険な温度(例えば 50 デgree セルシウス)で動作不良を起こしています。フランスの小売業者——インターマーシェ、レクルー、coopérative U を含む——は、その施設が侵害されていることを確認し、電子棚ラベルを使用した動的価格設定に関する配送遅延やエラーを招いています。coopérative U の社長であるドミニク・シュルシェル氏は、状況を「極めて深刻」と表現し、昨夜から複数の店舗の生産施設が標的になっていると指摘しています。それでもなお、チームは危機の解決に向けて動いています。今回の攻撃は、Danfoss 製冷凍制御システムにおける脆弱性を悪用しており、多数の大規模な食料品ネットワークを同時に影響を与えています。介入が行われなければ、継続的な解凍により広範な食品の廃棄を引き起こす可能性があります。当局は、間もなく本格的な調査を開始し、侵害の全体範囲と起源を明らかにする予定となっています。ラ・デペシュからの報道によると、この事件は欧州小売業全体を脅かす産業制御システムにおける重大なセキュリティ弱点を浮き彫りにし、 Escalating サイバー脅威に対するより良いデジタルインフラ保護の切迫した必要性を強調しています。

ZX Spectrum 向けのデモシーンイントロを作成する | そっか~ニュース