From 81338a61c3a8576ff29408c3bc372c8f95d33621 Mon Sep 17 00:00:00 2001 From: Wayne Parham Date: Thu, 3 Mar 2022 17:47:31 -0600 Subject: [PATCH] Added Sym-1 extended memory sample program and documentation --- doc/sym1.sgml | 9 +-- samples/sym1/Makefile | 7 ++- samples/sym1/symExtendedMemory.c | 95 ++++++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+), 5 deletions(-) create mode 100644 samples/sym1/symExtendedMemory.c diff --git a/doc/sym1.sgml b/doc/sym1.sgml index 5961984bd..c2265ba7b 100644 --- a/doc/sym1.sgml +++ b/doc/sym1.sgml @@ -29,7 +29,7 @@ Included with this distribution is a 4k configuration file and a 32k config file Memory layout

-The ROMs and I/O areas are defined in the configuration files, as are most of the entry points for useful subroutines in the Sym-1 monitor ROM. cc65 generated programs compiled and linked using 4k config run in the memory range of $200 - $0FFF. The 32k config expands this range to $7FFF. The starting memory location and entry point for running the program is $200, so when the program is transferred to the Sym-1, it is executed by typing 'g 200'. The system returns control back to the monitor ROM when the program terminates, providing the '.' prompt. +The ROMs and I/O areas are defined in the configuration files, as are most of the entry points for useful subroutines in the Sym-1 monitor ROM. cc65 generated programs compiled and linked using 4k config run in the memory range of $200 - $0FFF. The 32k config expands this range to $7FFF. Memory above 32K can be used to extend the heap, as described below. The starting memory location and entry point for running the program is $200, so when the program is transferred to the Sym-1, it is executed by typing 'g 200'. The system returns control back to the monitor ROM when the program terminates, providing the '.' prompt. Special locations: @@ -41,7 +41,7 @@ Special locations: The C runtime stack is located at $0FFF on 4KB Syms, or at $7FFF for 32KB systems. The stack always grows downwards.

@@ -61,7 +61,7 @@ No graphics drivers are currently available for the Sym-1. Extended memory drivers

-No extended memory drivers are currently available for the Sym-1. +See the example program, symExtendedMemory, in the samples directory. Joystick drivers

@@ -102,7 +102,7 @@ As stated earlier, there are config files for 4KB and 32KB systems. If you have Sample programs

-All the samples will run on the "stock" 4KB Sym-1, except for symIO and symNotepad, which require 32KB. These sample programs can be found in the samples/sym1 directory: +All the samples will run on the "stock" 4KB Sym-1, except for symIO and symNotepad, which require 32KB. Additionally, symExtendedMemory shows how to access memory above 32KB, so it expects more than 32KB. These sample programs can be found in the samples/sym1 directory: symHello prints "Hello World!" and then inputs characters, which are echoed on the screen. It also makes a "beep" sound. @@ -110,6 +110,7 @@ All the samples will run on the "stock" 4KB Sym-1, except for symIO an symDisplay allows entry of a message, which is then displayed by scrolling it across the front panel display. symIO allows access to the Sym-1 digital I/O ports. symNotepad is a simple text entry/retrieval program that uses tape storage. +symExtendedMemory demonstrates how to access upper-memory and add it to the heap. License

diff --git a/samples/sym1/Makefile b/samples/sym1/Makefile index 14da90ad3..281b5bcd0 100644 --- a/samples/sym1/Makefile +++ b/samples/sym1/Makefile @@ -32,7 +32,7 @@ else endif EXELIST_sym1 = \ - symHello.bin symTiny.bin symDisplay.bin symIO.bin symNotepad.bin + symHello.bin symTiny.bin symDisplay.bin symIO.bin symNotepad.bin symExtendedMemory.bin ifneq ($(EXELIST_$(SYS)),) samples: $(EXELIST_$(SYS)) @@ -64,9 +64,14 @@ symIO.bin: symIO.c symNotepad.bin: symNotepad.c $(CL) -t sym1 -C sym1-32k.cfg -O -o symNotepad.bin symNotepad.c +symExtendedMemory.bin: symExtendedMemory.c + $(CL) -t sym1 -C sym1-32k.cfg -O -o symExtendedMemory.bin symExtendedMemory.c + + clean: @$(DEL) symHello.bin 2>$(NULLDEV) @$(DEL) symTiny.bin 2>$(NULLDEV) @$(DEL) symDisplay.bin 2>$(NULLDEV) @$(DEL) symIO.bin 2>$(NULLDEV) @$(DEL) symNotepad.bin 2>$(NULLDEV) + @$(DEL) symExtendedMemory.bin 2>$(NULLDEV) diff --git a/samples/sym1/symExtendedMemory.c b/samples/sym1/symExtendedMemory.c new file mode 100644 index 000000000..81902382f --- /dev/null +++ b/samples/sym1/symExtendedMemory.c @@ -0,0 +1,95 @@ +// -------------------------------------------------------------------------- +// Sym-1 Extended Memory +// +// Wayne Parham +// +// wayne@parhamdata.com +// -------------------------------------------------------------------------- +// +// Note: This program examines memory above the monitor ROM (8000-8FFF) to +// Determine what, if any, memory is available. It then adds whatever +// 4K segments it finds to the heap. +// +// Memory Segment Remark +// 0x9000 Usually available +// 0xA000 System I/O, always unavailable +// 0xB000 Used by RAE, but normally available +// 0xC000 Used by BASIC, normally unavailable +// 0xD000 Used by BASIC, normally unavailable +// 0xE000 Used by RAE, but normally available +// 0xF000 Normally available, but only to FF7F +// +// -------------------------------------------------------------------------- + +#include +#include +#include +#include + +#define SEGMENT 0x9000 // First 4K segment of extended memory +#define SEG_END 0x0FFF // Last location of segment +#define BLOCK_SIZE 0x1000 // Size of segment +#define TOP_END 0x0F7F // Last location of memory +#define TOP_SIZE 0x0F80 // Size of top segment +#define UNAVAILABLE 0xA000 // System I/O area + +int main (void) { + int error = 0; + unsigned heap_size = 0x0000; + char* segment = (char*) SEGMENT; + + printf ( "Analyzing memory.\n\n" ); + + heap_size = _heapmemavail(); + + printf ( "Main memory has %d bytes available.\n", heap_size ); + + while ( (int) segment < 0xEFFF ) { // Iterate through 4K memory blocks + if( (int) segment != UNAVAILABLE ) { + segment[0] = 0x00; // Check beginning of segment + if ( segment[0] != 0x00 ) + error = 1; + segment[0] = 0xFF; + if ( segment[0] != 0xFF ) + error = 1; + segment[SEG_END] = 0x00; // Check end of segment + if ( segment[SEG_END] != 0x00 ) + error = 1; + segment[SEG_END] = 0xFF; + if ( segment[SEG_END] != 0xFF ) + error = 1; + if ( ! error ) { // If memory found, add to the heap + printf ( "Memory found at location %p, ", segment ); + _heapadd ( segment, BLOCK_SIZE ); + heap_size = _heapmemavail(); + printf( "so the system now has %u bytes available.\n", heap_size ); + } else { + error = 0; + } + } + segment += 0x1000; // Increment to next segment + } + + segment[0] = 0x00; // Check beginning of top memory segment + if ( segment[0] != 0x00 ) + error = 1; + segment[0] = 0xFF; + if ( segment[0] != 0xFF ) + error = 1; + segment[TOP_END] = 0x00; // Check end of usable memory + if ( segment[TOP_END] != 0x00 ) + error = 1; + segment[TOP_END] = 0xFF; + if ( segment[TOP_END] != 0xFF ) + error = 1; + if ( ! error ) { // If memory found, add to the heap + printf ( "Memory found at location %p, ", segment ); + _heapadd ( segment, TOP_SIZE ); + heap_size = _heapmemavail(); + printf( "so the system now has %u bytes available.\n", heap_size ); + } + + puts ("\nEnjoy your day!\n"); + + return 0; +}