Added RAM2GS functionality
This commit is contained in:
parent
1e1ecf9592
commit
08f6a7017b
38
Makefile
38
Makefile
|
@ -1,14 +1,14 @@
|
||||||
all: RAM2Eutil.po RAM2Eutil.dbg.po
|
all: RAM2Eutil.po RAM2Eutil.dbg.po
|
||||||
|
|
||||||
.PHONY: clean
|
|
||||||
|
|
||||||
obj:
|
obj:
|
||||||
@mkdir obj
|
@mkdir obj
|
||||||
|
|
||||||
bin:
|
bin:
|
||||||
@mkdir 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
|
obj/ram2e.o: obj ram2e.c
|
||||||
cc65 ram2e.c -O --cpu 6502 -t apple2enh -o obj/ram2e.s
|
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
|
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
|
ca65 obj/ram2e.dbg.s -o obj/ram2e.dbg.o
|
||||||
|
|
||||||
bin/ram2e.sys: bin obj/ram2e.o
|
obj/ram2gs_asm.o: obj ram2gs_asm.s
|
||||||
ld65 -o bin/ram2e.sys obj/ram2e.o -C apple2enh-system.cfg --lib apple2enh.lib -D __EXEHDR__=0
|
ca65 ram2gs_asm.s -o obj/ram2gs_asm.o
|
||||||
|
|
||||||
bin/ram2e.dbg.sys: bin obj/ram2e.dbg.o
|
obj/ram2gs.o: obj ram2gs.c
|
||||||
ld65 -o bin/ram2e.dbg.sys obj/ram2e.dbg.o -C apple2enh-system.cfg --lib apple2enh.lib -D __EXEHDR__=0
|
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
|
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
|
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:
|
clean:
|
||||||
rm -fr bin obj
|
rm -fr bin obj
|
||||||
|
|
Binary file not shown.
BIN
bin/RAM2Eutil.po
BIN
bin/RAM2Eutil.po
Binary file not shown.
|
@ -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 <ctype.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#define true 1
|
#include "util.h"
|
||||||
#define false 0
|
|
||||||
|
|
||||||
|
static char _cmd;
|
||||||
#define VBL ((signed char*)0xC019)
|
static char _arg;
|
||||||
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;
|
|
||||||
/* ram2e_cmd(...) issues a coded command+argument sequence to the RAM2E */
|
/* ram2e_cmd(...) issues a coded command+argument sequence to the RAM2E */
|
||||||
static void ram2e_cmd(char cmd, char arg) {
|
static void ram2e_cmd(char cmd, char arg) {
|
||||||
// Load operation and data bytes into X and Y registers
|
// 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 */
|
/* ram2e_detect() returns true if a RAM2E II has been detected */
|
||||||
uint8_t _detect;
|
static uint8_t _detect;
|
||||||
static char ram2e_detect() {
|
static char ram2e_detect() {
|
||||||
#ifdef SKIP_RAM2E_DETECT
|
#ifdef SKIP_RAM2E_DETECT
|
||||||
return true;
|
return true;
|
||||||
|
@ -148,8 +138,8 @@ static char ram2e_detect() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ramworks_getsize() returns the number of banks of RAM2E aux memory */
|
/* ramworks_getsize() returns the number of banks of RAM2E aux memory */
|
||||||
uint8_t _rwsize;
|
static uint8_t _rwsize;
|
||||||
uint8_t _rwnot16mb;
|
static uint8_t _rwnot16mb;
|
||||||
static uint16_t ramworks_getsize() {
|
static uint16_t ramworks_getsize() {
|
||||||
_rwnot16mb = 1; // Set "not 16 mb" flag
|
_rwnot16mb = 1; // Set "not 16 mb" flag
|
||||||
|
|
||||||
|
@ -169,11 +159,11 @@ static uint16_t ramworks_getsize() {
|
||||||
CountLoop:
|
CountLoop:
|
||||||
__asm__("sty $C073"); // Set bank
|
__asm__("sty $C073"); // Set bank
|
||||||
__asm__("cpy $00"); // Is bank num stored at address 0?
|
__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__("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
|
__asm__("stx %v", _rwnot16mb); // Othwerwise rolled over so clear rwnot16mb
|
||||||
NotMem:
|
AfterInc:
|
||||||
__asm__("iny"); // Move to next bank
|
__asm__("iny"); // Move to next bank
|
||||||
__asm__("bne %g", CountLoop); // Repeat if not on bank 0
|
__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.");
|
cputs("Press [Q] to quit without saving.");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void spin(uint8_t x, uint8_t y) {
|
int ram2e_main(void)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
char mask;
|
char mask;
|
||||||
char nvm;
|
char nvm;
|
||||||
int reset_count;
|
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
|
// Check for RAM2E
|
||||||
if(!auxram_detect() || !ram2e_detect()) {
|
if(!auxram_detect() || !ram2e_detect()) {
|
||||||
// If no RAM2E, show an error message and quit
|
// If no RAM2E, show an error message and quit
|
||||||
|
@ -331,7 +266,7 @@ int main(void)
|
||||||
reset_count = 0;
|
reset_count = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
// Set capacity mask or quit according to keypress.
|
// Set capacity mask or quit according to keypress.
|
||||||
switch (toupper(cgetc())) {
|
switch (toupper(cgetc() & 0x7F)) {
|
||||||
case 'Q' : {
|
case 'Q' : {
|
||||||
clrscr();
|
clrscr();
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
|
@ -366,8 +301,7 @@ int main(void)
|
||||||
} default: continue;
|
} default: continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if pressed with apple key.
|
// Check if pressed with apple key. If so, save to nonvolatile memory.
|
||||||
// If so, save to nonvolatile memory.
|
|
||||||
if (read_applekey()) { nvm = true; }
|
if (read_applekey()) { nvm = true; }
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
#ifndef RAM2E_H
|
||||||
|
#define RAM2E_H
|
||||||
|
|
||||||
|
int ram2e_main(void);
|
||||||
|
|
||||||
|
#endif /* RAM2E_H */
|
|
@ -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(); }
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
#ifndef RAM2GS_H
|
||||||
|
#define RAM2GS_H
|
||||||
|
|
||||||
|
int ram2gs_main(void);
|
||||||
|
|
||||||
|
#endif /* RAM2GS_H */
|
|
@ -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 */
|
|
@ -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
|
|
@ -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);
|
||||||
|
}
|
Loading…
Reference in New Issue