One of the biggest complaints about the C64 is that all the available expansions that are cleaning your bank account aren't utilized by any software. Memory expansions are one of the biggest offenders. Even nowadays, the only programs that really utilize the expanded memory as system RAM are terminal programs and text editors. The goal of SoftMMU is to define an API standard that can be used to access any and all available memory expansions. The first implementation will be written for LUnix NG, and will probably find a home in other multitasking C64 OSes like Andre Fachat's OS/A65.
The following memory expansions are the ones that are currently being implemented in SoftMMU:
To come up with an interface that can accomodate all of these radically
different expansion approaches, a program is given a 256-byte window
into the 24-bit address space which it actually allocates. Bytes are
accessed out of this window with the LDA (window),Y
assembly
instruction. The program must
tell the API to change the portion of the chunk which the window is
mirroring when access to memory outside of the 256-byte window is needed.
The actual location of the window must be dynamic, to allow for fast
random access to flat memory (6502, SuperRAM) and large banks (C128,
C64/256K). This allows the API greater flexibility in deciding
how the program should see the requested memory, as well as being able to
cache multiple windows in system memory.
The pointer to the window lies in zero page, and for multitasking/protected systems, in the user memory context. This pointer is initialized and updated by the SoftMMU API and should be considered by the program to be read-only. Another 16-bit user-space zero page variable contains the upper 16 bits of the 24-bit address of the window's position within the chunk. Finally, a single byte is reserved for system-specific purposes, most probably being a pointer or offset to further internal structures related to the memory chunk. This byte must never be changed by the program.
;Within zero-page window .word $0000 page .word $0000 .byte $00Multiple chunks may be allocated, each with their own 5-byte zero page structure. All other variables and bookkeeping is handled by the system.
page
window
xinfo | Report SoftMMU and implementation info. |
xalloc | Allocate a memory chunk. |
xrealloc | Resize an existing memory chunk. |
xgetsize | Get the size of an existing memory chunk. |
xfree | Deallocate a memory chunk. |
xpage | Page through a memory chunk. |
Returns information about SoftMMU version, system and implementation information. Fairly useless, because enhancements in future versions should be transparent to the API. However, it only takes 7 bytes of memory to implement.
The lower 4 bits define the base system:%0000: C64
%0001: C64 w/256K
%0010: C128
%0011: C128 w/1M
%0100: SuperCPU 64
%0101: SuperCPU 128
%0110: reserved
%0111: reserved
%1xxx: reserved for different platform(s)The rest of the bits define the C64/C128 expansions:
$10: REU
$20: GeoRAM/BBGRam
$40: SuperRAM
$80: RamLinkIf bit 3 is set, the upper 4 bits are reserved for other platform-specific expansions.
Allocates a memory chunk, and creates a window to that chunk. Memory in the chunk is not initialized. The structure that contains the window pointer and page number must be provided by the user program.
Error: Carry set. The program's memory context is not changed.
Success: Carry clear. window
will be allocated to point
to the newly allocated window, page
is initialized to $0000, and the
window will mirror the first page of the memory chunk.
;Zero page variables window = $fb page = $fd ;Allocate 132 pages (33K) of RAM ldx #window lda #<132 ldy #>132 jsr xalloc
Changes the size of an existing memory chunk. Contents of the chunk (up to the new size) are preserved. If the chunk is made smalled, contents which are contained above the new chunk size are lost. If the chunk is made larger, the newly allocated memory is not initialized.
Error: Carry set. The memory state of the program is not changed.
Success: Carry clear. window
is updated if required, and
is refreshed with the according page. An undefined condition occurs if
page
is outside of the bounds of the new chunk.
;Zero page variables window = $fb page = $fd ldx #window ... jsr xalloc ... ;Resize the chunk to 4096 pages (1M) of RAM ldx #window lda #<4096 ldy #>4096 jsr xrealloc
Queries the allocated size of an existing memory chunk.
Error: Carry set.
Success: Carry clear. .A/.Y = Size (in pages) of the memory chunk allocated to the structure pointed to by .X
;Zero page variables window = $fb page = $fd ldx #window ... jsr xalloc ... ;See if our memory chunk is >=128k ldx #window jsr xgetsize cpy #1 bcs bigchunk
Deallocates a memory chunk that was previously allocated with xalloc
.
If .X points to an unitialized, already freed, or invalid
window structure, xfree
merely returns.
;Zero page variables window = $fb page = $fd ldx #window ... jsr xalloc ... ;Deallocate the chunk ldx #window jsr xfree
Moves the memory window to a different section of the chunk. The implementation
may do this in whatever method suits the environment best. This may include
changing the window
pointer to point to another location in
RAM, copying or banking a page of memory into the page that
window
points to, or a combination of both.
page
= holds the page number to mirror in the window.
If page
points to a page outside of the bounds
of the memory chunk, a Segmentation Fault
fatal error
occurs.
;Zero page variables window = $fb page = $fd ldx #window ... jsr xalloc ... ;Page in the first page lda #$00 sta page sta page+1 ldx #window jsr xpage ... ;Look at the next page inc page bne + inc page+1 + jsr xpage
Overview of Implementation (read this first)
Config