RETROF-16Mプロセッサ 自己診断用テストプログラム

本ページの概略

RETROF16M

画像はTTLのみで作成した16bitコンピュータ「RETROF-16M」です。
本頁は、このRETROF-16Mの、自己診断用に作成したインベーダーゲーム風のアプリケーションの全ソースコードを紹介するためのものです。

このソースコードはRETROF-16Mの命令セットを最大限活用するために考案した独自言語BAC+で記述されています。


 

このソースコードは専用のIDE(統合開発環境)でコンパイルされます。以下がそのIDEのスクリーンショットです。
このIDEもC++/CLI(マイクロソフト社が独自拡張したC++言語)を用いて筆者が自作しました。コンパイルだけではなく、デバッグやエミュレート、16進ダンプ、逆アセンブル等の機能も有しています。

 R16MIDE

この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
    BaseBeamPos&#FF00:#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!=[;]

    Rnd&#F=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 

    InvBeamPos&#FF00:#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秒間赤色にした後、自動的に再スタートします。