1818// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1919
2020#define Printf_Swaps Serial.printf //Printf_dbg //
21+ #ifdef VM_HOST_PROFILE
22+ // VMBoot validates a complete 16 KiB client and mirrors it across 64 banks.
23+ // Its ABI-reserved RAM2 arena cannot host the native CRT erased-page buffer.
2124#define NumDecodeBanks 64
25+ #else
26+ #define NumDecodeBanks 256
27+ // ROM reads run in the PHI2 ISR: an erased half must live in RAM, never flash.
28+ DMAMEM static uint8_t EasyFlashErasedBank [8192 ];
29+ #endif
2230uint8_t * BankDecode [NumDecodeBanks ][2 ];
2331uint8_t EZFlashRAM [256 ];
32+ uint8_t EasyFlashBankMask = 0x3f ;
2433#ifdef FeatVMHost
2534// Defined by the extension image only. Stock builds compile none of this.
2635uint8_t CurrentEasyFlashBank ;
@@ -63,7 +72,7 @@ stcIOHandlers IOHndlr_EasyFlash =
6372};
6473
6574#ifdef MinimumBuild
66- void LoadBank (uint32_t SeekTo , uint8_t * ptrImage )
75+ static bool ReadBank (uint32_t SeekTo , uint8_t * ptrImage )
6776{
6877 if (!myFile )
6978 {
@@ -81,51 +90,90 @@ void LoadBank(uint32_t SeekTo, uint8_t* ptrImage)
8190 if (!myFile )
8291 {
8392 Printf_dbg ("File Not Found" );
84- return ;
93+ return false ;
8594 }
8695 }
8796 //Printf_dbg("\n %lu mS Open ", millis()-Startms);
8897
89- myFile .seek (SeekTo );
90- //One bulk read: SdFat moves whole sectors straight into the buffer instead of 8192 single-byte calls.
91- // SdFat returns -1 on error (through File's size_t, hence the cast); fill any shortfall with
92- // 0xff, which is what the byte-wise read() returned past the end of the file.
93- int BytesRead = (int )myFile .read (ptrImage , 8192 );
94- if (BytesRead < 0 ) BytesRead = 0 ;
95- if (BytesRead < 8192 ) memset (ptrImage + BytesRead , 0xff , 8192 - BytesRead );
96- //myFile.close();
97- //Printf_dbg("\n %lu mS Load ", millis()-Startms);
98+ // Do not publish a stale or partial page after a failed seek/read.
99+ return myFile .seek (SeekTo ) && myFile .read (ptrImage , 8192 ) == 8192 ;
100+ }
101+
102+ // Magic Desk 2 shares this reader and retains its erased-page fallback.
103+ void LoadBank (uint32_t SeekTo , uint8_t * ptrImage )
104+ {
105+ if (!ReadBank (SeekTo , ptrImage )) memset (ptrImage , 0xff , 8192 );
98106}
107+
108+ static void EasyFlashSwapFailed ()
109+ {
110+ LOROM_Image = HIROM_Image = NULL ;
111+ SetGameDeassert ;
112+ SetExROMDeassert ;
113+ doReset = true;
114+ DMA_State = DMA_S_StartDisable ;
115+ }
116+ uint8_t * ImageCheckAssign (uint8_t * BankRequested );
99117#endif
100118
101119void InitHndlr_EasyFlash ()
102120{
103121
104- //initialize bank decode pointers
105- for (uint8_t BankNum = 0 ; BankNum < NumDecodeBanks ; BankNum ++ ) {BankDecode [BankNum ][0 ]= NULL ;BankDecode [BankNum ][1 ]= NULL ;}
106- for (uint8_t ChipNum = 0 ; ChipNum < NumCrtChips ; ChipNum ++ )
122+ EasyFlashBankMask = 0x3f ;
123+ #ifdef VM_HOST_PROFILE
124+ uint8_t * ErasedBank = NULL ; // native CRT initialization is unused by VMBoot
125+ #else
126+ memset (EasyFlashErasedBank , 0xff , sizeof EasyFlashErasedBank );
127+ uint8_t * ErasedBank = EasyFlashErasedBank ;
128+ #endif
129+ // Sparse native images read as erased flash, including an absent ROMH in bank 0.
130+ for (uint16_t BankNum = 0 ; BankNum < NumDecodeBanks ; BankNum ++ ) {BankDecode [BankNum ][0 ]= ErasedBank ;BankDecode [BankNum ][1 ]= ErasedBank ;}
131+ for (uint16_t ChipNum = 0 ; ChipNum < NumCrtChips ; ChipNum ++ )
107132 {
108133 Printf_dbg ("Bank# %02d,%d chip# %03d addr %08x\n" , CrtChips [ChipNum ].BankNum , (CrtChips [ChipNum ].LoadAddress == 0x8000 ? 0 : 1 ), ChipNum , (uint32_t )CrtChips [ChipNum ].ChipROM );
109134 if (CrtChips [ChipNum ].BankNum < NumDecodeBanks )
110- BankDecode [CrtChips [ChipNum ].BankNum ][CrtChips [ChipNum ].LoadAddress == 0x8000 ? 0 : 1 ] = CrtChips [ChipNum ].ChipROM ;
135+ {
136+ const uint16_t Bank = CrtChips [ChipNum ].BankNum ;
137+ if (Bank >= 128 ) EasyFlashBankMask = 0xff ;
138+ else if (Bank >= 64 && EasyFlashBankMask != 0xff ) EasyFlashBankMask = 0x7f ;
139+ BankDecode [Bank ][CrtChips [ChipNum ].LoadAddress == 0x8000 ? 0 : 1 ] = CrtChips [ChipNum ].ChipROM ;
140+ }
111141 else Serial .printf ("Unexp Bank# (%d) in chip %d\n" , CrtChips [ChipNum ].BankNum , ChipNum );
112142 }
113143
114144 memset (EZFlashRAM , 0 , 256 );
115145
116146#ifdef MinimumBuild
117147 //initialize/invalidate swap buffer, pre-load first swappable chips
118- uint8_t ChipNum = 0 ;
148+ uint16_t ChipNum = 0 ;
119149 for (uint8_t BuffNum = 0 ; BuffNum < Num8kSwapBuffers ; BuffNum ++ )
120150 {
121151 SwapBuffers [BuffNum ].Offset = 0 ; //default to zero/invalid
152+ // Bank 0 must be resident before the C64 is released, even when CHIP
153+ // packets are unordered and its halves were not loaded into RAM.
154+ uint8_t * StartupHalf = BuffNum < 2 ? BankDecode [0 ][BuffNum ] : NULL ;
155+ if (((uint32_t )StartupHalf & SwapSeekAddrMask ) == SwapSeekAddrMask )
156+ {
157+ if (!ReadBank ((uint32_t )StartupHalf & ~SwapSeekAddrMask , SwapBuffers [BuffNum ].Image ))
158+ {
159+ EasyFlashSwapFailed ();
160+ return ;
161+ }
162+ SwapBuffers [BuffNum ].Offset = (uint32_t )StartupHalf ;
163+ continue ;
164+ }
122165 //find next chip marked as swappable
123166 while (ChipNum < NumCrtChips )
124167 {
125- if (((uint32_t )CrtChips [ChipNum ].ChipROM & SwapSeekAddrMask ) == SwapSeekAddrMask )
168+ if (((uint32_t )CrtChips [ChipNum ].ChipROM & SwapSeekAddrMask ) == SwapSeekAddrMask &&
169+ CrtChips [ChipNum ].BankNum != 0 )
126170 {
127171 //pre-load and update
128- LoadBank ((uint32_t )CrtChips [ChipNum ].ChipROM & ~SwapSeekAddrMask , SwapBuffers [BuffNum ].Image );
172+ if (!ReadBank ((uint32_t )CrtChips [ChipNum ].ChipROM & ~SwapSeekAddrMask , SwapBuffers [BuffNum ].Image ))
173+ {
174+ EasyFlashSwapFailed ();
175+ return ;
176+ }
129177 SwapBuffers [BuffNum ].Offset = (uint32_t )CrtChips [ChipNum ].ChipROM ;
130178 Printf_Swaps ("Pre%d: %08x\n" , BuffNum , (uint32_t ) SwapBuffers [BuffNum ].Offset & ~SwapSeekAddrMask );
131179 ChipNum ++ ;
@@ -137,8 +185,13 @@ void InitHndlr_EasyFlash()
137185#endif
138186
139187 //start with Bank 0:
188+ #ifdef MinimumBuild
189+ LOROM_Image = ImageCheckAssign (BankDecode [0 ][0 ]);
190+ HIROM_Image = ImageCheckAssign (BankDecode [0 ][1 ]);
191+ #else
140192 LOROM_Image = BankDecode [0 ][0 ];
141193 HIROM_Image = BankDecode [0 ][1 ];
194+ #endif
142195 //Printf_dbg("Jmp vect: $%02x%02x\n", HIROM_Image[0x1FFD], HIROM_Image[0x1FFC]);
143196 if (memcmp (HIROM_Image + 0x1800 , "eapi" , 4 )== 0 ) Serial .printf ("EAPI found\n" );
144197 else Printf_dbg ("EAPI *not* found: %d %d %d %d\n" , HIROM_Image [0x1800 ], HIROM_Image [0x1801 ], HIROM_Image [0x1802 ], HIROM_Image [0x1803 ]);
@@ -182,7 +235,7 @@ void IO1Hndlr_EasyFlash(uint8_t Address, bool R_Wn)
182235 switch (Address )
183236 {
184237 case 0x00 : // Register $DE00 – EasyFlash Bank (write-only)
185- Data &= 0x3f ;
238+ Data &= EasyFlashBankMask ;
186239#ifdef FeatVMHost
187240 CurrentEasyFlashBank = Data ;
188241#endif
@@ -248,7 +301,12 @@ void PollingHndlr_EasyFlash()
248301 if (HIROM_Image && HIROM_Image == SwapBuffers [NextSwapBuffNum ].Image )
249302 if (++ NextSwapBuffNum == Num8kSwapBuffers ) NextSwapBuffNum = 0 ;
250303
251- LoadBank ((uint32_t )LOROM_Image & ~SwapSeekAddrMask , SwapBuffers [NextSwapBuffNum ].Image );
304+ SwapBuffers [NextSwapBuffNum ].Offset = 0 ;
305+ if (!ReadBank ((uint32_t )LOROM_Image & ~SwapSeekAddrMask , SwapBuffers [NextSwapBuffNum ].Image ))
306+ {
307+ EasyFlashSwapFailed ();
308+ return ;
309+ }
252310 Printf_Swaps ("L%02d: %08x " , NextSwapBuffNum , (uint32_t )LOROM_Image & ~SwapSeekAddrMask );
253311 SwapBuffers [NextSwapBuffNum ].Offset = (uint32_t )LOROM_Image ;
254312 LOROM_Image = SwapBuffers [NextSwapBuffNum ].Image ;
@@ -261,7 +319,12 @@ void PollingHndlr_EasyFlash()
261319 if (LOROM_Image && LOROM_Image == SwapBuffers [NextSwapBuffNum ].Image )
262320 if (++ NextSwapBuffNum == Num8kSwapBuffers ) NextSwapBuffNum = 0 ;
263321
264- LoadBank ((uint32_t )HIROM_Image & ~SwapSeekAddrMask , SwapBuffers [NextSwapBuffNum ].Image );
322+ SwapBuffers [NextSwapBuffNum ].Offset = 0 ;
323+ if (!ReadBank ((uint32_t )HIROM_Image & ~SwapSeekAddrMask , SwapBuffers [NextSwapBuffNum ].Image ))
324+ {
325+ EasyFlashSwapFailed ();
326+ return ;
327+ }
265328 Printf_Swaps ("H%02d: %08x " , NextSwapBuffNum , (uint32_t )HIROM_Image & ~SwapSeekAddrMask );
266329 SwapBuffers [NextSwapBuffNum ].Offset = (uint32_t )HIROM_Image ;
267330 HIROM_Image = SwapBuffers [NextSwapBuffNum ].Image ;
0 commit comments