/ MCUME_teensy / teensy64 / patches.cpp
patches.cpp
  1  /*
  2  	Copyright Frank Bösing, 2017
  3  
  4  	This file is part of Teensy64.
  5  
  6      Teensy64 is free software: you can redistribute it and/or modify
  7      it under the terms of the GNU General Public License as published by
  8      the Free Software Foundation, either version 3 of the License, or
  9      (at your option) any later version.
 10  
 11      Teensy64 is distributed in the hope that it will be useful,
 12      but WITHOUT ANY WARRANTY; without even the implied warranty of
 13      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 14      GNU General Public License for more details.
 15  
 16      You should have received a copy of the GNU General Public License
 17      along with Teensy64.  If not, see <http://www.gnu.org/licenses/>.
 18  
 19      Diese Datei ist Teil von Teensy64.
 20  
 21      Teensy64 ist Freie Software: Sie können es unter den Bedingungen
 22      der GNU General Public License, wie von der Free Software Foundation,
 23      Version 3 der Lizenz oder (nach Ihrer Wahl) jeder späteren
 24      veröffentlichten Version, weiterverbreiten und/oder modifizieren.
 25  
 26      Teensy64 wird in der Hoffnung, dass es nützlich sein wird, aber
 27      OHNE JEDE GEWÄHRLEISTUNG, bereitgestellt; sogar ohne die implizite
 28      Gewährleistung der MARKTFÄHIGKEIT oder EIGNUNG FÜR EINEN BESTIMMTEN ZWECK.
 29      Siehe die GNU General Public License für weitere Details.
 30  
 31      Sie sollten eine Kopie der GNU General Public License zusammen mit diesem
 32      Programm erhalten haben. Wenn nicht, siehe <http://www.gnu.org/licenses/>.
 33  
 34  */
 35  
 36  #include "patches.h"
 37  #include "emuapi.h"
 38  #include "platform_config.h"
 39  
 40  
 41  #define DIRECTORY ROMSDIR + "/\0"
 42  
 43  static char filename[64];
 44  static char buffer[2];
 45  
 46  extern char * menuSelection(void);
 47  
 48  void patchLOAD(void) {
 49  
 50  int device;
 51  int secondaryAddress;
 52  uint16_t addr,size;
 53  
 54  	device = cpu.RAM[0xBA];
 55  	if (device != 1) {
 56  		//Jump to unpatched original address:
 57  		cpu.pc = rom_kernal[cpu.pc - 0xe000 + 1] * 256 + rom_kernal[cpu.pc - 0xe000];
 58  		return;
 59  	};
 60  
 61  
 62  #if XXX
 63  	if (cpu.RAM[cpu.RAM[0xBC] * 256 + cpu.RAM[0xBB]] == '$' && cpu.RAM[0xB7] == 1) {
 64  		//Directoy listing with LOAD "$"
 65  		printf("Listing of ");
 66  		printf(DIRECTORY);
 67  		printf("\n");
 68  		file = SD.open(DIRECTORY);
 69  		int blocks, start, len;
 70  		addr = cpu.RAM[0x2C] * 256 + cpu.RAM[0x2B];
 71  
 72  		/*first line of BASIC listing */
 73  		start = addr;
 74  		cpu.RAM[addr++] = (start + 30) & 0xff;
 75  		cpu.RAM[addr++] = (start + 30) >> 8;
 76  		blocks = 0;
 77  		cpu.RAM[addr++] = blocks & 0xff;
 78  		cpu.RAM[addr++] = blocks >> 8;
 79  
 80  		const char title[] = "\x12\"TEENSY64        \" FB " VERSION;
 81  		strcpy((char * )&cpu.RAM[addr], title);
 82  		addr = start + 30;
 83  
 84  		while (true) {
 85  			entry = file.openNextFile();
 86  			if (! entry) {
 87  				// no more files
 88  				break;
 89  			}
 90  			int offset;
 91  			if (!entry.isDirectory()) {
 92  
 93  				/* Listing to BASIC-RAM */
 94  				start = addr;
 95  				offset = 0;
 96  
 97  				//pointer to next line:
 98  				cpu.RAM[addr++] = (start + 32) & 0xff;
 99  				cpu.RAM[addr++] = (start + 32) >> 8;
100  
101  				//# of blocks
102  				blocks = ceil((float)entry.size()/256.0f);
103  				cpu.RAM[addr++] = blocks & 0xff;
104  				cpu.RAM[addr++] = blocks >> 8;
105  
106  				if (blocks < 100)   { cpu.RAM[addr++] = ' '; offset++;}
107  				if (blocks < 10)    { cpu.RAM[addr++] = ' '; offset++; }
108  			 	cpu.RAM[addr++] = ' ';
109  
110  				//filename:
111  				cpu.RAM[addr++] = '"';
112  				char *s = (char * )&cpu.RAM[addr];
113  				entry.getName(s, 17);
114  				while(*s) {*s = toupper(*s); s++;}
115  				//strcpy((char * )&cpu.RAM[addr], entry.name());
116  				len = strlen((char * )&cpu.RAM[addr]);
117  
118  				if (len > 16) len = 16;
119  				addr += len;
120  				cpu.RAM[addr++] = '"';
121  
122  				//fill with space
123  				while ((addr-start) < (32)) { cpu.RAM[addr++] = ' ';}
124  
125  				//display "PRG"
126  				addr = start + 23 + offset;
127  				cpu.RAM[addr++] = ' ';
128  				cpu.RAM[addr++] = 'P';
129  				cpu.RAM[addr++] = 'R';
130  				cpu.RAM[addr++] = 'G';
131  
132  				//line-ending
133  				cpu.RAM[start+31] = 0;
134  				addr = start + 32;
135  
136  				/* Listing to serial console */
137  				itoa (blocks,filename,10);
138  				len = strlen(filename);
139  				while (len < 4) { strcat(filename," "); len++; };
140  				strcat(filename, "\"");
141  				char nbuf[18] = {0};
142  				entry.getName(nbuf, 17);
143  				strcat(filename, nbuf);
144  				//strcat(filename, entry.getName());
145  				strcat(filename, "\"");
146  				len = strlen(filename);
147  				while (len < 18+4) { strcat(filename," "); len++; };
148  				strcat(filename," PRG   ");
149  				//printf(filename);
150  
151  			}
152  			entry.close();
153  		}
154  		file.close();
155  
156          /*add last line to BASIC listing*/
157  		start = addr;
158  		cpu.RAM[addr++] = (start + 32) & 0xff;
159  		cpu.RAM[addr++] = (start + 32) >> 8;
160  		//# of blocks. todo : determine free space on sd card
161  		blocks = 65535;
162  		cpu.RAM[addr++] = blocks & 0xff;
163  		cpu.RAM[addr++] = blocks >> 8;
164  		if (blocks < 100) { cpu.RAM[addr++] = ' ';}
165  		if (blocks < 10)  { cpu.RAM[addr++] = ' ';}
166  		const char blockfree[] = "BLOCKS FREE.";
167  
168  		strcpy((char * )&cpu.RAM[addr], blockfree);
169  		len = strlen(blockfree);
170  		addr += len;
171  		while ((addr-start) < (32)) { cpu.RAM[addr++] = ' ';}
172  		cpu.RAM[start+31] = 0;
173  		cpu.RAM[start+32] = 0;
174  		cpu.RAM[start+33] = 0;
175  
176  		cpu.y = 0x49; //Offset for "LOADING"
177  		cpu.pc = 0xF12B; //Print and return
178  		return;
179  	} // end directory listing
180  #endif
181  
182  	//$B7    : Length of file name or disk command
183  	//$BB-$BC: Pointer to current file name or disk command
184    memset(filename,0,sizeof(filename));
185    if ( cpu.RAM[0xB7] == 0) {
186  	strcpy(filename,menuSelection());
187    }
188    else {
189  	strncpy(filename, (char*)&cpu.RAM[cpu.RAM[0xBC] * 256 + cpu.RAM[0xBB]], cpu.RAM[0xB7] );
190    }     
191  	secondaryAddress = cpu.RAM[0xB9];
192  
193    Serial.println("loading");
194  	//printf("%s,%d,%d:", filename, device, secondaryAddress);
195  #ifdef EXTERNAL_SD  
196    tft.stopDMA();
197    //emu_resetSD();
198    tft.fillScreenNoDma( RGBVAL16(0x00,0x00,0x00) );
199  #endif  
200  	if (emu_FileOpen(filename) == 0) {
201  		//Serial.println("not found");
202  		cpu.pc = 0xf530; //Jump to $F530
203  #ifdef EXTERNAL_SD  
204      tft.startDMA(); 
205  #endif  
206  		return;
207  	}
208  
209  	size = emu_FileSize(filename);
210  	emu_FileOpen(filename);
211  	emu_FileRead(buffer, 2);
212  	addr = buffer[1] * 256 + buffer[0];
213  	emu_FileRead((char*)&cpu.RAM[addr], size - 2);
214  	emu_FileClose();
215  
216  	cpu.RAM[0xAF] = (addr + size - 2) & 0xff;
217  	cpu.RAM[0xAE] = (addr + size - 2) / 256;
218  
219  	cpu.y = 0x49; //Offset for "LOADING"
220  	cpu.pc = 0xF12B; //Print and return
221  	emu_printf("loaded");
222  #ifdef EXTERNAL_SD  
223    tft.startDMA(); 
224  #endif
225  	return;
226  }
227  
228  void patchSAVE(void) {
229  #ifdef XXX
230  int device;
231  int secondaryAddress;
232  uint16_t addr,size;
233  
234  	Serial.println("Patched SAVE");
235  	device = cpu.RAM[0xBA];
236  	if (device != 1) {
237  		//Jump to unpatched original address:
238  		cpu.pc = rom_kernal[cpu.pc - 0xe000 + 1] * 256 + rom_kernal[cpu.pc - 0xe000];
239  		return;
240  	};
241  
242  	if (!SDinitialized) {
243  		cpu.pc = 0xF707; //Device not present error
244  		Serial.println("SD Card not initialized");
245  		return;
246  	}
247  
248  	if( !SD.exists(DIRECTORY) && SD.mkdir(DIRECTORY) ) {
249  		cpu.pc = 0xF707; //Device not present error
250  		Serial.println("SD: Could not create " DIRECTORY);
251  	}
252  
253  	//$B7    : Length of file name or disk command
254  	//$BB-$BC: Pointer to current file name or disk command
255  	memset(filename,0,sizeof(filename));
256  	strcpy(filename, DIRECTORY);
257  	strncat(filename, (char*)&cpu.RAM[cpu.RAM[0xBC] * 256 + cpu.RAM[0xBB]], cpu.RAM[0xB7] );
258  
259  	secondaryAddress = cpu.RAM[0xB9];
260  
261  	Serial.print(filename);
262  	Serial.print(",");
263  	Serial.print(device);
264  	Serial.print(",");
265  	Serial.print(secondaryAddress);
266  	Serial.print(":");
267  
268  	addr = cpu.RAM[cpu.a + 1] * 256 + cpu.RAM[cpu.a];
269  	size = (cpu.y * 256 + cpu.x) - addr;
270  
271  	buffer[0] = addr & 0xff;
272  	buffer[1] = addr >> 8;
273  
274  	if (SD.exists(filename)) SD.remove(filename);
275  	file = SD.open(filename, FILE_WRITE);
276  	if (!file) {
277  		Serial.println ("not possible.");
278  		cpu.pc = 0xf530; //Jump to $F530
279  		return;
280  	}
281  	file.write(buffer, 2);
282  	file.write(&cpu.RAM[addr], size);
283  	file.close();
284  
285  	if (cpu.RAM[0x9D] & 128) {
286  		uint16_t pushval = 0xF68D;
287  		cpu.RAM[BASE_STACK + cpu.sp] = (pushval >> 8) & 0xFF;
288  		cpu.RAM[BASE_STACK + ((cpu.sp - 1) & 0xFF)] = pushval & 0xFF;
289  		cpu.sp -= 2;
290  
291  		cpu.y = 0x51;
292  		cpu.pc = 0xF12F;
293  	} else {
294  		cpu.pc = 0xF68D;
295  	}
296  
297  	Serial.println("saved.");
298  	return;
299  #endif	
300  }