當前位置: 妍妍網 > 碼農

成本不到 40 元!DIY 大神用樹莓派,重現 40 年前、售價 1.8 萬元的 Mac

2024-07-03碼農

【CSDN 編者 按】40 年前,蘋果釋出了首款 Macintosh(Mac 的前身),雖然曾有過一度十分強勁的銷售勢頭,但 2495 美元(約人民幣 1.8 萬元)的高昂售價還是令許多人望而卻步。如今,有個開發者嘗試用不到 50 元的 RP2040 MCU 復刻這個經典,一起來看看他是如何做到的吧!

原文連結:https://axio.ms/projects/2024/06/16/MicroMac.html

作者 | Matt Evans 轉譯 | 鄭麗媛

出品 | 程式人生(ID:coder_life)

這件事的起因,源於對 RP2040 MCU (Raspberry Pi 的首款微控制器) 的一次討論。

當時大家正在探討如何為 RP2040 MCU 構建一個簡單的桌面/圖形化使用者介面,我便隨口說了句「要麽,幹脆執行一些舊作業系統算了」。說完之後,我突然聯想到了最初的 Macintosh。

Macintosh 最早釋出於 40 年前,是一款硬體非常簡單卻相當酷的裝置。不過記憶體方面有些緊張:最初的 128KB 版本記憶體不足,僅售賣了幾個月便被 512K 的 Macintosh 取代,可以看出 512K 的記憶體似乎更為適當。

盡管如此,128KB 版本仍能執行一些真正的應用程式。雖然當時它還沒有 MultiFinder/實際多工處理功能,我依然覺得它很有魅力。

在 1984 年,Mac 的價格大約是 VW Golf (大眾高爾夫,一款小型家庭轎車) 的三分之一。但如今,我想用這塊售價 3.80 英鎊 (合人民幣約 34.8 元) 的 RPi Pico 微控制器板來試試:RP2040 有 264KB 記憶體,扣除 Mac 的 128KB 之後還剩下很多空間可以用——如果能快速搞定,然後在這上面玩 Mac,那該有多酷?

一段時間過去後,我真的做到了:

說出來你可能不信,這個高品質計畫我沒花多長時間就完成了。軟體顯然是最關鍵的部份,我分成了 3 個不同的計畫來進行。

那麽接下來,你將看到一個關於我這場「開發之旅」的故事。

什麽是 pico-mac?

它是一個基於 Raspberry Pi RP2040 微控制器 (安裝在 Pico 板上) 的系統,能夠驅動單色 VGA 視訊並接受 USB 鍵盤/滑鼠輸入,仿真 Macintosh 128K 電腦及其磁盤儲存。RP2040 的 RAM 容量足以容納 Mac 的記憶體和仿真器的記憶體。透過一些小技巧,它的速度能達到真實 Macintosh 的效能,還具備 USB 主機功能,並且 PIO 模組使得驅動 VGA 視訊也相對簡單。基本版 Pico 板的 2MB 快閃記憶體足以容納作業系統和軟體的磁盤映像。

以下是 Pico MicroMac 的實際執行情況,為未來的「無紙化辦公」做好了準備:

(未來的 Pico MicroMac RISC CISC 工作站)

我以前沒怎麽用過 Mac 128K,只在博物館的機器上點選過幾下。但我知道它們可以執行 MacDraw、MacWrite 和 MacPaint——對於 128K 裝置來說,這三個應用程式非常棒:一個基本所見即所得的文書處理器,帶有多種字型,還有一個向量繪圖軟體。

如果想體驗早期 Macintosh 系統軟體和這些出色的套用軟體,有一個方法是存取 https://infinitemac.org,這個網站透過 emscript 把 Mini vMac 仿真器封裝在瀏覽器中執行 (強烈推薦,有很多有趣內容可以玩)

提前劇透一下,我開發的 MicroMac 確實可以執行 MacDraw,在「仿真硬體」上用它非常有趣:

如果你也想做一個自己的 Pico-Mac,可以參考 GitHub 連結 (https://github.com/evansm7/pico-mac) ,裏面有具體的制作說明。

我的開發之旅,開始!

細想了一下,其實我一開始並沒有打算做一個 Pico 計畫,只是隱約對它是否可行有點感興趣,於是開始在我的普通電腦上搗鼓制作了一個 Mac 128K仿真器。

三條規則

對於這個計畫,我最初定了幾條簡單的規則:

  • 必須要做有趣的事。為了讓它能正常執行,黑進去做一些改動也是可以的。

  • 我喜歡寫仿真程式,但我不想 深入 學習和 了解 68K 組合語言。我知道有很多人喜歡 68K,它也確實很好,但我不喜歡把它作為 CPU。所以,一開始我本想直接用別人做好的現成 68K 直譯器。

  • 同樣,我還想深入了解很多作業系統的內部結構,但早期的 Mac 系統軟體並不在我的考慮之列。我只需要進入系統、模擬硬體、把作業系統作為黑盒啟動,就可以了。

  • 但在整個計畫過程中,我經常打破上述規則,有時是兩條,有時是全部。

    Mac 128K

    這類機器一般都非常簡單,也符合當時的時代特征。我從原理圖和【Inside Macintosh】開始學習,這些 PDF 檔涵蓋了原始 Mac 硬體、記憶體對映、滑鼠/鍵盤等各種細節。

    Macintosh 的硬體配置:

  • 執行頻率大約 8MHz 的 Motorola 68000 CPU;

  • 扁平記憶體結構,將記憶體解碼為不同區域,用於記憶體對映 IO,連線到 6522 VIA、8530 SCC 和 IWM 軟碟控制器 (某些地址解碼有些復雜)

  • 鍵盤和滑鼠透過 VIA/SCC 芯片連線。

  • 沒有外部中斷控制器:68K 有 3 條 IRQ 線,對應 3 個 IRQ 來源 (VIA、SCC、編程器開關/NMI)

  • 沒有插槽或擴充套件卡。

  • 沒有 DMA 控制器:一個簡單的自主 PAL 狀態機從 DRAM 中掃描視訊和音訊樣本。視訊分辨率固定為 512x342 1BPP。

  • 唯一的儲存裝置是內部軟碟機 (外加一個外部驅動器) ,由 IWM 芯片驅動。

  • 前三款 Mac 型號非常相似:

  • Mac 128K 和 Mac 512K 是同一款裝置,只是記憶體不同。

  • Mac Plus 在記憶體對映中添加了 SCSI 介面和一個 800K 軟碟機,該驅動器是雙面的,而原來的軟驅是單面 400K。

  • Mac Plus 的 ROM 也支持 128K/512K,是 Macintosh 512Ke 的升級版。其中 ‘e’ 表示額外的 ROM 功能。

  • Mac Plus 的 ROM 支持 HD20 外部硬碟和 HFS 檔案系統,Steve Chamberlin 對其拆解進行了註釋。這就是我要使用的 ROM:我正在制作一台 Macintosh 128Ke。

    Mac 仿真器:umac

    經過大約 8 分鐘的研究,我選擇了 Musashi 68K 直譯器。它是用 C 語言編寫的,介面簡單,並且提供了一個簡單的、開箱即用的 68K 系統範例,包含 RAM、ROM 和一些 IO。Musashi 適合嵌入到更大的計畫中:連線記憶體讀/寫回呼、一個引發 IRQ 的函式,並在迴圈中呼叫執行,完成。

    我開始圍繞它構建一個仿真器,最終這個計畫成為了 umac。前半部份進行得相當順利:

    1、構建一個簡單的命令列應用程式,載入 ROM 映像,分配 RAM、提供偵錯訊息、斷言和日誌記錄,並配置 Musashi。

    2、添加地址解碼:將 CPU 的讀/寫操作引導到 RAM 或 ROM。「overlay」寄存器使得 ROM 可以在 0x00000000 地址啟動,然後在設定 CPU 異常向量後跳轉到一個高地址的 ROM 映像——這會影響地址解碼。這是透過操作 VIA 寄存器完成的,所以現在只解碼了該寄存器的一部份。

    3、此時,ROM 開始執行並存取更多不存在的 VIA 和 SCC 寄存器。於是添加更多的地址解碼和一個模擬這些裝置的框架——讓 MMIO 讀/寫操作只是被簡單地標記出來。

    4、有一些 ROM 存取的特殊地址會「錯過」記錄在案的裝置:有一個制造測試選項,它會探測是否有外掛程式,然後我們就會看到 RAM 大小的探測結果。Mac Plus ROM 正在尋找最多 4MB 的 RAM。在分配給 RAM 的大區域中,實際 RAM 的較小容量被反復映像,因此探針會在高地址和開始環繞的點寫入一個特殊值,

    5、然後初始化 RAM 並填充已知模式。這是一個令人興奮的時刻,因為我可以轉儲 RAM,將用於視訊幀緩沖區的區域轉換為影像,並看到用於 RAM 測試的「對角條紋」圖案!

    6、並非所有裝置程式碼都喜歡讀取全零值,所以有時需要參考反組譯並返回 0xffffffff 以推動它進一步執行。我們的目標是讓它能夠存取 IWM 芯片,即嘗試載入作業系統。

    7、在看到一些 IWM 存取並返回隨機無意義的值後,第一個美妙的時刻是出現了帶問號的「未知磁盤」圖示——真正的圖形!ROM 真的在做一些事!

    8、此時我還沒有實作任何 IRQ,並行現 ROM 進入了一個無限迴圈:它在計算幾個 Vsync 以延遲閃爍的問號。於是我轉向了更好的 VIA,它能為 GPIO 寄存器讀/寫和 IRQ 處理提供回呼。這還需要連線到 Musashi 的 IRQ 函式。

    以上過程很大程度上激勵了我繼續做下去——記住規則一:盡管這是透過手動記憶體轉儲和 ImageMagick 轉換才看到的「圖形」,但這依然很棒。

    IWM、68K 和磁盤驅動程式

    其實在上個步驟中,我就知道 IWM 是一款很「有趣」的芯片,但對具體細節不太了解,因此打算在需要時再弄清楚——幸虧我把研究 IWM 的事拖到了現在。如果我在計畫開始時就讀了它的「數據手冊」 (一份含糊不清的寄存器文件) ,我肯定會原地放棄。

    IWM 確實很不錯,但它非常底層。其他同時代機器的磁盤控制器,例如 WD1770,會抽象出磁盤的物理操作,所以在某種程度上,你只需撥動寄存器,讓控制器步進到第 17 條軌域,然後抓取第 3 磁區。但 IWM 不是這樣的:首先,磁盤是恒線速度的,這意味著角速度需要根據當前軌域進行調整;其次,IWM 只會給 CPU 提供從磁盤頭讀取的大量原始數據 (幾乎沒有解碼)

    我花了很長時間閱讀 ROM 中 IWM 驅動程式的反組譯程式碼 (違反了規則 1 和規則 2) :驅動程式包含某種伺服控制環路,透過調節發送到 DAC 的 PWM 值來控制磁盤馬達,並與 VIA 定時器的參考值進行比較,以實作動態速率匹配,從磁盤磁區獲取正確的位元率。我認為,一旦找到軌域起點,驅動程式就會將軌域數據流入記憶體,解碼符號 (更復雜的編碼) 並選擇感興趣的磁區。

    說實話,我有點喪。我原以為像 Basilisk II 和 Mini vMac 這樣的仿真器已經透過某種巧妙的方式解決了這個問題,因為它們能模擬軟碟——但實際上它們並沒有,而是直接避開了這個問題。

    至於其他仿真器,對 ROM 進行了很多修補程式處理:ROM 並不是未經修改就執行的。可能有人會說,雖然這樣修改 ROM 它就不再是完美的硬體仿真了,但那又如何?嗯,我懷疑他們也遵循了規則 1,因為我也打算這樣做。

    我研究了一些 Mac 驅動程式介面的工作原理 (唉,還是違反了規則 3) ,並理解了其他仿真器是如何進行修補程式的。它們使用自訂的半虛擬化 68K 驅動程式,覆蓋 ROM 中的 IWM 驅動程式,為來自塊層的 .Sony 請求提供服務,並將其路由到更方便的主機端程式碼來管理這些請求。Basilisk II 使用了一些自訂的 68K 操作碼和一個簡單的驅動程式,而 Mini vMac 則使用了一個復雜的驅動程式,對自訂的記憶體區域進行「陷阱」存取。我重新使用了 Basilisk II 驅動程式,但將其轉換為存取一個自訂區域(這樣更容易路由:只需模擬另一個裝置)。驅動程式的回呼主機 / C 端執行,一些簡化的 Basilisk II 程式碼解釋請求,並將數據復制到作業系統提供的緩沖區或從中復制數據。這樣一來,我只需要從一個磁盤讀取塊:不需要不同的格式 (甚至不需要寫入支持) ,也不需要多個驅動器,更不需要彈出/更換映像。

    從磁盤載入第一個數據塊比第一部份花的總時間還長。我本來想著要不再學點 68K 組譯 (又違反了規則 3……) ,但在這千鈞一發之際,我看到了一個 Happy Mac 圖示,表示系統軟體開始載入。

    這時,我的仿真器仍然是一個簡單的 Linux 命令列應用程式,沒有任何使用者介面,沒有鍵盤或滑鼠,也沒有視訊輸出。於是,我覺得是時候將它封裝在一個 SDL2 前端中了,這樣能即時看到螢幕重繪效果。我把 1Hz 的計時器中斷添加到 VIA 中,它就成功啟動了!

    (第一次啟動)

    順便一提,我試著為所有嵌入式計畫都建立一個雙目標構建,即一個用於快速原型設計/偵錯的本地主機構建,用 libSDL 代替 LCD,這意味著我不需要在 MCU 上編碼。

    接下來是滑鼠支持。Macintosh 內部和原理圖展示了它是如何與 VIA 和 SCC 連線的。SCC 是我在這台機器中第二個不喜歡的芯片:很復雜,數據手冊似乎故意隱藏資訊、惹惱讀者、報復世界。但它能執行各種上世紀 80 年代的路線編碼方案,減輕 CPU 的工作負擔,對於支持 AppleTalk 等功能至關重要

    到這一步,雛形幾乎就完整了:有一個能工作的滑鼠,我可以用 Mini vMac 構建一個新的磁盤映像,其中還包含 Missile Command 這款遊戲——不到 10KB,非常好玩。

    總體來說:

  • 視訊正常

  • 能從磁盤啟動

  • 滑鼠正常,Missile Command 也能執行

  • 雖然還沒有鍵盤,但大部份功能已經實作。是時候開始第二個子計畫了。

    硬體和 RP2040

    與 umac 無關,我設計了一個電路和固件,目的有兩個:

    (1)用最少的元件將 512x342x1 的視訊顯示到 VGA 上。

    (2)讓 TinyUSB HID 範例正常工作並整合。

    準確來說,這個計畫只是為了將測試影像復制到幀緩沖區,並透過 printf() 輸出鍵盤/滑鼠,作為一個概念驗證。視訊部份的工作很有趣:雖然我之前做過一些 I2S 音訊 PIO 的計畫,但這次我想輸出視訊訊號並隨意控制 Vsync 和 Hsync。

    為了測試,我需要一個電路。VGA 介面要求視訊 R、G、B 訊號最大電壓為 0.7V,以及同步訊號的某些電壓 (具體數值略) 。R、G、B 訊號對地電阻為 75Ω:經過計算,3.3V GPIO 透過 100Ω 電阻驅動這三個訊號大致可行。

    開始焊接的那天,我需要一個 VGA 介面。我手頭雖說有一個 DB15 接頭,但想把它用在另一個計畫上,剪斷 VGA 電纜也不太合適。午餐後散步時,我無意在街邊發現了一些電纜,其中就有一根 VGA 電纜——雖然生銹了,但看起來有一種隨性的美感。

    (免費的 VGA 電纜)

    VGA PIO 這部份非常有趣。最終,PIO 動態讀取配置資訊來控制 Hsync 寬度、顯示位置等,然後用一些 DMA 技巧掃描出配置資訊與幀緩沖區數據。透過正確的位移方向並使用 RP2040 DMA 上的字節交換選項,無需在 CPU 端進行拷貝或格式轉換,就能直接輸出大端 Mac 幀緩沖區。

    不過,我總共重寫了三次視訊部份:

    (1)第一個版本有兩個 DMA 通道寫入 PIO TX FIFO。第一個傳輸配置資訊,然後觸發第二個傳輸視訊數據,接著引發 IRQ。然後,IRQ 處理常式會在短時間內選擇要讀取的新幀緩沖區地址,並重新對 DMA 進行編程。這種方法能正常工作,但對系統中的其他活動非常敏感。有個很明顯的解決方法是,任何對延遲敏感的 IRQ 處理常式都必須具有 __not_in_flash_func() 內容,避免 RAM 耗盡。但即便如此,該設計也沒有給重新配置 DMA 留出太多時間:快速移動滑鼠時,會出現隨機閃爍和空白。

    (3)第二個版本采用了雙緩沖區,目的是讓 IRQ 處理常式的工作變得簡單:快速插入預先準備好的 DMA 配置,然後在關鍵時刻計算出下次使用的緩沖區。這種方法的效果好了很多,但在高負載下仍會有一些故障。更奇怪的是,它有時會完全空白,需要重設,這讓我困惑了好一陣子。最終我打印出了 PIO FIFO 的 FDEBUG 寄存器,試圖在執行中發現錯誤。我看到 TXOVER 溢位標誌被設定了,但這應該是不可能的:FIFO 根據需求從 DMA 拉取數據,帶有 DMA 請求和基於信用的流量控制……哦,等等,如果信用發生混亂或重復,就會發生過多傳輸,導致接收端溢位。

    我漏看了 RP2040 DMA 文件中的一個細節規則:「多個通道不應連線到相同的 DREQ。」

    (3)因此第三個版本……並沒有違反這個規則,但也變得更加復雜:

  • 一個 DMA 通道傳輸數據到 PIO TX FIFO

  • 另一個通道負責設定第一個通道,從配置數據緩沖區發送數據

  • 第三個通道負責設定第一個通道,從視訊數據緩沖區發送數據

  • 第一個通道的設定觸發相應的「next reprogram me」通道

  • 除了不會出現釘選或視訊損壞之外,還有一個好處就是在視訊行掃描期間會觸發 Hsync IRQ,從而大大縮短了重新配置 DMA 的時間限制。我還想進一步改進這一點(再增加一個 DMA 通道),讓每行傳輸都不需要 IRQ,因為目前 IRQ 的開銷約占 CPU 時間的 1%。

    所以,現在我們有了一個可以嵌入 umac 的平台和固件框架,支持 HID 輸入和視訊輸出。至此,硬體部份已完成,接下來交給軟體團隊。

    回到仿真器的開發工作上

    看了一眼本地 umac 二進制檔,我發現要在 Pico 上執行還需要解決一些問題:

  • Musashi 執行時在 RAM 中構建了一個巨大的操作碼解碼跳轉表。這個表永遠不會改變,也不會在執行時更改。我添加了一個 Musashi 構建時生成器,這樣該表就可以設為 const (可儲存在 flash 中)

  • 反組譯器占用了很大空間,而且在 Pico 上也沒用,所以可以一個構建不包含反組譯器的版本。

  • Musashi 為了準確計算每條指令的執行周期,用了很多的大型尋找表。雖然這對一些遊戲主機來說很有用,但對 Mac 來說並不重要,因此我移除了這些尋找表。

  • pico-mac 開始成形,ROM 和磁盤映像儲存在 flash 中,現在可以在 Pico 上構建並執行了!只要註意不要把東西塞進 RAM,RAM 的使用情況還是不錯的。仿真器和 HID 程式碼總共使用了大約 35-40KB 的 Mac 128KB RAM 區域,還剩 95KB 以上的可用 RAM。

    這正是為 umac 添加鍵盤支持的好時機。Mac 鍵盤透過 VIA 的「移位寄存器」串列埠連線,這是一個基本的同步串列埠。雖然邏輯上很簡單,但在早期嘗試響應 ROM 的「初始化」命令時總是被忽略。ROM 的反組譯又派上了大用場:在閱讀鍵盤啟動程式碼時,如果響應字節在請求發送後過早出現,就會導致中斷確認的競爭條件。因此我在請求發送後插入了一個延遲,將響應延遲到稍後輪詢,然後就只需要對映按鍵程式碼了。

    有了鍵盤支持,就達到了 MacWrite 的最終關卡:

    但有一個問題:它的表現完全不行,速度超級慢。我添加了一個 1Hz 的指令計數轉儲,發現它每秒只執行約 300 KIPS (千條指令)

    68000 CPU 在 IPC 方面並不出色。雖然有些指令可以在 4 個周期內執行,但如果你想用那些復雜的尋址模式,存取記憶體會花費很多周期。當然我不是專家,但我覺得為大約 8MHz 的 68000 設定大約 1 MIPS (百萬條指令) 的目標並不過分,只需要提高 3 倍。

    效能

    我可沒說我不會作弊:讓我們把 Pico 的執行頻率從 125MHz 提高到 250MHz。好是好了點,但也沒好到翻倍,我記得好像只提高了大約 30%。

    Musashi 有很多可配置選項。我的第一個目標是讓主迴圈 (從反組譯/編譯後端來看) 變小:Mac 不會報告匯流排錯誤,所以寄存器不需要副本展開。操作碼總是從 16 位邊界獲取,因此不需要對齊檢查,可以用半字載入 (而不是將兩個字節載入合並為一個半字) 。對於 Cortex-M0+/armv6m ISA ,透過重新排列 CPU 上下文結構欄位,可實作即時偏移存取和更好的程式碼。令人費解的是,CPU 型別是動態可變的,這導致了大量執行時的間接操作。

    看起來好多了,也許有 2 倍的改進,但還不夠。Missile Command 仍然很卡,滑鼠也依舊不流暢!接下來,是一些較為激進的最佳化:刪除地址對齊檢查,因為在這種受限環境中不會發生未對齊的存取。

    不過,真正的最佳化來自下面提及的另一個小技巧。

    RP2040 記憶體存取

    RP2040 擁有快速 RAM,該 RAM 采用多行設計,允許多個使用者 (如兩個 CPU 和 DMA) 進行單周期存取。預設情況下,大多數程式碼透過外部 QSPI 快閃記憶體的 XIP 執行,而 QSPI 通常以內核時鐘 (預設 125MHz) 的速度執行,但隨機讀取一個字的延遲約為 20 個周期。為縮短這種延遲,RP2040 配備了一個 16KB 的簡單緩存,但如果程式碼量大,就更容易在呼叫函式時觸發 QSPI 讀取。當超頻到 250MHz 時,QSPI 無法達到那麽快的頻率,所以會保持在 125MHz。這樣一來,當緩存未命中時, QSPI 的 20 個周期延遲會變成 40 個 CPU 周期。

    這裏的問題在於,Musashi 在構建時會生成大量程式碼,每 1968 個操作碼都有一個函式,再加上一個 256KB 的操作碼跳轉表。即使內部執行迴圈非常高效,操作分碼發和函式呼叫也可能在快閃記憶體緩存中未命中。如果我們想在 200 MIPS 的基礎上實作 1 MIPS ,那這些延遲就會累加。

    面對這種情況,可以用 __not_in_flash_func() 內容將指定函式復制到 RAM 中,以保證快速執行。最起碼,主迴圈和記憶體存取函式需要這個內容,因為每條指令都需要存取一個操作碼,並且很可能會讀寫 RAM 。

    這樣的最佳化,又提升了幾個百分點的效能。

    接下來,我嘗試對整類操作碼進行最佳化:移動很頻繁,分支也很頻繁,所以把它們放在 RAM 中。這確實能提高效能,但 RAM 很快就用完了,距離目標的 1 MIPS 也還有差距。

    還記得我說 RISC 架構會改變一切嗎?

    我們想要加速的 1968 個 68K 操作碼中,有哪些是最常用的?在 umac 中加入一個 64K 的計數器表,啟動 Mac 並執行一些關鍵應用程式 (實際上是玩了一會兒 Missile Command ) ,就能得到一份動態指令使用情況的統計概況。結果顯示,最常用的 100 個操作碼 (占總數的 5%) 占了 89% 的執行次數,而最常用的 200 個操作碼則占了 98% 的執行次數。

    根據這個統計結果,umac 在構建後對 Musashi 自動生成的程式碼進行處理,並將最常用的 200 個函式附上 __not_in_flash_func() 內容。這樣只增加了 17KB 的 RAM 使用(剩余 95KB),而效能提升到了約 1.4 MIPS!

    終於,我們可以流暢地享受 Missile Command 的黑暗主題了:

    MacPaint 如何?

    人人都愛 MacPaint,但你會發現我一直對它避而不談,因為:

    它無法在 Mac 128Ke 上執行,因為 Mac Plus ROM 使用的 RAM 比原來的多:我在 68kMLA 上看到過一個關於「Mac 256K」的討論,很可能 Mac 128K 在實驗室裏實際上是 Mac 256K (甚至可能本來打算是 256K,但在釋出前削減了成本) ,因為作業系統在 256KB RAM 下執行良好。

    當時我在想,Mac ROM/OS 是否一定要是 2 的 n 次方才行?如果不是,那我還有 95K 空閑記憶體,能否制作一個「Mac 200K」,然後執行去 MacPaint?於是,我試了一個本地黑客程式,可以根據給定的記憶體大小修改 ROM,更新其全域 memTop 變量。結果不錯,我還用 256K 、 208K 和 192K 進行了啟動測試。不過,也有一些問題需要解決:如果記憶體大小不是 2 的 n 次方,ROM memtest 就會出錯,而跳過這個測試又會導致其他問題。這些問題都可以解決,但有些啟動過程會存取超出 RAM 末尾的區域。另外,2 的 n 次方以透過簡單的地址掩碼將 RAM 存取限制在有效緩沖區內,而 192K 無法做到這一點。

    不幸的是,當我測試 MacPaint 時,它仍然無法執行,因為它需要將臨時檔寫入一個唯讀引導卷。這完全違反了規則 1,所以我們現在暫時還是保持 128KB。另外,256K MicroMac 是完全可行的,只需要一個記憶體容量為 300KB 的微控制器就大功告成了。

    推薦閱讀:

    由 CSDN 和 Boolan 聯合主辦的「2024 全球軟體研發技術大會(SDCon)」將於 7 月 4 -5 日在北京威斯汀酒店舉行。

    由世界著名軟體架構大師、雲原生和微服務領域技術先驅 Chris Richardson 和 MIT 電腦與 AI 實驗室(CSAIL)副主任,ACM Fellow Daniel Jackson 領銜,BAT、微軟、字節跳動、小米等技術專家將齊聚一堂,共同探討軟體開發的最前沿趨勢與技術實踐。