應用程式/解決方案‎ > ‎雜記‎ > ‎2020‎ > ‎

Quick Basic 再生筆記

張貼者:2020年8月29日 下午7:11Wei-Xiuang Wang   [ 已更新 2020年9月22日 上午3:24 ]

YouTube 影片


以下筆記只是給自己看的

嘗試以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 切入文字模式就能恢復正常而不用強制重新開機
Quick Basic VGA繪圖模式 SCREEN 12
  那時有VGA可以用SCREEN 12已經很幸福...
9.如用於資料分析可於執行QBX時使用/AH參數, 這樣可以動態宣告超過64KB的記憶體的使用空間, 程式設計上會方便許多
Quick Basic QBX.exe 使用超過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呼叫範例


註解