Quick Basic 再生筆記

張貼日期:Aug 30, 2020 2:11:58 AM

以下筆記只是給自己看的

嘗試以DosBox使用QBX

(此番設置都是在VM的XP試的, 因為XP所需資源少最為方便)

將 HDD_850M.VCD 的內容用VirtualCD安置在 R:

執行DosBox後,用mount命令

    mount C R:\

讓R:\的內容對應在DosBox模擬環境下的C:

因為 QBX\BIN\WORK\QBX.ini 的設定中, QBX的路徑都是指定在 C:\QBX 之下

如果不想另外作設定, 那麼就弄出一樣的環境

由於 HDD_850M.VCD 為光碟裝置, 無法寫入

所以將 \QBX 複製一份到 Z:\

然後DosBox用mount命令

    mount D Z:\

之後於DosBox內便可於D:中跑QBX了, 指令如

    D:

    CD \QBX\BIN\WORK

    ..\QBX /AH

跑起QBX後, 用介面操作載入 LIGHT.BAS 這個光學共振腔的模擬程式

(檔案在 \QBX\BIN\HW\LIGHT.BAS 所以要先切換路徑到上一層再切入 HW 這路徑 )

於 [RUN] 中選擇 [MAKE EXE File...] 發現無法順利編譯

退出QBX後, 執行

    \QBX\BIN\HW\LIGHT.EXE

則是可以正確運行的, 只是跑的結果有點奇怪...

難道以前沒有保存到最後正確的完成版本嗎?

用UltraEdit開 \QBX\BIN\HW\LIGHT.EXE 則發現是Turbo Basic編譯的版本(有可能是自己的保護偽裝)

於是跑QBX試著修改 \QBX\BIN\HW\LIGHT.BAS

1.修正使用到 instat 的地方, 因為那是Turbo Basic才有提供的函式

2.修正 COLOR 31 為 COLOR 15 (這應該也是TB的習慣)

3.修正 COLOR 7, 8 為 COLOR 7 (SCREEN 12的繪圖模式下無法指定背景顏色)

4.修正 IF ... THEN label 的地方, 加上 GOTO (省略GOTO的方式應該也是TB的習慣)

5.寫死彩色顯卡設基址  DEF SEG = &HB800

  (原本似乎想 call interrupt 11h 判斷單色顯卡設基址 &HB000, 彩色顯卡設基址 &HB800, 不過應該是還沒寫好)

6.直接於QBX中RUN可以正確運行了, 但MAKE EXE出來, 跑EXE則會出錯且開除錯訊息則是無對應行號的位址出錯

  後來改於MAKE時, Speed 中的選項 改選 Alternate Math /FPa 替代預設的 80x87 or Emulator Math /FPi

  用 /FPa 參數MAKE出來的EXE檔就能正確在DosBox下直接執行沒有問題了

7.新的執行檔也能直接在XP中直接執行, 而由於要獨占全螢幕模式所以於Win7中不行只好使用DosBox的方式,

  於XP或DOS的VM環境下跑LIGHT.exe可以發現光反射填滿區域的過程速度很快, 但於DosBox下則像是慢動作(如YT影片),

  可看到DosBox是窗的標題有一個狀態 Cpu speed: 3000 cycle, 這可以用Ctrl-F12調大變快, 不過系統CPU使用率會變很高,

  反之可以用Ctrl-F11調小數值, 讓程式執行速度更慢, 如果想看更細的步驟也可以用看看

   (LIGHT程式在左上角有個 times 的數字, 代表反射的次數可以觀察)

8.為安全起見,若想於XP中直接執行繪圖模式的程式,最好準備一個執行 SCREEN 0 切入文字模式的小程式

  不然程式於繪圖模式中異常結束的畫將只能看到左上角的繪圖解析度大小的桌面,

  這時只要能有辦法執行到 SCREEN 0 切入文字模式就能恢復正常而不用強制重新開機

  那時有VGA可以用SCREEN 12已經很幸福...

9.如用於資料分析可於執行QBX時使用/AH參數, 這樣可以動態宣告超過64KB的記憶體的使用空間, 程式設計上會方便許多

LIGHT.BAS 主程式碼(副程式略)

DECLARE SUB StrHandle (w$(), n%, typ$)

DECLARE SUB ViewScrn (lul%, lux%, cf%, cb%, v$(), n%)

DECLARE SUB Selecter (lul%, lux%, cf%, cb%, v$(), n%, sle%)

DECLARE SUB KeyLine (l%, xl%, xr%, cf%, cb%, keylist$, ans$)

DECLARE SUB GetScrn (ll%, lx%, rl%, rx%, word$, clor$)

DECLARE SUB PutScrn (ll%, lx%, word$, clor$)

DEFDBL A-Z

ON ERROR GOTO errhandle

'-----------------------------------------------------------------

WordCode$ = " .MzLaQqKxAsDwPeBdYcFvGbJgErRfZtNyThCnUmVjWuOiIkSlXoHp5391468720()"

b$ = "%%%Q3GSIU%?W?AISU?%BX@%4.*LZV4%DX%Z*00%%%%%%Z@X&%<F%O&W&%O*J>%eIf^]]c&^d&b%%%%"

nam$ = ""

FOR i = 1 TO LEN(b$)

x = ASC(MID$(b$, i, 1)) - 36

nam$ = nam$ + MID$(WordCode$, x, 1)

NEXT

'-----------------------------------------------------------------

DIM w$(6)

w$(5) = "  --- START PROGRAM ---  "

w$(6) = "  ---  END PROGRAM  ---  "

col1 = 14

col2 = 9

wid = 30

pi = 3.141592654#

r1 = 300!

r2 = 300!

l = 200!

mainprogram:

SCREEN 0: COLOR 7, 3: CLS : LOCATE 25, 2: COLOR 15, 4: PRINT nam$;

sle% = 5

w$(1) = "   r1 =" + STR$(r1)

w$(2) = "   r2 =" + STR$(r2)

w$(3) = "    L =" + STR$(l)

w$(4) = " width=" + STR$(wid)

CALL StrHandle(w$(), 6, "L")

CALL ViewScrn(8, 25, 1, 3, w$(), 6)

LOCATE 6, 20: PRINT "(1 - L/r1)(1 + L/r2) = "; (1 - l / r1) * (1 + l / r2);

CALL Selecter(8, 25, 14, 1, w$(), 6, sle%)

IF sle% = 0 THEN GOTO mainprogram

IF sle% = 6 THEN COLOR 7, 0: CLS : END

IF sle% = 5 THEN GOTO start

ans$ = ""

LOCATE 14, 25: COLOR 14: PRINT "input value:"

CALL KeyLine(15, 36, 47, 1, 14, "0123456789eE", ans$): value = VAL(ans$)

LOCATE 14, 25: PRINT SPACE$(30)

IF ans$ = "" THEN GOTO mainprogram

IF sle% = 1 AND value <> 0 THEN r1 = value

IF sle% = 2 AND value <> 0 THEN r2 = value

IF sle% = 3 THEN l = value

IF sle% = 4 THEN wid = value

GOTO mainprogram

start:

SCREEN 12: COLOR 7: CLS

a = 0: b = wid: c = (l - r1 - r2) / 2!: x = (r1 - r2) / 2

lx = -320 + x: rx = 320 + x

WINDOW (lx, 240)-(rx, -240)

LINE (lx, 240)-(rx, -240), 2, B

LINE (lx, 0)-(rx, 0), 2

LINE (x, -240)-(x, 240), 2

CIRCLE (c, 0), r1, col1

CIRCLE (-c, 0), r2, col2

ti& = 0: LOCATE 2, 3: PRINT "times:"; : COLOR 15

restart:

y = a * x + b

PSET (x, y), col1

ox1 = ((c - a * b) + ((a * b - c) ^ 2 - (a ^ 2 + 1) * (b ^ 2 + c ^ 2 - r1 ^ 2)) ^ (1 / 2)) / (a ^ 2 + 1)

oy1 = a * ox1 + b

LINE -(ox1, oy1), col1

IF ox1 < c - r1 OR ox1 > c + r1 THEN GOTO outlight

a1 = oy1 / (ox1 - c)

b1 = -a1 * c

a2 = (2 * a1 - a + a * a1 ^ 2) / (1 + 2 * a1 * a - a1 ^ 2)

b2 = oy1 - a2 * ox1

a = a2

b = b2

x = ox1

y = a * x + b

PSET (x, y), col2

ox2 = (-(a * b + c) - ((a * b + c) ^ 2 - (a ^ 2 + 1) * (b ^ 2 + c ^ 2 - r2 ^ 2)) ^ (1 / 2)) / (a ^ 2 + 1)

oy2 = a * ox2 + b

LINE -(ox2, oy2), col2

IF ox2 < -c - r2 OR ox2 > -c + r2 THEN GOTO outlight

ti& = ti& + 1

LOCATE 2, 9: PRINT ti&;

a1 = oy2 / (ox2 + c)

b1 = a1 * a1

a2 = (2 * a1 - a + a * a1 ^ 2) / (1 + 2 * a1 * a - a1 ^ 2)

b2 = oy2 - a2 * ox2

a = a2

b = b2

x = ox2

IF INKEY$ <> "" THEN GOTO mainprogram

GOTO restart

outlight:

    LOCATE 12, 38: COLOR 31, 7: PRINT " O U T ! "

    PLAY "MBO4L16BB"

    a$ = INPUT$(1)

    GOTO mainprogram

errhandle:

    SCREEN 0: COLOR 7, 0: CLS : PRINT "Error !!"

    END

最後發現2017年發行了這個Quick Basic的APP版本, QBasic APP 等有興趣時再用Xbox One來去試試看

當然也有新潮的QB64可以玩, 溫故而知新...

QB64 gets compiled automatically into machine code

 – allowing exceptional performance, easy distribution, and the ability to link with external C and C++ programming libaries.

Compatible with most QBasic 4.5 code, QB64 adds a number of extensions,

 such as OpenGL and other modern features, providing the perfect blend of classic and modern program development.

QB64 is available for all recent Windows, Linux, and macOS versions.

感覺好像就是程式碼直接跨平台可攜且能編譯成對應的可執行檔甚為方便的樣子, 有機會再來試試

相關文章:

2020-09-12 使用QB64解決日常的一般程式需求

2020-09-18 於QB64上使用DLL裡的API呼叫範例