RETROF-16Mプロセッサ 自己診断用テストプログラム
本ページの概略
画像はTTLのみで作成した16bitコンピュータ「RETROF-16M」です。
本頁は、このRETROF-16Mの、自己診断用に作成したインベーダーゲーム風のアプリケーションの全ソースコードを紹介するためのものです。
このソースコードはRETROF-16Mの命令セットを最大限活用するために考案した独自言語BAC+で記述されています。
このソースコードは専用のIDE(統合開発環境)でコンパイルされます。以下がそのIDEのスクリーンショットです。
このIDEもC++/CLI(マイクロソフト社が独自拡張したC++言語)を用いて筆者が自作しました。コンパイルだけではなく、デバッグやエミュレート、16進ダンプ、逆アセンブル等の機能も有しています。
このIDEで作成されたオブジェクトコードはUSBケーブルで実機(本頁冒頭の写真)に転送されます。
実機はメモリ以外はすべてTTL(74シリーズ標準ロジック)で構成されていますが、このオブジェクトコード転送の為に、唯一の例外としてFT245RL(USB送受信用のチップ)を使用しています。
全ソースコード
//
// RETROF-16M TEST PROGRAM
// MAR. 2016 GATARO.RETROF
VAR EndFlag($10) VAR Ino($11) VAR HITtype($12) VAR Direction($13)
VAR Edge($14) VAR Down($15) VAR Time($16) VAR Step($17)
VAR Patt($18) VAR Color($19) VAR XY($20) VAR Rnd($21)
VAR BasePos($30) VAR BaseBeamPos($31) VAR BaseBeamWait($32)
VAR InvPos($33) VAR InvWait($34) VAR InvNumber($35)
VAR InvBeamPos($36) VAR InvBeamWait($37)
VAR UfoPos($38) VAR UfoWait($39) VAR UfoDir($40)
VAR INVADER_STYLE(55) // PATTAERN(Upper8bit) + COLOR(Lower8bit)
CONST INVADER
(0 0 0 0 0 0 #0000 #0180 #03C0 #07E0 #0DB0 #0FF0 #0240 #05A0 #0A50 #0000
0 0 0 0 0 0 #0000 #0180 #03C0 #07E0 #0DB0 #0FF0 #05A0 #0240 #0420 #0000
0 0 0 0 0 0 #0000 #0410 #0220 #07F0 #0DD8 #1FFC #17F4 #1414 #0360 #0000
0 0 0 0 0 0 #0000 #0820 #2448 #2FE8 #3BB8 #3FF8 #1FF0 #0820 #1010 #0000
0 0 0 0 0 0 #0000 #03C0 #1FF8 #3FFC #399C #3FFC #0660 #0DB0 #300C #0000
0 0 0 0 0 0 #0000 #03C0 #1FF8 #3FFC #399C #3FFC #0E70 #1998 #0C30 #0000)
CONST UFO
(#03F0 0 #0FFC 0 #1FFE 0 #36DB 0 #7FFF #8000 #1CCE 0 #0804 0)
CONST EXPLOSION_UFO
(#41D2 #8000 #1BEC 0 #2BFE 0 #16DB 0 #7FFB #8000 #0CCE 0 #2925 0)
CONST DELTA // Relative position of invaders
(#0000 #0010 #0020 #0030 #0040 #0050 #0060 #0070 #0080 #0090 #00A0
#1000 #1010 #1020 #1030 #1040 #1050 #1060 #1070 #1080 #1090 #10A0
#2000 #2010 #2020 #2030 #2040 #2050 #2060 #2070 #2080 #2090 #20A0
#3000 #3010 #3020 #3030 #3040 #3050 #3060 #3070 #3080 #3090 #30A0
#4000 #4010 #4020 #4030 #4040 #4050 #4060 #4070 #4080 #4090 #40A0)
CONST INIT_INVADER_STYLE // PATTAERN(Upper8bit) + COLOR(Lower8bit)
(#000C #000C #000C #000C #000C #000C #000C #000C #000C #000C #000C
#200F #200F #200F #200F #200F #200F #200F #200F #200F #200F #200F
#200F #200F #200F #200F #200F #200F #200F #200F #200F #200F #200F
#4033 #4033 #4033 #4033 #4033 #4033 #4033 #4033 #4033 #4033 #4033
#4033 #4033 #4033 #4033 #4033 #4033 #4033 #4033 #4033 #4033 #4033)
CONST BEAM
(#8000 #4000 #2000 #4000 #8000 #4000 #2000 #4000 #0000 #0000 #0000)
CONST HITMARK1
(#0000 #0220 #1144 #0808 #0410 #3006 #0410 #0948 #1224 #0410 #0000)
CONST HITMARK2
(#0000 #1088 #0410 #0FF0 #1FF8 #1FF8 #0FE0 #0440 #1208 #0410 #0000)
CONST LAUNCHER
(#0180 #03C0 #03C0 #1FF8 #3FFC #3FFC #3FFC #3FFC)
CONST BLOCK
(#03FF #C0FF #07FF #E0FF #0FFF #F0FF #1FFF #F800 #3FFF #FCFF #7FFF #FEFF
#FFFF #FFFF #FFFF #FFFF #FFFF #FFFF #FFFF #FFFF #FFFF #FFFF #FFFF #FFFF
#FFFF #FFFF #FFFF #FFFF #FFFF #FFFF #FFFF #FFFF #FFFF #FFFF #FFFF #FFFF
#FF00 #FFFF #FE00 #7FFF #FC00 #3FFF #FC00 #3FFF #FC00 #3FFF #FC00 #3FFF
#FC00 #3FFF)
<CLEAR_ALL> 0=XY [0=@XY ++XY,];
<DRAW_LINE> #F410=XY 1=Y[ #DF=X[ #3C=@XY ++XY --X'] XY+#20=XY --Y'] ;
<DRAW_BLOCKS>
#C028=XY 3=N[
BLOCK=Patt 24=Y[
%Patt=P 15=X [P|#7FFF *[100=@XY] P+P=P ++XY --X'] ++Patt
%Patt=P 7=X [P|#7FFF *[100=@XY] P+P=P ++XY --X'] ++Patt XY+232=XY
--Y'] XY+#E833=XY
--N']
;
<DRAW_A_INVADER> // input Ino
INVADER_STYLE + Ino = W // Style-Color Address
%W & #00FF = Color // Color Value
%W >> >> >> >> >> >> >> >> = W // Style Index
INVADER+W+Step = Patt // Style Address
DELTA + Ino = W // Delta of the invader
InvPos + %W = XY // Position of the invader
XY & #00FF:#00E8==[1=Edge] // Right Edge Check
XY & #00FF:#0008==[2=Edge] // Left Edge Check
XY & #F800:#D800==[2=EndFlag] // Game over
14=Y[ %Patt=P 15=X[ P|#7FFF *[Color=@XY][0=@XY] P+P=P ++XY --X']
XY+240=XY ++Patt --Y']
;
<DRAW_UFO> // input UfoPos Patt
UfoPos=XY 6=Y[
%Patt=P 15=X [P|#7FFF *[#3C=@XY][0=@XY] P+P=P ++XY --X'] ++Patt
%Patt=P 2=X [P|#7FFF *[#3C=@XY][0=@XY] P+P=P ++XY --X'] ++Patt XY+237=XY
--Y']
;
<ERACE_UFO> // input UfoPos
UfoPos=XY 6=Y[ 17=X[0=@XY ++XY --X'] XY+238=XY --Y']
;
<DRAW_BASE>
BasePos = XY LAUNCHER=Patt
7=Y[ %Patt=P 15=X[P|#7FFF *[255=@XY][0=@XY] P+P=P ++XY --X'] XY+240=XY ++Patt --Y']
;
<DRAW_INV_BEAM> // input XY (the most under point)
BEAM = Patt
8=Y[ %Patt=P 3=X[P|#7FFF *[#39=@XY][0=@XY] P+P=P ++XY --X'] XY-260=XY ++Patt --Y']
;
<ERACE_INV_BEAM> // input XY
8=Y[ 3=X[ 0=@XY ++XY --X'] XY-260=XY --Y']
;
<ERACE_BASE_BEAM> // input BaseBeam
BaseBeamPos=P
9=Y [0=@P P+256=P --Y']
;
<DRAW_HITMARK1> // input XY Color
HITMARK1 = Patt
8=Y[ %Patt=P 15=X[P|#7FFF *[Color=@XY][0=@XY] P+P=P ++XY --X'] XY+240=XY ++Patt --Y']
;
<DRAW_HITMARK2> // input XY Color
XY-#0408=XY HITMARK2 = Patt
8=Y[ %Patt=P 15=X[P|#7FFF *[Color=@XY] P+P=P ++XY --X'] XY+240=XY ++Patt --Y']
;
<ERACE_A_INVADER> // input XY
14=Y[ 15=X[0=@XY ++XY --X'] XY+240=XY --Y'] // Delete the invader (picture)
;
<MOVE_A_INV>
InvWait:0!=[--InvWait;]
[ ++Ino Ino:55==[>] INVADER_STYLE+Ino = W %W:0==] Ino:55!=[DRAW_A_INVADER;]
0=Down
Edge:1==[#FFFE=Direction 0=Edge #0400=Down]
Edge:2==[#0002=Direction 0=Edge #0400=Down]
InvPos + Direction + Down = InvPos
#FFFF=Ino
Step^#FFEF = Step
;
<MOVE_BASE>
Time|#FFFC *[ // Speed 1/4
?|#FFFB *[ BasePos:#E608!=[--BasePos]]
?|#FFFD *[ BasePos:#E6E8!=[++BasePos]]
DRAW_BASE
]
;
<LAUNCH_BASE_BEAM>
?|#FFFE *[ BaseBeamPos:0==[BasePos+#F807=BaseBeamPos]]
;
<HIT_INVADER>
BaseBeamPos-InvPos =P
P >> >> >> >> >> >> >> >> >> >> >> >> = Y
P & #00FF >> >> >> >> = X
Y+Y+Y+Y+Y=Z Z+Z+Y+X =Z // Index of the invader
INVADER_STYLE + Z = S // Style adrs. of the invader
%S & #00FF = Color
0= %S // Delete the invader (info)
DELTA + Z = W // Delta of the invader
InvPos + %W + #0600 = XY // Poshition of the invader
XY=BaseBeamPos DRAW_HITMARK1
;
<ERACE_BASE_BEAM_HIT_MARK>
HITtype:0==[BaseBeamPos-#0600=XY ERACE_A_INVADER] // Erace inv. hit mark
HITtype:1==[0=Color BaseBeamPos=XY DRAW_HITMARK2] // Erace Explosion mark
HITtype:2==[ERACE_UFO 0=UfoPos] // Erace UFO
;
<MOVE_BASE_BEAM>
BaseBeamPos:0==[;]
BaseBeamWait:1==[ERACE_BASE_BEAM_HIT_MARK 0=BaseBeamPos]
BaseBeamWait:0!=[--BaseBeamWait ;]
BaseBeamPos-#0100=BaseBeamPos
BaseBeamPos=XY
BaseBeamPosFF00:#0400
==[ERACE_BASE_BEAM 100=Color DRAW_HITMARK2 40=BaseBeamWait 1=HITtype;]
@XY=W:0!=[ ERACE_BASE_BEAM
W:100==[ 100=Color DRAW_HITMARK2 40=BaseBeamWait 1=HITtype;]
W:#3C==[ EXPLOSION_UFO=Patt DRAW_UFO 300=UfoWait 80=BaseBeamWait 2=HITtype;]
W:100!=[ HIT_INVADER 90=BaseBeamWait=InvWait 0=HITtype --InvNumber;]
]
8=Y [255=@XY XY+256=XY --Y'] // Redraw the beam
0=@XY
;
<LAUNCH_INV_BEAM>
InvBeamPos:0!=[;]
RndF=R R-11'[;] R+44=R // R=44..54
// Decide the invader who to fire (from random number).
[INVADER_STYLE+R=W %W:0!=[>] R-11=R -[R+56=R] R:55==[44=R] !]
DELTA+R=W
InvPos + %W + #1807 = InvBeamPos
;
<MOVE_INV_BEAM>
InvBeamPos:0==[;]
InvBeamWait:1==[InvBeamPos=XY 0=Color DRAW_HITMARK2
InvBeamPos+#0400=XY 0=Color DRAW_HITMARK2 0=InvBeamPos]
InvBeamWait:0!=[--InvBeamWait;]
InvBeamPos+#0100=InvBeamPos
InvBeamPos=XY
InvBeamPosFF00:#ED00==[
ERACE_INV_BEAM
InvBeamPos=XY
#20=Color DRAW_HITMARK2 50=InvBeamWait
;]
@XY:100==[
ERACE_INV_BEAM
InvBeamPos=XY
#20=Color DRAW_HITMARK2 50=InvBeamWait
;]
@XY:255==[2=EndFlag;] //Hit base. Game end.
DRAW_INV_BEAM
;
<APPEAR_AND_MOVE_UFO>
UfoWait:0!=[--UfoWait;]
UfoPos:0==[
Rnd & 1 = UfoDir //0:from left , 1:from right
UfoDir:0==[#2008=UfoPos][#20E6=UfoPos]
UFO=Patt DRAW_UFO;
]
Time&3:0!=[;]
UfoPos:#2007==[ERACE_UFO 500=UfoWait 0=UfoPos;]
UfoPos:#20E7==[ERACE_UFO 500=UfoWait 0=UfoPos;]
UfoDir:0==[++UfoPos][--UfoPos] UFO=Patt DRAW_UFO;
;
<MAIN>
[
0=N [INIT_INVADER_STYLE+N=S INVADER_STYLE+N=D %S=%D ++N N:55!=]
CLEAR_ALL
DRAW_LINE
DRAW_BLOCKS
0 = EndFlag
#FFFF = Ino
#3010 = InvPos
55 = InvNumber
0 = InvWait
2 = Direction
0 = Down
#E680 = BasePos
0 = InvBeamPos
0 = InvBeamWait
0 = BaseBeamPos
0 = BaseBeamWait
0 = UfoPos
300 = UfoWait
0 = Step // For inv Dance (0->16->0->16..)
[ 0=Q [ --Q:0!=] // Main Loop with wait
Rnd^Time^BasePos = Rnd // Rnd=0..65535
LAUNCH_INV_BEAM
MOVE_INV_BEAM
MOVE_A_INV
MOVE_BASE
LAUNCH_BASE_BEAM
MOVE_BASE_BEAM
APPEAR_AND_MOVE_UFO
++Time InvNumber:0==[1=EndFlag] EndFlag:0==]
EndFlag:2==[0=XY [@XY:0!=[#30=@XY] ++XY,]] //Red screen.
500=Q [0=R [--R R:0!=] --Q'] //Wait about 5sec.
!]
インベーダーゲームを極力模しています。但し、文字フォントは搭載していないので得点表示などの文字出力は割愛しています。またゲームオーバー時は全画面を約5秒間赤色にした後、自動的に再スタートします。