mirror of
				https://github.com/garrettsworkshop/GWRAM.SYSTEM.git
				synced 2025-10-24 11:50:48 -07:00 
			
		
		
		
	Added RAM2GS functionality
This commit is contained in:
		
							
								
								
									
										38
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										38
									
								
								Makefile
									
									
									
									
									
								
							| @@ -1,14 +1,14 @@ | ||||
| all:    RAM2Eutil.po RAM2Eutil.dbg.po | ||||
|  | ||||
| .PHONY: clean | ||||
|  | ||||
| obj: | ||||
| 	@mkdir obj | ||||
|  | ||||
| bin: | ||||
| 	@mkdir bin | ||||
|  | ||||
| ram2e.c: | ||||
| obj/main.o: obj main.c | ||||
| 	cc65 main.c -O --cpu 6502 -t apple2enh -o obj/main.s | ||||
| 	ca65 obj/main.s -o obj/main.o | ||||
|  | ||||
| obj/ram2e.o: obj ram2e.c | ||||
| 	cc65 ram2e.c -O --cpu 6502 -t apple2enh -o obj/ram2e.s | ||||
| @@ -18,19 +18,35 @@ obj/ram2e.dbg.o: obj ram2e.c | ||||
| 	cc65 ram2e.c -O --cpu 6502 -t apple2enh -o obj/ram2e.dbg.s -DSKIP_RAM2E_DETECT | ||||
| 	ca65 obj/ram2e.dbg.s -o obj/ram2e.dbg.o | ||||
|  | ||||
| bin/ram2e.sys: bin obj/ram2e.o | ||||
| 	ld65 -o bin/ram2e.sys obj/ram2e.o -C apple2enh-system.cfg --lib apple2enh.lib -D __EXEHDR__=0 | ||||
| obj/ram2gs_asm.o: obj ram2gs_asm.s | ||||
| 	ca65 ram2gs_asm.s -o obj/ram2gs_asm.o | ||||
|  | ||||
| bin/ram2e.dbg.sys: bin obj/ram2e.dbg.o | ||||
| 	ld65 -o bin/ram2e.dbg.sys obj/ram2e.dbg.o -C apple2enh-system.cfg --lib apple2enh.lib -D __EXEHDR__=0 | ||||
| obj/ram2gs.o: obj ram2gs.c | ||||
| 	cc65 ram2gs.c -O --cpu 6502 -t apple2enh -o obj/ram2gs.s | ||||
| 	ca65 obj/ram2gs.s -o obj/ram2gs.o | ||||
|  | ||||
| RAM2Eutil.po: bin/ram2e.sys | ||||
| obj/ram2gs.dbg.o: obj ram2gs.c | ||||
| 	cc65 ram2gs.c -O --cpu 6502 -t apple2enh -o obj/ram2gs.dbg.s -DSKIP_RAM2GS_DETECT | ||||
| 	ca65 obj/ram2gs.dbg.s -o obj/ram2gs.dbg.o | ||||
|  | ||||
| obj/util.o: obj util.c | ||||
| 	cc65 util.c -O --cpu 6502 -t apple2enh -o obj/util.s | ||||
| 	ca65 obj/util.s -o obj/util.o | ||||
|  | ||||
| bin/main.sys: bin obj/main.o obj/ram2e.o obj/ram2gs.o obj/ram2gs_asm.o obj/util.o | ||||
| 	ld65 -o bin/main.sys obj/main.o obj/ram2gs.o obj/ram2e.o obj/ram2gs_asm.o obj/util.o -C apple2enh-system.cfg --lib apple2enh.lib -D __EXEHDR__=0 | ||||
|  | ||||
| bin/main.dbg.sys: bin obj/main.o obj/ram2e.dbg.o obj/ram2gs.dbg.o obj/ram2gs_asm.o obj/util.o | ||||
| 	ld65 -o bin/main.dbg.sys obj/main.o obj/ram2gs.dbg.o obj/ram2e.dbg.o obj/ram2gs_asm.o obj/util.o -C apple2enh-system.cfg --lib apple2enh.lib -D __EXEHDR__=0 | ||||
|  | ||||
| RAM2Eutil.po: bin/main.sys | ||||
| 	cp prodos140.po bin/RAM2Eutil.po | ||||
| 	cat bin/ram2e.sys | java -jar ./AppleCommander-ac-1.6.0.jar -p bin/RAM2Eutil.po ram2e.system sys 0x2000 | ||||
| 	cat bin/main.sys | java -jar ./AppleCommander-ac-1.6.0.jar -p bin/RAM2Eutil.po gwram.system sys 0x2000 | ||||
|  | ||||
| RAM2Eutil.dbg.po: bin/ram2e.dbg.sys | ||||
| RAM2Eutil.dbg.po: bin/main.dbg.sys | ||||
| 	cp prodos140.po bin/RAM2Eutil.dbg.po | ||||
| 	cat bin/ram2e.dbg.sys | java -jar ./AppleCommander-ac-1.6.0.jar -p bin/RAM2Eutil.dbg.po ram2e.system sys 0x2000 | ||||
| 	cat bin/main.dbg.sys | java -jar ./AppleCommander-ac-1.6.0.jar -p bin/RAM2Eutil.dbg.po gwram.system sys 0x2000 | ||||
|  | ||||
| .PHONY: clean | ||||
| clean: | ||||
| 	rm -fr bin obj | ||||
|   | ||||
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								bin/RAM2Eutil.po
									
									
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								bin/RAM2Eutil.po
									
									
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										32
									
								
								main.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								main.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| #include <conio.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
|  | ||||
| #include "ram2e.h" | ||||
| #include "ram2gs.h" | ||||
|  | ||||
| int main(void) | ||||
| { | ||||
| 	// First clear screen | ||||
| 	clrscr(); | ||||
|  | ||||
| 	// Check machine type | ||||
| 	switch ((get_ostype() & 0xF0)) { | ||||
| 		case APPLE_IIE: | ||||
| 			ram2e_main(); | ||||
| 			break; | ||||
| 		case APPLE_IIGS: | ||||
| 			ram2gs_main(); | ||||
| 			break; | ||||
| 		default: | ||||
| 			// If not on IIe or IIgs, show an error message and quit | ||||
| 			gotoxy(0, 8); | ||||
| 			cputs(" THIS PROGRAM REQUIRES APPLE IIE OR IIGS"); | ||||
| 			gotoxy(0, 10); | ||||
| 			cputs(" PRESS ANY KEY TO QUIT."); | ||||
| 			cgetc(); // Wait for key | ||||
| 			clrscr(); // Clear screen before quitting | ||||
| 			return EXIT_SUCCESS; | ||||
| 			break; | ||||
| 	}  | ||||
| } | ||||
							
								
								
									
										90
									
								
								ram2e.c
									
									
									
									
									
								
							
							
						
						
									
										90
									
								
								ram2e.c
									
									
									
									
									
								
							| @@ -5,20 +5,10 @@ | ||||
| #include <ctype.h> | ||||
| #include <stdint.h> | ||||
|  | ||||
| #define true 1 | ||||
| #define false 0 | ||||
| #include "util.h" | ||||
|  | ||||
|  | ||||
| #define VBL ((signed char*)0xC019) | ||||
| const uint8_t SPIN_HALFCYCLES = 3; | ||||
| const uint8_t SPIN_FRAMESPERCHAR = 4; | ||||
|  | ||||
| #define PB0 ((char*)0xC061) | ||||
| #define PB1 ((char*)0xC062) | ||||
| static char read_applekey(void) { return (*PB0 | *PB1) & 0x80; } | ||||
|  | ||||
| char _cmd; | ||||
| char _arg; | ||||
| static char _cmd; | ||||
| static char _arg; | ||||
| /* ram2e_cmd(...) issues a coded command+argument sequence to the RAM2E */ | ||||
| static void ram2e_cmd(char cmd, char arg) { | ||||
| 	// Load operation and data bytes into X and Y registers | ||||
| @@ -100,7 +90,7 @@ static char auxram_detect() { | ||||
| } | ||||
|  | ||||
| /* ram2e_detect() returns true if a RAM2E II has been detected */ | ||||
| uint8_t _detect; | ||||
| static uint8_t _detect; | ||||
| static char ram2e_detect() { | ||||
| 	#ifdef SKIP_RAM2E_DETECT | ||||
| 	return true; | ||||
| @@ -148,8 +138,8 @@ static char ram2e_detect() { | ||||
| } | ||||
|  | ||||
| /* ramworks_getsize() returns the number of banks of RAM2E aux memory */ | ||||
| uint8_t _rwsize; | ||||
| uint8_t _rwnot16mb; | ||||
| static uint8_t _rwsize; | ||||
| static uint8_t _rwnot16mb; | ||||
| static uint16_t ramworks_getsize() { | ||||
| 	_rwnot16mb = 1; // Set "not 16 mb" flag | ||||
|  | ||||
| @@ -169,11 +159,11 @@ static uint16_t ramworks_getsize() { | ||||
| 	CountLoop: | ||||
| 	__asm__("sty $C073"); // Set bank | ||||
| 	__asm__("cpy $00"); // Is bank num stored at address 0? | ||||
| 	__asm__("bne %g", NotMem); // If not, skip increment | ||||
| 	__asm__("bne %g", AfterInc); // If not, skip increment | ||||
| 	__asm__("inx"); // If so, increment bank count | ||||
| 	__asm__("bne %g", NotMem); // Skip next if x!=0 | ||||
| 	__asm__("bne %g", AfterInc); // Skip next if x!=0 | ||||
| 	__asm__("stx %v", _rwnot16mb); // Othwerwise rolled over so clear rwnot16mb | ||||
| 	NotMem: | ||||
| 	AfterInc: | ||||
| 	__asm__("iny"); // Move to next bank | ||||
| 	__asm__("bne %g", CountLoop); // Repeat if not on bank 0 | ||||
|  | ||||
| @@ -250,67 +240,12 @@ static void menu(void) | ||||
| 	cputs("Press [Q] to quit without saving."); | ||||
| } | ||||
|  | ||||
| static void spin(uint8_t x, uint8_t y) {  | ||||
| 	char i; | ||||
|  | ||||
| 	// Sync to frame before starting | ||||
| 	while (*VBL >= 0); | ||||
|  | ||||
| 	// Wait and animate spinner. | ||||
| 	// Spin_half | ||||
| 	for (i = 0; i < SPIN_HALFCYCLES; i++) { | ||||
| 		char j; | ||||
| 		for (j = 0; j < 4; j++) { | ||||
| 			char spinchar; | ||||
| 			char k; | ||||
|  | ||||
| 			// Assign spinner char based on j | ||||
| 			switch (j) { | ||||
| 				case 0: spinchar = '\\'; break; | ||||
| 				case 1: spinchar = '|'; break; | ||||
| 				case 2: spinchar = '/'; break; | ||||
| 				case 3: spinchar = '-'; break; | ||||
| 				default: spinchar = '-'; break; | ||||
| 			} | ||||
|  | ||||
| 			// Write it to screen | ||||
| 			gotoxy(x, y); | ||||
| 			putchar(spinchar); | ||||
|  | ||||
| 			// Wait specificed number of frames | ||||
| 			for (k = 0; k < SPIN_FRAMESPERCHAR; k++) { | ||||
| 				while (*VBL < 0); | ||||
| 				while (*VBL >= 0); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Wait a frame when finished | ||||
| 	while (*VBL < 0); | ||||
| 	while (*VBL >= 0); | ||||
| } | ||||
|  | ||||
| int main(void) | ||||
| int ram2e_main(void) | ||||
| { | ||||
| 	char mask; | ||||
| 	char nvm; | ||||
| 	int reset_count; | ||||
|  | ||||
| 	// First clear screen | ||||
| 	clrscr(); | ||||
|  | ||||
| 	// Make sure we are running on an Apple IIe | ||||
| 	if((get_ostype() & 0xF0) != APPLE_IIE) { | ||||
| 		// If not on Apple IIe, show an error message and quit | ||||
| 		gotoxy(0, 8); | ||||
| 		cputs(" THIS PROGRAM REQUIRES AN APPLE IIE."); | ||||
| 		gotoxy(0, 10); | ||||
| 		cputs(" PRESS ANY KEY TO QUIT."); | ||||
| 		cgetc(); // Wait for key | ||||
| 		clrscr(); // Clear screen before quitting | ||||
| 		return EXIT_SUCCESS; | ||||
| 	} | ||||
|  | ||||
| 	// Check for RAM2E | ||||
| 	if(!auxram_detect() || !ram2e_detect()) { | ||||
| 		// If no RAM2E, show an error message and quit | ||||
| @@ -331,7 +266,7 @@ int main(void) | ||||
| 	reset_count = 0; | ||||
| 	while (true) { | ||||
| 		// Set capacity mask or quit according to keypress. | ||||
| 		switch (toupper(cgetc())) { | ||||
| 		switch (toupper(cgetc() & 0x7F)) { | ||||
| 			case 'Q' : { | ||||
| 				clrscr(); | ||||
| 				return EXIT_SUCCESS; | ||||
| @@ -366,8 +301,7 @@ int main(void) | ||||
| 			} default: continue; | ||||
| 		} | ||||
|  | ||||
| 		// Check if pressed with apple key. | ||||
| 		// If so, save to nonvolatile memory. | ||||
| 		// Check if pressed with apple key. If so, save to nonvolatile memory. | ||||
| 		if (read_applekey()) { nvm = true; } | ||||
| 		break; | ||||
| 	} | ||||
|   | ||||
							
								
								
									
										6
									
								
								ram2e.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								ram2e.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| #ifndef RAM2E_H | ||||
| #define RAM2E_H | ||||
|  | ||||
| int ram2e_main(void); | ||||
|  | ||||
| #endif /* RAM2E_H */ | ||||
							
								
								
									
										173
									
								
								ram2gs.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										173
									
								
								ram2gs.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,173 @@ | ||||
| #include <stdlib.h> | ||||
| #include <conio.h> | ||||
| #include <string.h> | ||||
| #include <stdio.h> | ||||
| #include <ctype.h> | ||||
| #include <stdint.h> | ||||
|  | ||||
| #include "util.h" | ||||
| #include "ram2gs_asm.h" | ||||
|  | ||||
| static void ram2gs_erase() { ram2gs_cmd(0x28); } | ||||
| static void ram2gs_program() { ram2gs_cmd(0x24); } | ||||
| static void ram2gs_set4mb() { ram2gs_cmd(0x10); } | ||||
| static void ram2gs_set8mb() { ram2gs_cmd(0x11); } | ||||
| static void ram2gs_setnvm(char en8meg) { | ||||
| 	char i; | ||||
| 	// Clock in 0 to enable this setting entry | ||||
| 	ram2gs_cmd(0x20); | ||||
| 	ram2gs_cmd(0x22); | ||||
|  | ||||
| 	if (en8meg) { | ||||
| 		// Clock in 1 to enable 8mb | ||||
| 		ram2gs_cmd(0x21); | ||||
| 		ram2gs_cmd(0x23); | ||||
| 	} else { | ||||
| 		// Clock in 0 to disable 8mb | ||||
| 		ram2gs_cmd(0x20); | ||||
| 		ram2gs_cmd(0x22); | ||||
| 	} | ||||
|  | ||||
| 	// Clock in 14 dummy "1"s | ||||
| 	for (i = 0; i < 14; i++) { | ||||
| 		ram2gs_cmd(0x21); | ||||
| 		ram2gs_cmd(0x23); | ||||
| 	} | ||||
|  | ||||
| 	ram2gs_program(); | ||||
| } | ||||
|  | ||||
| static void menu(void) | ||||
| { | ||||
| 	uint8_t bankcount = ram2gs_getsize(); | ||||
| 	gotoxy(5, 1); | ||||
| 	cputs("-- RAM2GS Capacity Settings --"); | ||||
| 	gotoxy(4, 3); | ||||
| 	printf("Current RAM2GS capacity: %d kB", bankcount * 64); | ||||
|  | ||||
| 	gotoxy(1, 6); | ||||
| 	cputs("Select desired memory capacity:"); | ||||
|  | ||||
| 	gotoxy(4, 8); | ||||
| 	cputs("1. 4 megabytes"); | ||||
| 	gotoxy(4, 10); | ||||
| 	cputs("2. 8 megabytes"); | ||||
|  | ||||
| 	gotoxy(1, 18); | ||||
| 	cputs("Capacity will be saved until power-off."); | ||||
|  | ||||
| 	gotoxy(1, 20); | ||||
| 	cputs("To remember capacity setting in"); | ||||
| 	gotoxy(1, 21); | ||||
| 	cputs("nonvolatile memory, press Apple+number."); | ||||
|  | ||||
| 	gotoxy(1, 23); | ||||
| 	cputs("Press [Q] to quit without saving."); | ||||
| } | ||||
|  | ||||
| int ram2gs_main(void) | ||||
| { | ||||
| 	char en8meg; | ||||
| 	char nvm; | ||||
| 	int reset_count; | ||||
|  | ||||
| 	// Check for RAM2GS | ||||
| 	#ifndef SKIP_RAM2GS_DETECT | ||||
| 	if(!ram2gs_detect()) { | ||||
| 		// If no RAM2GS, show an error message and quit | ||||
| 		gotoxy(0, 8); | ||||
| 		cputs(" No RAM2GS II detected."); | ||||
| 		gotoxy(0, 10); | ||||
| 		cputs(" Press any key to quit."); | ||||
| 		cgetc(); // Wait for key | ||||
| 		clrscr(); // Clear screen before quitting | ||||
| 		return EXIT_SUCCESS; | ||||
| 	} | ||||
| 	#endif | ||||
|  | ||||
| 	menu(); // Print menu | ||||
|  | ||||
| 	// Get user choice from menu | ||||
| 	en8meg = 0; | ||||
| 	nvm = 0; | ||||
| 	reset_count = 0; | ||||
| 	while (true) { | ||||
| 		// Set capacity or quit according to keypress. | ||||
| 		switch (toupper(cgetc() & 0x7F)) { | ||||
| 			case 'Q' : { | ||||
| 				clrscr(); | ||||
| 				return EXIT_SUCCESS; | ||||
| 			} | ||||
| 			case '!': nvm = true; | ||||
| 			case '1': en8meg = 0; ram2gs_set4mb(); break; | ||||
| 			case '@': nvm = true; | ||||
| 			case '2': en8meg = 1; ram2gs_set8mb(); break; | ||||
| 			case 'R': { | ||||
| 				reset_count++; | ||||
| 				if (reset_count >= 100) { | ||||
| 					// Show message about saving. | ||||
| 					clrscr(); // Clear screen | ||||
| 					gotoxy(1, 8); | ||||
| 					cputs("Resetting RAM2GS settings."); | ||||
| 					gotoxy(1, 9); | ||||
| 					cputs("Do not turn off your Apple."); | ||||
|  | ||||
| 					ram2gs_erase(); // Erase RAM2GS settings memory | ||||
| 					ram2gs_set8mb(); // Enable 8 megabytes now | ||||
|  | ||||
| 					// Wait for >= 500ms on even the fastest systems. | ||||
| 					spin(32, 8); | ||||
| 					 | ||||
| 					// Show success message and quit | ||||
| 					clrscr(); // Clear screen | ||||
| 					gotoxy(1, 8); | ||||
| 					cputs("RAM2GS settings reset successfully."); | ||||
| 					goto end; | ||||
| 				} | ||||
| 			} default: continue; | ||||
| 		} | ||||
|  | ||||
| 		// Check if pressed with apple key. If so, save to nonvolatile memory. | ||||
| 		if (read_applekey()) { nvm = true; } | ||||
| 		break; | ||||
| 	} | ||||
|  | ||||
| 	// Clear screen in preparation to show saving or success message. | ||||
| 	clrscr(); | ||||
|  | ||||
| 	if (nvm) { // Save in NVM if requested. | ||||
| 		// Show message about saving. | ||||
| 		gotoxy(1, 8); | ||||
| 		cputs("Saving RAM2GS capacity setting."); | ||||
| 		gotoxy(1, 9); | ||||
| 		cputs("Do not turn off your Apple."); | ||||
| 		// Save capacity in nonvolatile memory. | ||||
| 		ram2gs_setnvm(en8meg); | ||||
| 		// Wait for >= 500ms on even the fastest systems. | ||||
| 		spin(33, 8); | ||||
| 		// Print success message | ||||
| 		clrscr(); // Clear screen | ||||
| 		gotoxy(1, 8); | ||||
| 		cputs("RAM2GS capacity saved successfully."); | ||||
| 	} else { // Print success message if not saving in NVM. | ||||
| 		gotoxy(1, 8); | ||||
| 		cputs("RAM2GS capacity set successfully."); | ||||
| 	} | ||||
|  | ||||
| 	end: | ||||
| 	if (nvm) { // Show end message for nonvolatile save | ||||
| 		gotoxy(1, 10); | ||||
| 		cputs("You may now turn off your Apple."); | ||||
| 		gotoxy(1, 12); | ||||
| 		cputs("You may also reset your Apple for"); | ||||
| 		gotoxy(1, 13); | ||||
| 		cputs("the setting change to take effect."); | ||||
| 	} else { // Show end message for volatile save | ||||
| 		gotoxy(1, 10); | ||||
| 		cputs("Please reset your Apple for"); | ||||
| 		gotoxy(1, 11); | ||||
| 		cputs("the setting change to take effect."); | ||||
| 	} | ||||
| 	// Don't quit. Instead leave prompt asking user to reset. | ||||
| 	while(1) { cgetc(); } | ||||
| } | ||||
							
								
								
									
										6
									
								
								ram2gs.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								ram2gs.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| #ifndef RAM2GS_H | ||||
| #define RAM2GS_H | ||||
|  | ||||
| int ram2gs_main(void); | ||||
|  | ||||
| #endif /* RAM2GS_H */ | ||||
							
								
								
									
										8
									
								
								ram2gs_asm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								ram2gs_asm.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| #ifndef RAM2GS_ASM_H | ||||
| #define RAM2GS_ASM_H | ||||
|  | ||||
| uint8_t __fastcall__ ram2gs_getsize(void); | ||||
| uint8_t __fastcall__ ram2gs_detect(void); | ||||
| uint8_t __fastcall__ ram2gs_cmd(char cmd); | ||||
|  | ||||
| #endif /* RAM2GS_ASM_H */ | ||||
							
								
								
									
										306
									
								
								ram2gs_asm.s
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										306
									
								
								ram2gs_asm.s
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,306 @@ | ||||
| .setcpu		"65816" | ||||
| .autoimport on | ||||
| .importzp	sp | ||||
|  | ||||
| .export 	_ram2gs_getsize | ||||
| .export 	_ram2gs_detect | ||||
| .export 	_ram2gs_cmd | ||||
|  | ||||
| .macro A8 | ||||
|        sep #$20 ; put the 65C816 in 8-bit accumulator mode | ||||
|       .A8 | ||||
| .endmacro | ||||
|  | ||||
| .macro I8 | ||||
|        sep #$10 ; put the 65C816 in 8-bit index register mode | ||||
|       .I8 | ||||
| .endmacro | ||||
|  | ||||
| .macro AI8 | ||||
|        sep #$30 ; put the 65C816 in 8-bit accumulator and index register mode | ||||
|       .A8 | ||||
|       .I8 | ||||
| .endmacro | ||||
|  | ||||
| .macro A16 | ||||
|        rep #$20 ; put the 65C816 in 8-bit accumulator mode | ||||
|       .A16 | ||||
| .endmacro | ||||
|  | ||||
| .macro I16 | ||||
|        rep #$10 ; put the 65C816 in 8-bit index register mode | ||||
|       .I16 | ||||
| .endmacro | ||||
|  | ||||
| .macro AI16 | ||||
|        rep #$30 ; put the 65C816 in 8-bit accumulator and index register mode | ||||
|       .A16 | ||||
|       .I16 | ||||
| .endmacro | ||||
|  | ||||
| .segment	"CODE" | ||||
|  | ||||
| .proc _gsram_getsize: near | ||||
| .A8 | ||||
| .I8 | ||||
| 	; Preamble | ||||
| 	sei				; Disable interrupts | ||||
| 	clc				; Clear carry | ||||
| 	xce				; Clear emulation bit | ||||
| 	php				; Push status | ||||
| 	phb				; Push bank | ||||
| 	AI8 | ||||
|  | ||||
| 	; Store bank number at address 0xFFFF in each bank | ||||
| 	ldy #$7F		; Start at bank 0x7F | ||||
| 	BankSetLoop: | ||||
| 	phy				; Push future bank | ||||
| 	plb 			; Pull bank | ||||
| 	lda $8000		; Get address 0xFFFF in this bank | ||||
| 	pha				; Save old address 0xFFFF contents | ||||
| 	tya				; A = Y | ||||
| 	eor #$FF		; Flip all bits | ||||
| 	tay				; Y = A | ||||
| 	sty $8000		; Overwrite address 0xFFFF with bank number | ||||
| 	eor #$FF		; Flip all bits back | ||||
| 	tay				; Y = A | ||||
| 	dey				; Decrement bank number | ||||
| 	cpy #$FF		; Have we wrapped around? | ||||
| 	bne BankSetLoop ; If not, repeat | ||||
|  | ||||
| 	; Count banks with matching bank number | ||||
| 	ldy #$00		; Y is bank | ||||
| 	ldx #$00		; X is count | ||||
| 	CountLoop: | ||||
| 	phy				; Push future bank | ||||
| 	plb				; Pull bank | ||||
| 	tya				; A = Y | ||||
| 	eor #$FF		; Flip all bits | ||||
| 	tay				; Y = A | ||||
| 	cpy $8000		; Is bank num stored at address 0xFFFF? | ||||
| 	bne AfterInc	; If not, skip increment | ||||
| 	inx				; If so, increment bank count | ||||
| 	AfterInc: | ||||
| 	eor #$FF		; Flip all bits back | ||||
| 	tay				; Y = A | ||||
| 	pla				; Get contents to restore | ||||
| 	sta $8000		; Restore address 0xFFFF in this bank | ||||
| 	iny				; Move to next bank | ||||
| 	cpy #$80		; Are we at bank 0x80 yet? | ||||
| 	bne CountLoop	; If not, repeat | ||||
|  | ||||
| 	; Postamble | ||||
| 	plb				; Restore bank | ||||
| 	plp				; Restore status | ||||
| 	xce				; Restore emulation bit | ||||
| 	cli				; Enable interrupts | ||||
| 	txa				; Transfer bank count to A | ||||
| 	rts | ||||
| .endproc | ||||
|  | ||||
| .proc _ram2gs_getsize: near | ||||
| .A8 | ||||
| .I8 | ||||
| 	; Preamble | ||||
| 	sei				; Disable interrupts | ||||
| 	clc				; Clear carry | ||||
| 	xce				; Clear emulation bit | ||||
| 	php				; Push status | ||||
| 	phb				; Push bank | ||||
| 	AI8 | ||||
|  | ||||
| 	; Go to bank 3F | ||||
| 	ldy #$3F | ||||
| 	phy | ||||
| 	plb | ||||
| 	; Save 3F/3456 | ||||
| 	ldx $3456 | ||||
|  | ||||
| 	; Go to bank 7F | ||||
| 	ldy #$7F | ||||
| 	phy | ||||
| 	plb | ||||
| 	; Invert 7F/3456 | ||||
| 	lda $3456 | ||||
| 	eor #$FF | ||||
| 	sta $3456 | ||||
|  | ||||
| 	; Go to bank 3F | ||||
| 	ldy #$3F | ||||
| 	phy | ||||
| 	plb | ||||
| 	; Has 3F/3456 changed? | ||||
| 	cpx $3456 | ||||
| 	php | ||||
|  | ||||
| 	; Go to bank 7F | ||||
| 	ldy #$7F | ||||
| 	phy | ||||
| 	plb | ||||
| 	; Restore 7F/3456 | ||||
| 	eor #$FF | ||||
| 	sta $3456 | ||||
|  | ||||
| 	; Check result | ||||
| 	ldx #$80 | ||||
| 	plp | ||||
| 	beq _ram2gs_getsize_return | ||||
| 	ldx #$40 | ||||
|  | ||||
| 	; Postamble | ||||
| 	_ram2gs_getsize_return: | ||||
| 	plb				; Restore bank | ||||
| 	plp				; Restore status | ||||
| 	xce				; Restore emulation bit | ||||
| 	cli				; Enable interrupts | ||||
| 	txa				; Transfer bank count to A | ||||
| 	rts | ||||
| .endproc | ||||
|  | ||||
|  | ||||
| .proc _unswap: near | ||||
| .A8 | ||||
| .I8 | ||||
| 	; Save current bank and accumulator | ||||
| 	phb | ||||
| 	pha | ||||
| 	; Switch to bank 0xFB | ||||
| 	lda #$FB | ||||
| 	pha | ||||
| 	plb | ||||
| 	; Submit C1AD | ||||
| 	lda #$C1 | ||||
| 	sta $FFFE | ||||
| 	lda #$AD | ||||
| 	sta $FFFF | ||||
| 	; Pull and submit command  | ||||
| 	lda #$00 | ||||
| 	sta $FFFD | ||||
| 	; Restore accumulator and bank and return | ||||
| 	pla | ||||
| 	plb | ||||
| 	rts | ||||
| .endproc | ||||
|  | ||||
| .proc _swap: near | ||||
| .A8 | ||||
| .I8 | ||||
| 	; Save current bank and accumulator | ||||
| 	phb | ||||
| 	pha | ||||
| 	; Switch to bank 0xFB | ||||
| 	lda #$FB | ||||
| 	pha | ||||
| 	plb | ||||
| 	; Submit C1AD | ||||
| 	lda #$C1 | ||||
| 	sta $FFFE | ||||
| 	lda #$AD | ||||
| 	sta $FFFF | ||||
| 	; Pull and submit command  | ||||
| 	lda #$01 | ||||
| 	sta $FFFD | ||||
| 	; Restore accumulator and bank and return | ||||
| 	pla | ||||
| 	plb | ||||
| 	rts | ||||
| .endproc | ||||
|  | ||||
| .proc _ram2gs_detect: near | ||||
| .A8 | ||||
| .I8 | ||||
| 	; Preamble | ||||
| 	sei				; Disable interrupts | ||||
| 	clc				; Clear carry | ||||
| 	xce				; Clear emulation bit | ||||
| 	php				; Push status | ||||
| 	phb				; Push bank | ||||
| 	AI8 | ||||
|  | ||||
| 	; Switch to bank 0x3F | ||||
| 	lda #$3F | ||||
| 	pha | ||||
| 	plb | ||||
|  | ||||
| 	; Unswap | ||||
| 	jsr _unswap | ||||
| 	; Save unswapped 3F/8000 | ||||
| 	lda $8000 | ||||
| 	pha | ||||
| 	; Swap | ||||
| 	jsr _swap | ||||
| 	; Save swapped 3F/8000 | ||||
| 	lda $8000 | ||||
| 	pha | ||||
|  | ||||
| 	; Store 0xFF in swapped | ||||
| 	lda #$FF | ||||
| 	sta $8000 | ||||
| 	; Verify 0xFF stored | ||||
| 	lda $8000 | ||||
| 	cmp #$FF | ||||
| 	bne _ram2gs_detect_fail | ||||
|  | ||||
| 	; Unswap | ||||
| 	jsr _unswap | ||||
| 	; Store 0x00 in unswapped | ||||
| 	lda #$00 | ||||
| 	sta $8000 | ||||
| 	; Verify 0x00 stored | ||||
| 	lda $8000 | ||||
| 	cmp #$00 | ||||
| 	bne _ram2gs_detect_fail | ||||
|  | ||||
| 	; Swap | ||||
| 	jsr _swap | ||||
| 	; Verify 0xFF stored | ||||
| 	lda $8000 | ||||
| 	cmp #$FF | ||||
| 	bne _ram2gs_detect_fail | ||||
|  | ||||
| 	; Get success return value and jump to postamble | ||||
| 	ldx #$01		; Get success falue | ||||
| 	bne _ram2gs_detect_return ; Jump to postamble | ||||
|  | ||||
| 	; Fail | ||||
| 	_ram2gs_detect_fail: | ||||
| 	ldx #$00		; Get fail value | ||||
|  | ||||
| 	; Postamble | ||||
| 	_ram2gs_detect_return: | ||||
| 	jsr _swap		; Swap | ||||
| 	pla				; Get value to restore to swapped bank 3F | ||||
| 	sta $8000		; Restore | ||||
| 	jsr _unswap		; Unswap | ||||
| 	pla				; Get value to restore to unswapped bank 3F | ||||
| 	sta $8000		; Restore | ||||
| 	txa				; Put return value in accumulator | ||||
| 	plb				; Restore bank | ||||
| 	plp				; Restore status | ||||
| 	xce				; Restore emulation bit | ||||
| 	cli				; Enable interrupts | ||||
| 	rts | ||||
| .endproc | ||||
|  | ||||
| .proc _ram2gs_cmd: near | ||||
| .A8 | ||||
| .I8 | ||||
| 	; Save current bank and command in accumulator | ||||
| 	phb | ||||
| 	pha | ||||
| 	; Switch to bank 0xFB | ||||
| 	lda #$FB | ||||
| 	pha | ||||
| 	plb | ||||
| 	; Submit C1AD | ||||
| 	lda #$C1 | ||||
| 	sta $FFFE | ||||
| 	lda #$AD | ||||
| 	sta $FFFF | ||||
| 	; Pull and submit command  | ||||
| 	pla | ||||
| 	sta $FFFD | ||||
| 	; Restore bank and return | ||||
| 	plb | ||||
| 	rts | ||||
| .endproc | ||||
							
								
								
									
										52
									
								
								util.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								util.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | ||||
| #include "util.h" | ||||
|  | ||||
| #include <stdint.h> | ||||
| #include <stdio.h> | ||||
| #include <conio.h> | ||||
|  | ||||
| #define PB0 ((char*)0xC061) | ||||
| #define PB1 ((char*)0xC062) | ||||
| char read_applekey(void) { return ((*PB0) | (*PB1)) & 0x80; } | ||||
|  | ||||
| #define VBL ((signed char*)0xC019) | ||||
| #define SPIN_HALFCYCLES 3 | ||||
| #define SPIN_FRAMESPERCHAR 4 | ||||
| void spin(uint8_t x, uint8_t y) {  | ||||
| 	char i; | ||||
|  | ||||
| 	// Sync to frame before starting | ||||
| 	while (*VBL >= 0); | ||||
|  | ||||
| 	// Wait and animate spinner. | ||||
| 	// Spin_half | ||||
| 	for (i = 0; i < SPIN_HALFCYCLES; i++) { | ||||
| 		char j; | ||||
| 		for (j = 0; j < 4; j++) { | ||||
| 			char spinchar; | ||||
| 			char k; | ||||
|  | ||||
| 			// Assign spinner char based on j | ||||
| 			switch (j) { | ||||
| 				case 0: spinchar = '\\'; break; | ||||
| 				case 1: spinchar = '|'; break; | ||||
| 				case 2: spinchar = '/'; break; | ||||
| 				case 3: spinchar = '-'; break; | ||||
| 				default: spinchar = '-'; break; | ||||
| 			} | ||||
|  | ||||
| 			// Write it to screen | ||||
| 			gotoxy(x, y); | ||||
| 			putchar(spinchar); | ||||
|  | ||||
| 			// Wait specificed number of frames | ||||
| 			for (k = 0; k < SPIN_FRAMESPERCHAR; k++) { | ||||
| 				while (*VBL < 0); | ||||
| 				while (*VBL >= 0); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Wait a frame when finished | ||||
| 	while (*VBL < 0); | ||||
| 	while (*VBL >= 0); | ||||
| } | ||||
		Reference in New Issue
	
	Block a user