2026年01月11日

Z80での高速な乱数発生方式


1.はじめに
 X(旧Twitter)のタイムラインで「ゲームでは1%の確率で100回に一度は当たらないと暴れる人が結構おられる」のでテーブルを参照することで一定の回数で必ず当たるようなロジックにしていると言うメッセージを見かけ成程なぁと思いました。
 Z80で乱数を実装する場合、従来は合同法を使っていましたが、テーブル引き(以降、テーブル方式と記す)にすれば合同法で必要な乗算処理も不要になり、高速化できると言うメリットもあります。
 今回はタイムラインからの情報をもとにZ80でのテーブル方式の乱数発生の高速化について書いてみたいと思います。


2.テーブル方式
 タイムラインで書かれているようにテーブル方式では要素数を256とし、テーブルを xx00h に配置することで高速化できます。
 例えば下記のようにすれば 53 ステートで乱数発生処理を実装できます。

GetRnd: LD A,(TblIdx) ; 13 INC A ; 4 LD (TblIdx),A ; 13 LD A,(RndTbl) ; 13 TblIdx EQU $ - 2 RET ; 10 ORG ($ + 255) and 0FF00H RndTbl: DB 02EH,082H,0C1H,011H,01FH,049H,02FH,058H ・ ・



3.テーブル方式の高速化案
 テーブル内の値に重複が無い場合には、乱数テーブルをリスト方式に変換することで次のように 36 ステートまで高速化できます。

リストテーブルでの高速な乱数生成処理(Z80アセンブラ)
;++++++++++++++++++++++++++ ; random list table test ; Ver 0.01 2026/01/11 ; by skyriver ;++++++++++++++++++++++++++ [0100] : ORG 0100H [0100] : 3A 18 02 GetRnd: LD A,(RndLst+18H) ; 13 18H is a initial value [0101] : RndPnt EQU $ - 2 [0103] : 32 01 01 LD (RndPnt),A ; 13 [0106] : C9 RET ; 10 ; total 36 [0200] : ORG ($ + 255) and 0FF00H [0200] : 42 69 BB 20 RndLst: DB 042H,069H,0bbH,020H,051H,0baH,040H,028H 51 BA 40 28 [0208] : 02 43 A6 44 DB 002H,043H,0a6H,044H,064H,080H,038H,003H 64 80 38 03 [0210] : 1E 1F 39 73 DB 01eH,01fH,039H,073H,075H,048H,02bH,016H 75 48 2B 16 [0218] : 2E E4 86 57 DB 02eH,0e4H,086H,057H,08fH,052H,0d4H,049H 8F 52 D4 49 [0220] : 4E 94 96 EE DB 04eH,094H,096H,0eeH,09bH,0c8H,019H,03cH 9B C8 19 3C [0228] : 29 17 E9 62 DB 029H,017H,0e9H,062H,09dH,047H,082H,058H 9D 47 82 58 [0230] : 13 12 0E 6E DB 013H,012H,00eH,06eH,0e5H,0b2H,0fbH,070H E5 B2 FB 70 [0238] : 2D 5E 01 AC DB 02dH,05eH,001H,0acH,088H,0d1H,0ceH,065H 88 D1 CE 65 [0240] : 56 F7 60 A8 DB 056H,0f7H,060H,0a8H,0a4H,0f6H,030H,0cbH A4 F6 30 CB [0248] : 72 2F 74 A7 DB 072H,02fH,074H,0a7H,0beH,063H,037H,0cfH BE 63 37 CF [0250] : 8E 5B 92 BF DB 08eH,05bH,092H,0bfH,078H,0b1H,01aH,07cH 78 B1 1A 7C [0258] : 7A B3 C7 3F DB 07aH,0b3H,0c7H,03fH,03eH,07eH,0abH,0f1H 3E 7E AB F1 [0260] : 9A 6A 0C 6C DB 09aH,06aH,00cH,06cH,04dH,0bcH,010H,0c6H 4D BC 10 C6 [0268] : 0A E3 C3 84 DB 00aH,0e3H,0c3H,084H,06fH,071H,07fH,079H 6F 71 7F 79 [0270] : 6D 14 54 5D DB 06dH,014H,054H,05dH,033H,089H,0ccH,009H 33 89 CC 09 [0278] : 83 B5 D5 4C DB 083H,0b5H,0d5H,04cH,0daH,026H,087H,08aH DA 26 87 8A [0280] : 22 DE C1 8B DB 022H,0deH,0c1H,08bH,095H,032H,06bH,090H 95 32 6B 90 [0288] : 9E A9 F4 0D DB 09eH,0a9H,0f4H,00dH,08dH,0ddH,045H,035H 8D DD 45 35 [0290] : 98 3A 93 ED DB 098H,03aH,093H,0edH,0b6H,0d6H,0a5H,0bdH B6 D6 A5 BD [0298] : AE C0 68 A3 DB 0aeH,0c0H,068H,0a3H,055H,005H,04bH,02aH 55 05 4B 2A [02A0] : 9F CD 46 A2 DB 09fH,0cdH,046H,0a2H,0f3H,0b4H,0b0H,0adH F3 B4 B0 AD [02A8] : B7 3B 2C 53 DB 0b7H,03bH,02cH,053H,059H,0b9H,03dH,0c2H 59 B9 3D C2 [02B0] : 9C B8 0F 4F DB 09cH,0b8H,00fH,04fH,024H,097H,007H,0ebH 24 97 07 EB [02B8] : 7D 15 67 D9 DB 07dH,015H,067H,0d9H,00bH,0d0H,0afH,0dcH 0B D0 AF DC [02C0] : 91 11 EA FC DB 091H,011H,0eaH,0fcH,050H,036H,0caH,0d2H 50 36 CA D2 [02C8] : 18 23 C5 A1 DB 018H,023H,0c5H,0a1H,006H,0e2H,08cH,0d3H 06 E2 8C D3 [02D0] : 81 5A 76 D7 DB 081H,05aH,076H,0d7H,0d8H,0f2H,01bH,05cH D8 F2 1B 5C [02D8] : 04 34 DB E1 DB 004H,034H,0dbH,0e1H,0dfH,0e8H,0e0H,085H DF E8 E0 85 [02E0] : 99 21 7B 08 DB 099H,021H,07bH,008H,0f0H,0e6H,0e7H,0ecH F0 E6 E7 EC [02E8] : A0 FD EF 25 DB 0a0H,0fdH,0efH,025H,0c9H,041H,000H,04aH C9 41 00 4A [02F0] : 5F 77 66 F5 DB 05fH,077H,066H,0f5H,0faH,0c4H,0f8H,027H FA C4 F8 27 [02F8] : F9 AA 1D 61 DB 0f9H,0aaH,01dH,061H,01cH,0feH,0ffH,031H 1C FE FF 31 END


■乱数テーブルのリスト化とは
 乱数の値自体をテーブルのインデックスとしてテーブルを順次辿って行った場合に、元データの乱数テーブルの順番通りに辿れる(元データの乱数列をリスト構造で連結する)ようにしたものをここではリスト化した乱数テーブルと表現しています。
 乱数テーブルをリスト化する具体的なサンプルコードを以下に示します。GenRndLst()でリスト化の処理を行っています。
※より判り易いように表現を変更 2026/01/12

乱数テーブルのリスト化処理の例(C言語)
/* * random list table test * Ver 0.01 2026/01/11 * by skyriver */ #include <stdio.h> #include <stdlib.h> #include <stdint.h> uint8_t RndTbl[ 256 ]; uint8_t RndLst[ 256 ]; void GenRndTbl( void ) { int pos, zeropos; zeropos = rand() & 0xff; // zero position for ( int i = 1; i< 256; i++ ) { pos = (rand() & 0xff) - 1; do { pos = (pos + 1) & 0xff; } while ( (pos == zeropos) || (RndTbl[ pos ] != 0) ); RndTbl[ pos ] = i; } } void GenRndLst( void ) { for ( int i = 0; i < 256; i++ ) { RndLst[ RndTbl[ i ] ] = RndTbl[ (i + 1) & 0xff ]; } } void DmpTbl( uint8_t *ValPnt ) { for ( int i = 0; i < 256; i++ ) { if ( ( i % 16 ) == 0 ) { printf( "\n%04x :", i ); } else if ( ( i % 8 ) == 0 ) { printf( " -" ); } printf( " %02x", *( ValPnt + i ) ); } } void GenAsmSrc( uint8_t *ValPnt ) { for ( int i = 0; i < 256; i++ ) { if ( ( i % 8 ) == 0 ) { printf( "\n\tDB\t" ); } printf( "0%02xH", *( ValPnt + i ) ); if ( ( i % 8 ) != 7 ) { putchar( ',' ); } } } int main( int argc, char *argv[] ) { srand( 1234 ); GenRndTbl(); printf( "\nRndTbl" ); DmpTbl( RndTbl ); GenRndLst(); printf( "\n\nRndLst" ); DmpTbl( RndLst ); printf( "\n\nAsm source of RndLst\n" ); GenAsmSrc( RndLst ); return 0; }

 上記のコードを実行した結果が下記になります。

実行結果
$ ./rndlst RndTbl 0000 : 2e 82 c1 11 1f 49 2f 58 - 7a d5 f2 66 10 1e d4 d8 0010 : 04 51 5b 3f 65 bc 0b 44 - a4 f3 f5 c4 50 8e 45 f6 0020 : f8 f9 aa 2c 9d 05 ba 67 - c6 ca c5 36 fb 61 6a c3 0030 : fc 1c 8f 35 b2 0f 03 20 - 4e 37 70 6d 71 14 75 89 0040 : a9 3b ac 59 b3 4f cf d3 - d7 5c 3e ce 8c 8d dd e8 0050 : a0 9f 2a e9 fd fe ff 31 - 12 39 5e ab 53 bf dc df 0060 : 85 32 0e 38 2d 47 cb a1 - cd e2 7b 4c be af c2 ea 0070 : ef 4a 74 33 6e 7f 8a f4 - fa 1d 52 92 93 ed 41 f7 0080 : 27 3c 88 9e 4b a7 ad b9 - 15 48 72 54 78 83 8b 0d 0090 : 80 22 96 a5 b4 24 9b a3 - a2 46 30 13 73 5d 7e 87 00a0 : 90 98 ae 3d d1 5a c7 d2 - 76 cc 06 40 56 1a 86 6b 00b0 : 84 95 d6 1b 57 7c da db - e1 21 94 b6 07 28 29 17 00c0 : 16 2b 62 0c 64 4d 63 6c - 6f 79 b5 97 bd d0 81 de 00d0 : e0 99 c0 91 3a 01 69 e3 - 08 02 bb d9 34 e5 e6 e7 00e0 : ec c9 23 ee 00 42 60 9a - 68 0a a6 b0 9c 55 b1 b8 00f0 : 7d 26 19 e4 f0 5f f1 77 - 09 43 a8 b7 eb 25 c8 18 RndLst 0000 : 42 69 bb 20 51 ba 40 28 - 02 43 a6 44 64 80 38 03 0010 : 1e 1f 39 73 75 48 2b 16 - 2e e4 86 57 8f 52 d4 49 0020 : 4e 94 96 ee 9b c8 19 3c - 29 17 e9 62 9d 47 82 58 0030 : 13 12 0e 6e e5 b2 fb 70 - 2d 5e 01 ac 88 d1 ce 65 0040 : 56 f7 60 a8 a4 f6 30 cb - 72 2f 74 a7 be 63 37 cf 0050 : 8e 5b 92 bf 78 b1 1a 7c - 7a b3 c7 3f 3e 7e ab f1 0060 : 9a 6a 0c 6c 4d bc 10 c6 - 0a e3 c3 84 6f 71 7f 79 0070 : 6d 14 54 5d 33 89 cc 09 - 83 b5 d5 4c da 26 87 8a 0080 : 22 de c1 8b 95 32 6b 90 - 9e a9 f4 0d 8d dd 45 35 0090 : 98 3a 93 ed b6 d6 a5 bd - ae c0 68 a3 55 05 4b 2a 00a0 : 9f cd 46 a2 f3 b4 b0 ad - b7 3b 2c 53 59 b9 3d c2 00b0 : 9c b8 0f 4f 24 97 07 eb - 7d 15 67 d9 0b d0 af dc 00c0 : 91 11 ea fc 50 36 ca d2 - 18 23 c5 a1 06 e2 8c d3 00d0 : 81 5a 76 d7 d8 f2 1b 5c - 04 34 db e1 df e8 e0 85 00e0 : 99 21 7b 08 f0 e6 e7 ec - a0 fd ef 25 c9 41 00 4a 00f0 : 5f 77 66 f5 fa c4 f8 27 - f9 aa 1d 61 1c fe ff 31 Asm source of RndLst DB 042H,069H,0bbH,020H,051H,0baH,040H,028H DB 002H,043H,0a6H,044H,064H,080H,038H,003H DB 01eH,01fH,039H,073H,075H,048H,02bH,016H DB 02eH,0e4H,086H,057H,08fH,052H,0d4H,049H DB 04eH,094H,096H,0eeH,09bH,0c8H,019H,03cH DB 029H,017H,0e9H,062H,09dH,047H,082H,058H DB 013H,012H,00eH,06eH,0e5H,0b2H,0fbH,070H DB 02dH,05eH,001H,0acH,088H,0d1H,0ceH,065H DB 056H,0f7H,060H,0a8H,0a4H,0f6H,030H,0cbH DB 072H,02fH,074H,0a7H,0beH,063H,037H,0cfH DB 08eH,05bH,092H,0bfH,078H,0b1H,01aH,07cH DB 07aH,0b3H,0c7H,03fH,03eH,07eH,0abH,0f1H DB 09aH,06aH,00cH,06cH,04dH,0bcH,010H,0c6H DB 00aH,0e3H,0c3H,084H,06fH,071H,07fH,079H DB 06dH,014H,054H,05dH,033H,089H,0ccH,009H DB 083H,0b5H,0d5H,04cH,0daH,026H,087H,08aH DB 022H,0deH,0c1H,08bH,095H,032H,06bH,090H DB 09eH,0a9H,0f4H,00dH,08dH,0ddH,045H,035H DB 098H,03aH,093H,0edH,0b6H,0d6H,0a5H,0bdH DB 0aeH,0c0H,068H,0a3H,055H,005H,04bH,02aH DB 09fH,0cdH,046H,0a2H,0f3H,0b4H,0b0H,0adH DB 0b7H,03bH,02cH,053H,059H,0b9H,03dH,0c2H DB 09cH,0b8H,00fH,04fH,024H,097H,007H,0ebH DB 07dH,015H,067H,0d9H,00bH,0d0H,0afH,0dcH DB 091H,011H,0eaH,0fcH,050H,036H,0caH,0d2H DB 018H,023H,0c5H,0a1H,006H,0e2H,08cH,0d3H DB 081H,05aH,076H,0d7H,0d8H,0f2H,01bH,05cH DB 004H,034H,0dbH,0e1H,0dfH,0e8H,0e0H,085H DB 099H,021H,07bH,008H,0f0H,0e6H,0e7H,0ecH DB 0a0H,0fdH,0efH,025H,0c9H,041H,000H,04aH DB 05fH,077H,066H,0f5H,0faH,0c4H,0f8H,027H DB 0f9H,0aaH,01dH,061H,01cH,0feH,0ffH,031H $


4.まとめ
 乱数テーブルをリスト化することでかなり高速になりました。今回提案したリスト方式はテーブル方式と比較して要素値の重複が許されない反面、要素数を少なくした場合でも処理の変更は不要(AND演算等の追加が不要)という特徴があります。また、処理内容はseedの読み込みと書き込みだけで加工処理が全く無いので究極の速度と言えるのではないでしょうか?
 乱数テーブルを使った方式は高速な反面、合同法等と比較し、
  • 乱数の周期が短い
  • メモリ消費が多い
等の短所もありますので実装する処理に合わせて適宜使い分けることが必要かと思います。
※リスト方式の特徴を追記 2026/01/18


★追記 2026/01/16
 処理が軽い乱数発生アルゴリズムとして Xorshift があります。
 上記で書いた周期が 256 のテーブル方式の乱数は 8bit の Xorshift で代用できるかもしれません。テーブル方式と同様に Xorshift8 は周期内で同じ値が出ることはありませんが、周期が 255 で 0 は出力されません。
 8bit の Xorshift の計算式をここで見つけたので、Z80 のアセンブラ用に書いてみたものが下記のソースになります。私がネット上で確認した限りでは Z80 での16bit 版 Xorshift の最速コードは Retro Programming のサイトに書いてあるもので RET を含めないで 20 バイトの 86 クロックと書かれていますが 82 クロックの間違いではないかと思います。
 下記の Xorshift8 では RET を含めなければ 17 バイトの 68 クロックになり、16bit 版よりも高速でコードも短くなるので Z80 を実装したレトロなマシンでのゲーム製作等で使えるかもしれませんね。

Xorshift8 Z80 version(Z80アセンブラ)
; Xorshift 8bits version for Z80 ; Ver 0.01 2026/01/16 by skyriver ; x ^= x >> 1 ; x ^= x << 1 ; x ^= x >> 2 ; ; 17 bytes, 68 clocks(excluding ret) ; ; A -> random value [0200] : 3E 01 XS8: LD A,1 [0201] : SEED8 EQU $ - 1 [0202] : 4F LD C,A [0203] : B7 OR A [0204] : 1F RRA [0205] : A9 XOR C [0206] : 4F LD C,A [0207] : 87 ADD A,A [0208] : A9 XOR C [0209] : 4F LD C,A [020A] : 1F RRA [020B] : B7 OR A [020C] : 1F RRA [020D] : A9 XOR C [020E] : 32 01 02 LD (SEED8),A [0211] : C9 RET

 参考として seed の初期値が1の場合に発生した乱数値も貼っておきます。周期が 255 なので先頭と末尾が同じ値になっています。

Xorshift8 で生成された乱数値
0000 : 03 07 0F 1E 3F 78 FF A0 - 14 2A 51 A9 06 0C 19 30 0010 : 66 C0 D8 EB 8A 45 83 57 - A5 1F 3C 7F F0 BE 2B 52 0020 : AE 09 12 26 48 99 60 CC - C1 DB EC 85 5B BC 2F 5A 0030 : BF 28 55 A1 17 2D 5E B7 - 39 74 E6 90 72 EA 89 42 0040 : 8C 49 9A 67 C3 DF E4 94 - 7A FB A8 05 0B 16 2E 59 0050 : B8 27 4B 9E 6F D2 FE A3 - 13 25 4F 96 7E F3 B9 24 0060 : 4C 91 71 ED 86 5C B3 31 - 65 C7 D7 F5 B5 3D 7C F7 0070 : B1 35 6D D6 F6 B2 32 62 - C8 C9 CA CD C2 DC E3 9B 0080 : 64 C4 D0 FA AB 02 04 08 - 11 21 47 87 5F B4 3E 7B 0090 : F8 AF 0A 15 29 56 A6 18 - 33 61 CF C6 D4 F2 BA 23 00A0 : 43 8F 4E 95 79 FC A7 1B - 34 6E D1 F9 AC 0D 1A 37 00B0 : 69 DE E7 93 75 E5 97 7D - F4 B6 3A 73 E9 8E 4D 92 00C0 : 76 E2 98 63 CB CE C5 D3 - FD A4 1C 3B 70 EE 81 53 00D0 : AD 0E 1D 38 77 E1 9F 6C - D5 F1 BD 2C 5D B0 36 6A 00E0 : D9 E8 8D 4A 9D 68 DD E0 - 9C 6B DA EF 82 54 A2 10 00F0 : 22 40 88 41 8B 46 84 58 - BB 20 44 80 50 AA 01 03


★追記 2026/01/24
 ネットで最初に左シフトする Xorshift8 の計算式を見つけました。
 RET を含めなければ 15 バイトで 60 クロックとなり更にコンパクト&高速になりました。

Xorshift8 Z80 version その2(Z80アセンブラ)
; Xorshift 8bit version for Z80 ; Ver 0.01 2026/01/24 by skyriver ; x ^= x << 1 ; x ^= x >> 1 ; x ^= x << 2 ; ; 15 bytes, 60 clocks(excluding ret) ; ; A -> random value [0200] : 3E 01 XS82: LD A,1 [0201] : SEED82 EQU $ - 1 [0202] : 4F LD C,A [0203] : 87 ADD A,A [0204] : A9 XOR C [0205] : 4F LD C,A [0206] : 1F RRA [0207] : A9 XOR C [0208] : 4F LD C,A [0209] : 87 ADD A,A [020A] : 87 ADD A,A [020B] : A9 XOR C [020C] : 32 01 02 LD (SEED82),A [020F] : C9 RET

 参考として seed の初期値が1の場合に発生した乱数値も貼っておきます。周期が 255 であることも確認できました。

Xorshift8 で生成された乱数値 その2
0000 : 0A 55 80 C0 E0 F0 78 FC - 1E FF 05 28 54 8A 95 60 0010 : 30 98 0C 66 03 1B D7 51 - A2 C1 EA A5 F8 3C FE 0F 0020 : 7D D4 4A 75 90 48 64 12 - 99 06 33 83 DB 37 A1 DA 0030 : 3D F4 5A FD 14 AA 85 E8 - B4 7A ED 9C 2E 67 09 4E 0040 : 57 91 42 31 92 59 E6 C3 - FB 27 29 5E DF 15 A0 D0 0050 : 68 74 9A 1D E4 D2 79 F6 - 4B 7F C5 C8 A4 F2 69 7E 0060 : CF 9D 24 32 89 8E B7 61 - 3A CD 8C A6 E3 EB AF AD 0070 : BC 3E EF 8D AC B6 6B 6F - 4D 4C 46 13 93 53 B3 43 0080 : 3B C7 D9 26 23 0B 5F D5 - 40 20 10 88 84 E2 E1 FA 0090 : 2D 7C DE 1F F5 50 A8 94 - 6A 65 18 CC 86 F3 63 2B 00A0 : 4F 5D C4 C2 F1 72 A9 9E - 3F E5 D8 2C 76 8B 9F 35 00B0 : B0 58 EC 96 7B E7 C9 AE - A7 E9 BE 2F 6D 5C CE 97 00C0 : 71 B2 49 6E 47 19 C6 D3 - 73 A3 CB BF 25 38 DC 0E 00D0 : 77 81 CA B5 70 B8 1C EE - 87 F9 36 AB 8F BD 34 BA 00E0 : 0D 6C 56 9B 17 B1 52 B9 - 16 BB 07 39 D6 5B F7 41 00F0 : 2A 45 08 44 02 11 82 D1 - 62 21 1A DD 04 22 01 0A


★追記 2026/05/10
 上記の「乱数テーブルのリスト化処理の例(C言語)」のソースの中でGenRndTbl()で乱数テーブルを生成しています。
 X(旧Twitter)のタイムラインでトランプをシャッフルする処理に関して話題にのぼり、より簡単(高速)にシャッフルする処理はこんな処理ということが判りました。

★追記 2026/05/14
 高速なシャッフル処理についてブログにまとめました。

★追記 2026/07/12
 Z80 での 16bit の xorshift に関しては「Retro Programming」のサイトが参考になります。


posted by skyriver at 14:39| Comment(0) | Z80 | このブログの読者になる | 更新情報をチェックする

2025年12月30日

X(Twitter)での今年(2025年)の振り返り


1.はじめに
 常々日記などは書いていないので今年も去年のようにX(旧Twitter)に投稿したメッセージで今年一年を振り返りたいと思います。


2.受賞メッセージ
 今年も個人的見解により賞を次のように決定しました。


2-1.いいね貰ったで賞
 今年はタイムラインで見かけた穿孔テープ情報が懐かしかったことがきっかけで開発を始めた穿孔テープ関連のメッセージで久々に10万以上のビューを頂きました。
 いいねを沢山頂いたメッセージに対する「いいね貰ったで賞」は下記に決まりました。

■第一位
 栄光の第一位は・・・フルスクラッチで開発中の穿孔テープリーダーの状況を書いたポストで、498個のいいねと14万ビューを頂きました^^



■第ニ位
 フルスクラッチで開発中のテープリーダーをPuntareaderと命名し、実装機能デモの動画を貼ったポストです。117個のいいねを頂きました。



■第三位
 68の日にポストした「自作のCP/M-68Kボード」の写真を添付したメッセージです。67個のいいねを頂きました。



2-2.予想外だったで賞
 下記の「秋月さんのZ80用Cコンパイラでの「食事する哲学者の問題」」のポストは私的には結構面白い内容だと思っていましたが、予想に反して「いいね」が1個も貰えませんでしたorz



2-3.懐かしかったで賞 ※追記 2026/01/01
 学生の頃、自作のマイコンを作成し始めた頃にパチパチスイッチでDMAによりメモリを設定し、アドレスとデータバスのLED表示くらいしか出力が無い(つまりZ80にはI/Oが全く無い)状態なのに研究室の先輩がリセットスイッチとアドレス表示のLEDを使ってピンポンゲームを作ったのを見て大変驚いた記憶があります。
 ゲーム内容の詳細までは覚えていませんが、今回、実装部品最小化を目指してプリント基板化して開発したパチパチマイコンボードで同様のゲームを作り、感慨深い思いでした。



3.まとめ
 いいね数のトップは穿孔テープ関連のメッセージがほぼ独占という結果になりました。ポスト時はそれほど反響があるとは思ってもいませんでしたが海外の技術系のサイトでも紹介して頂いたことから予想を遥かに上回る反応に驚きました。逆に「食事する哲学者の問題」は・・・

 最後に2025年に投稿した主要なメッセージのサマリを表にまとめましたので貼っておきます。いいねとビュー数は2025/12/30時点で確認した数値です。

No. ranking date content like view
1 2025/01/26 Z80パチパチマイコン(Z80Pachin) 47 5,868
2 2025/02/05 I/Oが全く無いパチパチマイコン(Z80Pachin)でゲーム 16 3,474
3 2025/03/01 一次元ライフゲーム 38 2,354
4 2025/03/01 三ッ池公園 3 686
5 2025/03/01 デルタ変調を使った音声合成 6 838
6 2025/03/21 素数生成プログラミングコンテスト 5 817
7 ★3 2025/06/08 自作のCP/M-68Kボード 67 2,189
8 2025/06/27 Z80クイズ 全メモリ同一値設定クイズ 52 8,911
9 2025/07/31 東芝製のZ80互換CPU(TMPZ84C015)を使ったプリント基板 34 5,559
10 2025/08/23 Free版MITOUJTAGでのXC9572で書込み実験 17 2,284
11 2025/09/09 Z80での高速なバイナリデータの10進数変換 11 673
12 2025/09/20 Z80での高速な16bitの平方根処理 6 469
13 2025/09/26 AKI-80 用のCコンパイラをZ-Visionに連携させたソースディバッグ 14 1,349
14 2025/10/02 秋月さんのZ80用Cコンパイラでの「食事する哲学者の問題」 0 453
15 2025/10/13 穿孔テープのDXFファイルを生成するツール作成 42 3.3万
16 ★1 2025/11/21 穿孔テープのリーダーをフルスクラッチで開発中 498 14万
17 ★2 2025/12/03 穿孔テープのリーダーをフルスクラッチで開発中でPuntareaderと命名 117 1.2万
18 2025/12/15 スクラッチで開発中の紙テープリーダー(Pantareader)のケースが完成 55 3,427


posted by skyriver at 22:51| Comment(0) | 日記 | このブログの読者になる | 更新情報をチェックする

2025年12月15日

穿孔テープの再現実験(その5)紙テープリーダーの開発(ケース作成)


1.はじめに
 前回の記事で今回開発中の穿孔テープ(以降、紙テープと記す)リーダーに実装する機能について書きましたが、今回はケースの作成についてメモしておきたいと思います。


2.ケース検討でネックになる点
 下の写真は今回作成した紙テープリーダー(Pantareader)の制御部の写真ですが、裏側の赤外線LEDへの電源供給のための白いコネクタのサイズが大きく、コンパクトなケースを設計する上でネックになりました。

紙テープリーダーの試作機(再掲)

 そこで基板には電源用のケーブルを直付けしてケーブル同士をコネクタで接続する方式にしました。使用するコネクタは1.25mmピッチのマイクロコネクタです。AliExpressさんで手配したので届くまで一週間程度かかりました。
 下の写真はマイクロコネクタを使って接続した様子です。ピッタリ収まりましたね^^

マイクロコネクタでの結線状態


3.CADでのケース設計
 CADを使って設計したケースが下図になります。想定通りにコンパクトにまとまりました。

紙テープリーダーのケース設計その1(CAD画面)

 ケースの上側を非表示にすると下図のようになります。下図では見えていませんが右サイドにはマイクロコネクタを格納するための空間を設けています。

紙テープリーダーのケース設計その2(CAD画面)

 ケースの上側の内部が下図になります。ケースをコンパクトにするためにリーダー制御部が辛うじて格納できるサイズにしていて制御部の格納時に少し出っ張っているUSBコネクタが通る溝を設けました。格納作業はちょっとしたパズルのようになりますw

ケースの内部設計その3(CAD画面)


4.3Dプリンタでの出力
 紙テープリーダーの制御部をケースに入れた状態が下の写真です。
 マイクロコネクタも綺麗に収まっていますね。

ケースに収めた制御部

 下の写真は完成した紙テープリーダーのです。いつもはPEIプレートの凹凸が上面に転写されてかなり綺麗に仕上がるのですが、試作造形作業の途中でフィラメントを交換してから少し不調です(1層目の流量を増やしたいのですが流量キャリブレーションしても変わらず)。
 ★追記 2025/12/17 動的流量キャリブレーションを行うことで問題の現象は8割方解決しました。
右端の緑色の部分は制御基板のLEDの光です。

完成した紙テープリーダー


完成した紙テープリーダー(その2)
※2025/12/20 追加


5.まとめ
 今回のケース作成ではコンパクトにするために制御部を格納できるギリギリの大きさで作ったので試作時の造形リトライ回数が普段よりも多めになってしまいました。また、ケース検討時に思い付きでマイクロコネクタに変更するために手配したり、今まで好調だったプリンタの調子が悪くなったりで、想定より時間が掛かってしまいました。
 紙テープリーダーに関しては今回のケース作成で一段しましたので次のことを検討していきたいと思います。


★追記 2025/12/16
 久々にLCD方式の3Dプリンタでもケースを造形してみました。
 このような形状であればビルドプレートに対して斜めに配置するのが一般的だと思いますが、トップパネルの部分にビルトプレートの質感を転写したかったのでビルドプレートに直置きにしています。斜めの平面部分には積層ピッチが拡大されて現れてしまうことも斜めに配置したくない理由です。
 そのままだとサポートとケースがボトム面付近で一体化してしまうので、ボトム設定で「Platform Touch Shape」を「none」に設定変更しています。

LCD方式でのサポート生成状況

 下の写真は造形したケースです。LCD方式では評価のために最近購入しておいた「ELEGOO ABSライク3.0 8Kレジン」を使用しました。FDM方式で使用したフィラメントはPETGです。
 色が違うので比較しにくいですが、LCD側は流石に文字などの細部まで綺麗に出力されていますが、側面では目視では見えない積層痕により光が変に反射されてしまいます。この問題は紫外線防止用のラッカー等を塗布すれば対処できますがFDM方式に比べ手が掛かるのに更なる手間は避けたいところです。
 また、写真では判り辛いですがトップ面にはビルドプレートの質感がしっかり転写されていてしぶい感じに仕上がっています。
 今回、ABSライクレジンを初めて使いましたが、確かに強度的には従来のものより靱性は高そうで、ケース作成にも使えそうです(経年変化の影響は現時点では未知数)。

ケースの造形比較(左:LCD方式、右:FDM方式)




[TOP] [ 前へ ] 穿孔テープの再現実験 [ 次へ ]

posted by skyriver at 17:41| Comment(0) | RetroDevice | このブログの読者になる | 更新情報をチェックする