diff --git a/Makefile b/Makefile index b888577..e3bf6d1 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,5 @@ +cflags = -O --cpu 6502 -t apple2 + all: GWRAM.po GWRAM.dbg.po obj: @@ -7,37 +9,40 @@ bin: @mkdir bin obj/main.o: obj main.c - cc65 main.c -O --cpu 6502 -t apple2enh -o obj/main.s + cc65 main.c $(cflags) -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 + cc65 ram2e.c $(cflags) -o obj/ram2e.s ca65 obj/ram2e.s -o obj/ram2e.o 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 $(cflags) -o obj/ram2e.dbg.s -DSKIP_RAM2E_DETECT ca65 obj/ram2e.dbg.s -o obj/ram2e.dbg.o obj/ram2gs_asm.o: obj ram2gs_asm.s ca65 ram2gs_asm.s -o obj/ram2gs_asm.o obj/ram2gs.o: obj ram2gs.c - cc65 ram2gs.c -O --cpu 6502 -t apple2enh -o obj/ram2gs.s + cc65 ram2gs.c $(cflags) -o obj/ram2gs.s ca65 obj/ram2gs.s -o obj/ram2gs.o obj/ram2gs.dbg.o: obj ram2gs.c - cc65 ram2gs.c -O --cpu 6502 -t apple2enh -o obj/ram2gs.dbg.s -DSKIP_RAM2GS_DETECT + cc65 ram2gs.c $(cflags) -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 + cc65 util.c $(cflags) -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 +obj/gwconio.o: obj gwconio.s + ca65 gwconio.s -o obj/gwconio.o -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 +bin/main.sys: bin obj/main.o obj/ram2e.o obj/ram2gs.o obj/ram2gs_asm.o obj/util.o obj/gwconio.o + ld65 -o bin/main.sys obj/main.o obj/ram2gs.o obj/ram2e.o obj/ram2gs_asm.o obj/util.o obj/gwconio.o -C apple2-system.cfg --lib apple2.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 obj/gwconio.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 obj/gwconio.o -C apple2-system.cfg --lib apple2.lib -D __EXEHDR__=0 GWRAM.po: bin/main.sys cp prodos140.po bin/GWRAM.po diff --git a/bin/GWRAM.dbg.po b/bin/GWRAM.dbg.po index 8b3441f..45f04a6 100644 Binary files a/bin/GWRAM.dbg.po and b/bin/GWRAM.dbg.po differ diff --git a/bin/GWRAM.po b/bin/GWRAM.po index 240f417..1b2dedc 100644 Binary files a/bin/GWRAM.po and b/bin/GWRAM.po differ diff --git a/gwconio.h b/gwconio.h new file mode 100644 index 0000000..36739f0 --- /dev/null +++ b/gwconio.h @@ -0,0 +1,9 @@ +#ifndef GWCONIO_H +#define GWCONIO_H + +void gwcputsxy (unsigned char x, unsigned char y, const char* s); +void gwcputs (const char* s); +void __fastcall__ gwcputcxy (unsigned char x, unsigned char y, char c); +void __fastcall__ gwcputc (char c); + +#endif /* GWCONIO_H */ diff --git a/gwconio.s b/gwconio.s new file mode 100644 index 0000000..df337a1 --- /dev/null +++ b/gwconio.s @@ -0,0 +1,122 @@ +; +; Ullrich von Bassewitz, 06.08.1998 +; Modified Sep. 6, 2020 by Zane Kaminski, Engineer @ Garrett's Workshop +; +; + .ifdef __APPLE2ENH__ + .constructor initconio + .endif + .export _gwcputcxy, _gwcputc + .export _gwcputsxy, _gwcputs + .import _gwconiomask + .import gotoxy, VTABZ + .importzp ptr1, tmp1 + + .include "apple2.inc" + + .segment "ONCE" + + .ifdef __APPLE2ENH__ +initconio: + sta SETALTCHAR ; Switch in alternate charset + bit LORES ; Limit SET80COL-HISCR to text + rts + .endif + + .code + + +; void gwcputsxy (unsigned char x, unsigned char y, const char* s); +_gwcputsxy: + sta ptr1 ; Save s for later + stx ptr1+1 + jsr gotoxy ; Set cursor, pop x and y + jmp L0 ; Same as cputs... +; void gwcputs (const char* s); +_gwcputs: sta ptr1 ; Save s + stx ptr1+1 +L0: ldy #0 +L1: lda (ptr1),y + beq L9 ; Jump if done + iny + sty tmp1 ; Save offset + jsr _gwcputc ; Output char, advance cursor + ldy tmp1 ; Get offset + bne L1 ; Next char + inc ptr1+1 ; Bump high byte + bne L1 +; Done +L9: rts + + +; void __fastcall__ gwcputcxy (unsigned char x, unsigned char y, char c); +_gwcputcxy: + pha ; Save C + jsr gotoxy ; Call this one, will pop params + pla ; Restore C and run into _gwcputc +; void __fastcall__ gwcputc (char c); +_gwcputc: + cmp #$0D ; Test for \r = carrage return + beq left + cmp #$0A ; Test for \n = line feed + beq newline + eor #$80 ; Invert high bit + ; .ifndef __APPLE2ENH__ + cmp #$E0 ; Test for lowercase + bcc cputdirect +; and #$DF ; Convert to uppercase + and _gwconiomask ; Convert to uppercase using mask +; .endif + +cputdirect: + jsr putchar + inc CH ; Bump to next column + lda CH + cmp WNDWDTH + bcc :+ + jsr newline +left: lda #$00 ; Goto left edge of screen + sta CH +: rts + +newline: + inc CV ; Bump to next line + lda CV + cmp WNDBTM + bcc :+ + lda WNDTOP ; Goto top of screen + sta CV +: jmp VTABZ + +putchar: + .ifdef __APPLE2ENH__ + ldy INVFLG + cpy #$FF ; Normal character display mode? + beq putchardirect + cmp #$E0 ; Lowercase? + bcc mask + and #$7F ; Inverse lowercase + bra putchardirect + .endif +mask: and INVFLG ; Apply normal, inverse, flash + +putchardirect: + pha + ldy CH + .ifdef __APPLE2ENH__ + bit RD80VID ; In 80 column mode? + bpl put ; No, just go ahead + tya + lsr ; Div by 2 + tay + bcs put ; Odd cols go in main memory + bit HISCR ; Assume SET80COL + .endif +put: lda (BASL),Y ; Get current character + tax ; Return old character for _cgetc + pla + sta (BASL),Y + .ifdef __APPLE2ENH__ + bit LOWSCR ; Doesn't hurt in 40 column mode + .endif + rts \ No newline at end of file diff --git a/main.c b/main.c index 2f2bd9b..03c3d52 100644 --- a/main.c +++ b/main.c @@ -4,9 +4,14 @@ #include "ram2e.h" #include "ram2gs.h" +#include "gwconio.h" + +char gwconiomask; int main(void) { + gwconiomask = 0xFF; + // First clear screen clrscr(); @@ -19,16 +24,15 @@ int main(void) __asm__("sta $C073"); return EXIT_SUCCESS; case APPLE_IIGS: - ram2gs_main(); + ram2gs_main(); return EXIT_SUCCESS; default: + gwconiomask = 0xDF; // 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."); + gwcputsxy(0, 8, " THIS PROGRAM REQUIRES APPLE IIE OR IIGS"); + gwcputsxy(0, 10, " PRESS ANY KEY TO QUIT."); cgetc(); // Wait for key clrscr(); // Clear screen before quitting return EXIT_SUCCESS; - } + } } diff --git a/ram2e.c b/ram2e.c index c76196e..97b5c7a 100644 --- a/ram2e.c +++ b/ram2e.c @@ -6,6 +6,7 @@ #include #include "util.h" +#include "gwconio.h" static char _rwsave[256]; static char _rwsave0_1; @@ -262,36 +263,28 @@ static void set_nvm(char mask) { static void menu(uint16_t bankcount) { - gotoxy(5, 1); - cputs("-- RAM2E Capacity Settings --"); + gwcputsxy(5, 1, "-- RAM2E Capacity Settings --"); + if (bankcount < 2) { gotoxy(5, 3); } else { gotoxy(4, 3); } - printf("Current RAM2E capacity: %d kB", bankcount * 64); + gwcputs("Current RAM2E capacity: "); + printf("%d", bankcount * 64); + gwcputs(" kB"); - gotoxy(1, 5); - cputs("Select desired memory capacity:"); + gwcputsxy(1, 5, "Select desired memory capacity:"); - gotoxy(4, 7); - cputs("1. 64 kilobytes"); - gotoxy(4, 9); - cputs("2. 512 kilobytes"); - gotoxy(4, 11); - cputs("3. 1 megabyte"); - gotoxy(4, 13); - cputs("4. 4 megabytes"); - gotoxy(4, 15); - cputs("5. 8 megabytes"); + gwcputsxy(4, 7, "1. 64 kilobytes"); + gwcputsxy(4, 9, "2. 512 kilobytes"); + gwcputsxy(4, 11, "3. 1 megabyte"); + gwcputsxy(4, 13, "4. 4 megabytes"); + gwcputsxy(4, 15, "5. 8 megabytes"); - gotoxy(1, 18); - cputs("Capacity will be saved until power-off."); + gwcputsxy(1, 18, "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."); + gwcputsxy(1, 20, "To remember capacity setting in"); + gwcputsxy(1, 21, "nonvolatile memory, press Apple+number."); - gotoxy(1, 23); - cputs("Press [Q] to quit without saving."); + gwcputsxy(1, 23, "Press [Q] to quit without saving."); } int ram2e_main(void) @@ -306,10 +299,8 @@ int ram2e_main(void) if(!auxram_detect() || !ram2e_detect()) { ramworks_restore(); // If no RAM2E, show an error message and quit - gotoxy(0, 8); - cputs(" No RAM2E II detected."); - gotoxy(0, 10); - cputs(" Press any key to quit."); + gwcputsxy(0, 8, " No RAM2E II detected."); + gwcputsxy(0, 10, " Press any key to quit."); cgetc(); // Wait for key clrscr(); // Clear screen before quitting return EXIT_SUCCESS; @@ -338,13 +329,11 @@ int ram2e_main(void) case '5': mask = 0x7F; break; case 'R': { reset_count++; - if (reset_count >= 100) { - // Show message about saving. + if (reset_count >= 25) { + // Show message about resetting. clrscr(); // Clear screen - gotoxy(1, 8); - cputs("Resetting RAM2E settings."); - gotoxy(1, 9); - cputs("Do not turn off your Apple."); + gwcputsxy(1, 8, "Resetting RAM2E settings."); + gwcputsxy(1, 9, "Do not turn off your Apple."); ufm_erase(); // Erase RAM2E settings memory set_mask_temp(0x7F); // Set mask to default (0x7F) @@ -354,11 +343,11 @@ int ram2e_main(void) // Show success message and quit clrscr(); // Clear screen - gotoxy(1, 8); - cputs("RAM2E settings reset successfully."); + gwcputsxy(1, 8, "RAM2E settings reset successfully."); goto end; } - } default: continue; + continue; + } default: reset_count = 0; continue; } // Check if pressed with apple key. If so, save to nonvolatile memory. @@ -374,36 +363,27 @@ int ram2e_main(void) if (nvm) { // Save in NVM if requested. // Show message about saving. - gotoxy(1, 8); - cputs("Saving RAM2E capacity setting."); - gotoxy(1, 9); - cputs("Do not turn off your Apple."); + gwcputsxy(1, 8, "Saving RAM2E capacity setting."); + gwcputsxy(1, 9, "Do not turn off your Apple."); // Save capacity in nonvolatile memory. set_nvm(mask); // Wait for >= 500ms on even the fastest systems. spin(32, 8); // Print success message clrscr(); // Clear screen - gotoxy(1, 8); - cputs("RAM2E capacity saved successfully."); + gwcputsxy(1, 8, "RAM2E capacity saved successfully."); } else { // Print success message if not saving in NVM. - gotoxy(1, 8); - cputs("RAM2E capacity set successfully."); + gwcputsxy(1, 8, "RAM2E 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."); + gwcputsxy(1, 10, "You may now turn off your Apple."); + gwcputsxy(1, 12, "You may also reset your Apple for"); + gwcputsxy(1, 13, "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."); + gwcputsxy(1, 10, "Please reset your Apple for"); + gwcputsxy(1, 11, "the setting change to take effect."); } // Don't quit. Instead leave prompt asking user to reset. while(1) { cgetc(); } diff --git a/ram2gs.c b/ram2gs.c index d430f6f..ca1d0a0 100644 --- a/ram2gs.c +++ b/ram2gs.c @@ -6,6 +6,7 @@ #include #include "util.h" +#include "gwconio.h" #include "ram2gs_asm.h" static void ram2gs_erase() { ram2gs_cmd(0x28); } @@ -40,29 +41,24 @@ static void ram2gs_setnvm(char en8meg) { static void menu(void) { uint8_t bankcount = ram2gs_getsize(); - gotoxy(5, 1); - cputs("-- RAM2GS Capacity Settings --"); + gwcputsxy(5, 1, "-- RAM2GS Capacity Settings --"); + gotoxy(4, 3); - printf("Current RAM2GS capacity: %d kB", bankcount * 64); + gwcputs("Current RAM2GS capacity: "); + printf("%d", bankcount * 64); + gwcputs(" kB"); - gotoxy(1, 6); - cputs("Select desired memory capacity:"); + gwcputsxy(1, 6, "Select desired memory capacity:"); - gotoxy(4, 8); - cputs("1. 4 megabytes"); - gotoxy(4, 10); - cputs("2. 8 megabytes"); + gwcputsxy(4, 8, "1. 4 megabytes"); + gwcputsxy(4, 10, "2. 8 megabytes"); - gotoxy(1, 18); - cputs("Capacity will be saved until power-off."); + gwcputsxy(1, 18, "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."); + gwcputsxy(1, 20, "To remember capacity setting in"); + gwcputsxy(1, 21, "nonvolatile memory, press Apple+number."); - gotoxy(1, 23); - cputs("Press [Q] to quit without saving."); + gwcputsxy(1, 23, "Press [Q] to quit without saving."); } int ram2gs_main(void) @@ -75,10 +71,8 @@ int ram2gs_main(void) #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."); + gwcputsxy(0, 8, " No RAM2GS II detected."); + gwcputsxy(0, 10, " Press any key to quit."); cgetc(); // Wait for key clrscr(); // Clear screen before quitting return EXIT_SUCCESS; @@ -102,13 +96,11 @@ int ram2gs_main(void) case '2': en8meg = 1; ram2gs_set8mb(); break; case 'R': { reset_count++; - if (reset_count >= 100) { - // Show message about saving. + if (reset_count >= 25) { + // Show message about resetting. clrscr(); // Clear screen - gotoxy(1, 8); - cputs("Resetting RAM2GS settings."); - gotoxy(1, 9); - cputs("Do not turn off your Apple."); + gwcputsxy(1, 8, "Resetting RAM2GS settings."); + gwcputsxy(1, 9, "Do not turn off your Apple."); ram2gs_erase(); // Erase RAM2GS settings memory ram2gs_set8mb(); // Enable 8 megabytes now @@ -118,11 +110,11 @@ int ram2gs_main(void) // Show success message and quit clrscr(); // Clear screen - gotoxy(1, 8); - cputs("RAM2GS settings reset successfully."); + gwcputsxy(1, 8, "RAM2GS settings reset successfully."); goto end; } - } default: continue; + continue; + } default: reset_count = 0; continue; } // Check if pressed with apple key. If so, save to nonvolatile memory. @@ -135,36 +127,27 @@ int ram2gs_main(void) 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."); + gwcputsxy(1, 8, "Saving RAM2GS capacity setting."); + gwcputsxy(1, 9, "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."); + gwcputsxy(1, 8, "RAM2GS capacity saved successfully."); } else { // Print success message if not saving in NVM. - gotoxy(1, 8); - cputs("RAM2GS capacity set successfully."); + gwcputsxy(1, 8, "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."); + gwcputsxy(1, 10, "You may now turn off your Apple."); + gwcputsxy(1, 12, "You may also reset your Apple for"); + gwcputsxy(1, 13, "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."); + gwcputsxy(1, 10, "Please reset your Apple for"); + gwcputsxy(1, 11, "the setting change to take effect."); } // Don't quit. Instead leave prompt asking user to reset. while(1) { cgetc(); } diff --git a/ramtest.c b/ramtest.c new file mode 100644 index 0000000..e4ec7a2 --- /dev/null +++ b/ramtest.c @@ -0,0 +1,71 @@ +#include +#include +#include +#include +#include +#include + +#include "util.h" +#include "gwconio.h" +#include "ramtestpat.c" + +#define TEST_SIZE 8*1024*1024 + +char test_run() { + // Put copy stub in low RAM + for (uint32_t a = 0; a < TEST_SIZE) { + wr(a, getpat(a)); + } + + for (uint32_t a = 0; a < TEST_SIZE) { + char d = rd(a); + if (d != getpat(a)) { return -1; } + } + + return 0; +} + +static inline char getpat(uint32_t a) { + return ramtestpat[a % RAMTESTPAT_SIZE]; +} + +static char rd(uint32_t a) { + uint16_t al = a & 0xFFFF; + if (al < 0x0200) { return rd_zplc(a); } + else if (al < 0xC000) { return rd_mid(a); } + else if (al < 0xD000) { return rd_lc2(a); } + else { return rd_zplc(a); } +} + +static char rd_zplc(uint32_t a) { + +} + +static char rd_mid(uint32_t a) { + +} + +static char rd_lc2(uint32_t a) { + +} + +static char wr(uint32_t a, char d) { + uint16_t al = a & 0xFFFF; + if (al < 0x0200) { wr_zplc(a, d); } + else if (al < 0xC000) { wr_mid(a, d); } + else if (al < 0xD000) { wr_lc2(a, d); } + else { wr_zplc(a, d); } +} + +static char rd_zplc(uint32_t a) { + +} + +static char rd_mid(uint32_t a) { + +} + +static char rd_lc2(uint32_t a) { + +} + diff --git a/ramtest.h b/ramtest.h new file mode 100644 index 0000000..c9e8909 --- /dev/null +++ b/ramtest.h @@ -0,0 +1,6 @@ +#ifndef TEST_H +#define TEST_H + +char test_run(); + +#endif /* TEST_H */ diff --git a/ramtestpat.c b/ramtestpat.c new file mode 100644 index 0000000..fd3edc9 --- /dev/null +++ b/ramtestpat.c @@ -0,0 +1,4 @@ +#define RAMTESTPAT_SIZE 4097 +char ramtestpat[RAMTESTPAT_SIZE] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9 +}; \ No newline at end of file diff --git a/util.c b/util.c index a597700..4584d13 100644 --- a/util.c +++ b/util.c @@ -49,4 +49,4 @@ void spin(uint8_t x, uint8_t y) { // Wait a frame when finished while (*VBL < 0); while (*VBL >= 0); -} \ No newline at end of file +}