diff --git a/CONFIG.md b/CONFIG.md new file mode 100644 index 00000000..8975dc56 --- /dev/null +++ b/CONFIG.md @@ -0,0 +1,58 @@ + +# Configuring the build + +It's not possible to provide ROM builds that suit everyone needs - therefore configuration files were introduced, separately for each of the hardware targets: + +* [`c64/,,config_generic.s`](c64/,,config_generic.s) +* [`c64/,,config_mega65.s`](c64/,,config_mega65.s) +* [`c64/,,config_ultimate64.s`](c64/,,config_ultimate64.s) + +Just edit them and recompile the project. To enable particular option - uncomment it by removing leading `//` from before `#define` directive (as you probably guessed, commenting out disables it). Some options are followed by constants - you can change them too to further fine-tune the build. + +Note however, that features do not came for free - enabling them needs some additional ROM space (in BASIC segment, in KERNAL segment, or in both), which is VERY limited on the target machines. Some options might be unavailable for speecific targets - read the comments in the configuration files. Some options might also carry compatibility and/or performance hit - so choose wisely. + +Sane defaults are already present - different for each target. + +## Memory models + +Different layouts of memory are possible - but they can be selected at compile time only. + +### `CONFIG_MEMORY_MODEL_38K` + +Memory model the original machine uses - memory available for BASIC ends at `$9FFF`, just before the first block of ROM. The fastest and the most compatible, but gives the least memory for BASIC. If unsure - select this one. + +### `CONFIG_MEMORY_MODEL_46K` and `CONFIG_MEMORY_MODEL_50K` + +Planned for the future - not available yet. + +### `CONFIG_MEMORY_MODEL_60K` + +Uses RAM under BASIC, I/O and KERNAL, takes over `$C000`-`$CFFF` area requires special helper routines installed in `$2A7`-`$2FF` area (normally unused and free for the user). Gives the most free memory for BASIC programs, but it's the slowest and the least compatible model. + +TODO: ROM memory consumption + +## Multiple SID support + +The SID is a sound chip - original machine had one installed. However, mods exists to add more of them for improved sound capabilitiee. Emulators and FPGA machines typically allow to simulate more than one too. Unfortunately, there is no standard regarding how these additional chips are visible in the processor address space, and there is no sane way to detect it - thus, it has to be configurable. + +The SID support in the ROM is very limited - it only disables the sound during startup or warm restart (when STOP+RESTORE is pressed or BRK assembler instruction is executed). + +### `CONFIG_SID_2ND` and `CONFIG_SID_3RD` + +Each of them add support for one additional SID - addresses should be given in `CONFIG_SID_2ND_ADDRESS` and `CONFIG_SID_3RD_ADDRESS`, respectively. + +Each of these options needs 8 bytes in KERNAL segment. + +### `CONFIG_SID_D4XX` and `CONFIG_SID_D5XX` + +Cause the system to support SIDs in `$D4xx` and `$D5xx` ranges, respectively. + +Each of them needs a couple of bytes in KERNAL segment - but they can share some code, and `$D4xx` range support replaces the standard `$D400` address handling, so exact amount depends on the exact configuration. + +## Miscelaneous features + +### `CONFIG_DOS_WEDGE` + +If enabled, a simple DOS wedge is available from the direct mode - supports `@`, `@`, `@$`, `@$` and `@` commands. + +Feature needs about 330 bytes in BASIC segment. diff --git a/Makefile b/Makefile index 5f770905..7fcf6975 100644 --- a/Makefile +++ b/Makefile @@ -15,6 +15,11 @@ SRCDIR_KERNAL_ultimate64 = $(SRCDIR_KERNAL_COMMON) c64/kernal/,target_ultimate64 SRC_TOOLS = $(wildcard src/tools/*.c,src/tools/*.cc) +# Generated files + +GEN_BASIC = build/,generated/packed_messages.s +GEN_KERNAL = + # List of tools TOOL_COLLECT_DATA = build/tools/collect_data @@ -84,13 +89,13 @@ build/chargen.rom: $(TOOL_PNGPREPARE) assets/8x8font.png # Dependencies - BASIC and KERNAL -build/target_generic/OUTB.BIN: $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(SRCDIR_BASIC_generic) $(foreach dir,$(SRCDIR_BASIC_generic),$(wildcard $(dir)/*.s)) build/,generated/packed_messages.s -build/target_mega65/OUTB.BIN: $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(SRCDIR_BASIC_mega65) $(foreach dir,$(SRCDIR_BASIC_mega65),$(wildcard $(dir)/*.s)) build/,generated/packed_messages.s -build/target_ultimate64/OUTB.BIN: $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(SRCDIR_BASIC_ultimate64) $(foreach dir,$(SRCDIR_BASIC_ultimate64),$(wildcard $(dir)/*.s)) build/,generated/packed_messages.s +build/target_generic/OUTB.BIN: $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(GEN_BASIC) $(SRCDIR_BASIC_generic) c64/,,config_generic.s $(foreach dir,$(SRCDIR_BASIC_generic),$(wildcard $(dir)/*.s)) +build/target_mega65/OUTB.BIN: $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(GEN_BASIC) $(SRCDIR_BASIC_mega65) c64/,,config_mega65.s $(foreach dir,$(SRCDIR_BASIC_mega65),$(wildcard $(dir)/*.s)) +build/target_ultimate64/OUTB.BIN: $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(GEN_BASIC) $(SRCDIR_BASIC_ultimate64) c64/,,config_ultimate64.s $(foreach dir,$(SRCDIR_BASIC_ultimate64),$(wildcard $(dir)/*.s)) -build/target_generic/OUTK.BIN: $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(SRCDIR_KERNAL_generic) $(foreach dir,$(SRCDIR_KERNAL_generic),$(wildcard $(dir)/*.s)) -build/target_mega65/OUTK.BIN: $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(SRCDIR_KERNAL_mega65) $(foreach dir,$(SRCDIR_KERNAL_mega65),$(wildcard $(dir)/*.s)) -build/target_ultimate64/OUTK.BIN: $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(SRCDIR_KERNAL_ultimate64) $(foreach dir,$(SRCDIR_KERNAL_ultimate64),$(wildcard $(dir)/*.s)) +build/target_generic/OUTK.BIN: $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(GEN_KERNAL) $(SRCDIR_KERNAL_generic) c64/,,config_generic.s $(foreach dir,$(SRCDIR_KERNAL_generic),$(wildcard $(dir)/*.s)) +build/target_mega65/OUTK.BIN: $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(GEN_KERNAL) $(SRCDIR_KERNAL_mega65) c64/,,config_mega65.s $(foreach dir,$(SRCDIR_KERNAL_mega65),$(wildcard $(dir)/*.s)) +build/target_ultimate64/OUTK.BIN: $(TOOL_ASSEMBLER) $(TOOL_BUILD_SEGMENT) $(GEN_KERNAL) $(SRCDIR_KERNAL_ultimate64) c64/,,config_ultimate64.s $(foreach dir,$(SRCDIR_KERNAL_ultimate64),$(wildcard $(dir)/*.s)) build/target_generic/newrom: build/target_generic/OUTB.BIN build/target_generic/OUTK.BIN build/target_mega65/newrom: build/target_mega65/OUTB.BIN build/target_mega65/OUTK.BIN @@ -114,13 +119,13 @@ build/,generated/packed_messages.s: $(TOOL_COMPRESS_TEXT) build/target_%/OUTB.BIN: @mkdir -p build/target_$* @rm -f $@* build/target_$*/BASIC* - @$(TOOL_BUILD_SEGMENT) -s BASIC -i BASIC-$* -o OUTB.BIN -t build/target_$* -l a000 -h e4d2 $(SRCDIR_BASIC_$*) build/,generated/packed_messages.s + @$(TOOL_BUILD_SEGMENT) -s BASIC -i BASIC-$* -o OUTB.BIN -t build/target_$* -l a000 -h e4d2 c64/,,config_$*.s $(SRCDIR_BASIC_$*) $(GEN_BASIC) .PRECIOUS: build/target_%/OUTK.BIN build/target_%/OUTK.BIN: @mkdir -p build/target_$* @rm -f $@* build/target_$*/KERNAL* - @$(TOOL_BUILD_SEGMENT) -s KERNAL -i KERNAL-$* -o OUTK.BIN -t build/target_$* -l e4d3 -h ffff $(SRCDIR_KERNAL_$*) + @$(TOOL_BUILD_SEGMENT) -s KERNAL -i KERNAL-$* -o OUTK.BIN -t build/target_$* -l e4d3 -h ffff c64/,,config_$*.s $(SRCDIR_KERNAL_$*) $(GEN_KERNAL) .PRECIOUS: build/target_%/newrom build/target_%/newrom: @@ -148,12 +153,21 @@ build/newc65.rom: build/kernal_mega65.rom build/basic_mega65.rom build/chargen.r test: build/kernal_generic.rom build/basic_generic.rom x64 -kernal build/kernal_generic.rom -basic build/basic_generic.rom -8 empty.d64 +test_generic: build/kernal_generic.rom build/basic_generic.rom + x64 -kernal build/kernal_generic.rom -basic build/basic_generic.rom -8 empty.d64 + +test_mega65: build/kernal_mega65.rom build/basic_mega65.rom + x64 -kernal build/kernal_mega65.rom -basic build/basic_mega65.rom -8 empty.d64 + +test_ultimate64: build/kernal_ultimate64.rom build/basic_ultimate64.rom + x64 -kernal build/kernal_ultimate64.rom -basic build/basic_ultimate64.rom -8 empty.d64 + +test_m65: build/newc65 + m65 -b ../mega65-core/bin/mega65r1.bit -k ../mega65-core/bin/KICKUP.M65 -R build/newc65.rom -4 + testremote: build/kernal_generic.rom build/basic_generic.rom x64 -kernal build/kernal_generic.rom -basic build/basic_generic.rom -remotemonitor -testm65: build/newc65 - m65 -b ../mega65-core/bin/mega65r1.bit -k ../mega65-core/bin/KICKUP.M65 -R build/newc65.rom -4 - testsimilarity: build/target_generic/newrom $(TOOL_SIMILARITY) $(TOOL_SIMILARITY) kernal build/target_generic/newrom $(TOOL_SIMILARITY) basic build/target_generic/newrom diff --git a/STATUS.md b/STATUS.md index 3759a299..e1f308af 100644 --- a/STATUS.md +++ b/STATUS.md @@ -1,7 +1,7 @@ # New features -Here are the features of the Open ROMs not found in the original ROMs from the 80s: +Here are the features of the Open ROMs not found in the original ROMs from the 80s (many of them are [configurable](CONFIG.md)): * improved keyboard scanning, supports multi-key roll-over and rejection of spurious joystick input * joystick (port 1) can be used to move text cursor diff --git a/c64/,,config_generic.s b/c64/,,config_generic.s new file mode 100644 index 00000000..7f57226d --- /dev/null +++ b/c64/,,config_generic.s @@ -0,0 +1,19 @@ + +// +// Please read CONFIG.md before modifying this file! +// + + +#define CONFIG_MEMORY_MODEL_38K +// #define CONFIG_MEMORY_MODEL_60K + +// #define CONFIG_SID_2ND +.const CONFIG_SID_2ND_ADDRESS = $D420 + +// #define CONFIG_SID_3RD +.const CONFIG_SID_3RD_ADDRESS = $D440 + +// #define CONFIG_SID_D4XX +// #define CONFIG_SID_D5XX + +#define CONFIG_DOS_WEDGE diff --git a/c64/,,config_mega65.s b/c64/,,config_mega65.s new file mode 100644 index 00000000..14782cd8 --- /dev/null +++ b/c64/,,config_mega65.s @@ -0,0 +1,19 @@ + +// +// Please read CONFIG.md before modifying this file! +// + + +// #define CONFIG_MEMORY_MODEL_38K +#define CONFIG_MEMORY_MODEL_60K + +#define CONFIG_SID_2ND +.const CONFIG_SID_2ND_ADDRESS = $D420 + +// #define CONFIG_SID_3RD +.const CONFIG_SID_3RD_ADDRESS = $D440 + +// #define CONFIG_SID_D4XX +// #define CONFIG_SID_D5XX + +#define CONFIG_DOS_WEDGE diff --git a/c64/,,config_ultimate64.s b/c64/,,config_ultimate64.s new file mode 100644 index 00000000..5fa131a9 --- /dev/null +++ b/c64/,,config_ultimate64.s @@ -0,0 +1,19 @@ + +// +// Please read CONFIG.md before modifying this file! +// + + +#define CONFIG_MEMORY_MODEL_38K +// #define CONFIG_MEMORY_MODEL_60K + +// #define CONFIG_SID_2ND +.const CONFIG_SID_2ND_ADDRESS = $D420 + +// #define CONFIG_SID_3RD +.const CONFIG_SID_3RD_ADDRESS = $D440 + +#define CONFIG_SID_D4XX +#define CONFIG_SID_D5XX + +#define CONFIG_DOS_WEDGE diff --git a/c64/aliases/,aliases_hardware.s b/c64/aliases/,aliases_hardware.s index 2eee3541..343fb5db 100644 --- a/c64/aliases/,aliases_hardware.s +++ b/c64/aliases/,aliases_hardware.s @@ -10,6 +10,8 @@ // VIC-II registers + .label VIC_BASE = $D000 // base address of the chip + .label VIC_SP0X = $D000 .label VIC_SP0Y = $D001 .label VIC_SP1X = $D002 @@ -62,6 +64,8 @@ // SID registers + .label SID_BASE = $D400 // base address of the chip + .label SID_FRELO1 = $D400 .label SID_FREHI1 = $D401 .label SID_PWLO1 = $D402 @@ -97,6 +101,8 @@ // CIA #1 registers + .label CIA1_BASE = $DC00 // base address of the chip + .label CIA1_PRA = $DC00 .label CIA1_PRB = $DC01 .label CIA1_DDRA = $DC02 @@ -119,6 +125,8 @@ // CIA #2 registers + .label CIA2_BASE = $DD00 // base address of the chip + .label CIA2_PRA = $DD00 // VIC bank switching and IEC port .label CIA2_PRB = $DD01 .label CIA2_DDRA = $DD02 diff --git a/c64/basic/,aliases.s b/c64/basic/,aliases.s index 2cd8b229..e2a02afb 100644 --- a/c64/basic/,aliases.s +++ b/c64/basic/,aliases.s @@ -113,6 +113,8 @@ .label enable_case_switch = $0291 .label screen_scroll_disable = $0292 +#if CONFIG_MEMORY_MODEL_60K + // BASIC uses some extra bytes for memory access under ROMs located at $2A7 onwards // IRQs are disabled when doing such accesses, and a default NMI handler only increments // a counter, so that if an NMI occurs, it doesn't crash the machine, but can be captured. @@ -124,3 +126,5 @@ .label poke_under_roms = tiny_nmi_handler+poke_under_roms_routine-tiny_nmi_handler_routine .label memmap_allram = tiny_nmi_handler+memmap_allram_routine-tiny_nmi_handler_routine .label memmap_normal = tiny_nmi_handler+memmap_normal_routine-tiny_nmi_handler_routine + +#endif // CONFIG_MEMORY_MODEL_60K diff --git a/c64/basic/basic_delete_line.s b/c64/basic/basic_delete_line.s index 4b4867fd..922cc46b 100644 --- a/c64/basic/basic_delete_line.s +++ b/c64/basic/basic_delete_line.s @@ -14,12 +14,24 @@ basic_delete_line: // .byte $0d,0 // Get address of next line - ldx #$f7ff +#if CONFIG_MEMORY_MODEL_60K + lda #>$F7FF +#else // CONFIG_MEMORY_MODEL_38K + lda #>$9FFF +#endif .byte $2C -!: lda #>$7FFF +!: +#if CONFIG_MEMORY_MODEL_60K + lda #>$F7FF +#else // CONFIG_MEMORY_MODEL_38K + lda #>$9FFF +#endif sta basic_top_of_memory_ptr+1 sta basic_start_of_strings_ptr+1 - lda #<$f7ff +#if CONFIG_MEMORY_MODEL_60K + lda #<$F7FF +#else // CONFIG_MEMORY_MODEL_38K + lda #<$9FFF +#endif sta basic_top_of_memory_ptr+0 sta basic_start_of_strings_ptr+0 diff --git a/c64/basic/peek_line_pointer_null_check.s b/c64/basic/peek_line_pointer_null_check.s new file mode 100644 index 00000000..e7a8fb38 --- /dev/null +++ b/c64/basic/peek_line_pointer_null_check.s @@ -0,0 +1,34 @@ +// Return C=1 if a pointer in BASIC memory space is NULL, else C=0 +// X = ZP pointer to check + +peek_line_pointer_null_check: + + ldy #$00 + +#if CONFIG_MEMORY_MODEL_60K + ldx # memmove_src + // This means we have to copy from the back end down. + // This routine assumes the pointers are already pointed + // to the end of the areas, and that Y is correctly initialised + // to allow the copy to begin. + php +smu1: + lda (memmove_src),y + sta (memmove_dst),y + dey + bne smu1 + dec memmove_src+1 + dec memmove_dst+1 + dec memmove_size+1 + bne smu1 + plp + rts + +shift_mem_down: + // Move memmove_size bytes from memmove_src to memmove_dst, + // where memmove_dst > memmove_src + // This means we have to copy from the back end down. + // This routine assumes the pointers are already pointed + // to the end of the areas, and that Y is correctly initialised + // to allow the copy to begin. + php +smd1: + lda (memmove_src),y + sta (memmove_dst),y + iny + bne smd1 + inc memmove_src+1 + inc memmove_dst+1 + dec memmove_size+1 + bne smd1 + plp + rts + +#endif diff --git a/c64/basic/wedge_dos.s b/c64/basic/wedge_dos.s index 7259d131..28785111 100644 --- a/c64/basic/wedge_dos.s +++ b/c64/basic/wedge_dos.s @@ -1,5 +1,5 @@ -// START wedge support +#if CONFIG_DOS_WEDGE wedge_dos: @@ -235,4 +235,4 @@ wedge_dos_setnam: ldy basic_current_statement_ptr+1 jmp JSETNAM -// END wedge support +#endif // CONFIG_DOS_WEDGE diff --git a/c64/kernal/,aliases.s b/c64/kernal/,aliases.s index 0d133ed5..00578fd7 100644 --- a/c64/kernal/,aliases.s +++ b/c64/kernal/,aliases.s @@ -62,6 +62,8 @@ .label enable_case_switch = $0291 .label screen_scroll_disable = $0292 +#if CONFIG_MEMORY_MODEL_60K + // Under-ROM routines // (BASIC also includes them. XXX - We should de-duplicate them in a safe manner) .label missed_nmi_flag = $2A7 @@ -71,3 +73,4 @@ .label memmap_allram = tiny_nmi_handler+memmap_allram_routine-tiny_nmi_handler_routine .label memmap_normal = tiny_nmi_handler+memmap_normal_routine-tiny_nmi_handler_routine +#endif // CONFIG_MEMORY_MODEL_60K diff --git a/c64/kernal/f34a.open.s b/c64/kernal/f34a.open.s index a669d960..65b03974 100644 --- a/c64/kernal/f34a.open.s +++ b/c64/kernal/f34a.open.s @@ -81,8 +81,10 @@ open_iec: jmp kernalerror_DEVICE_NOT_FOUND !: +#if CONFIG_MEMORY_MODEL_60K // We need our helpers to get to filenames under ROMs or IO area jsr install_ram_routines +#endif // Send command ('file name') jsr lvs_send_file_name diff --git a/c64/kernal/f4a5.load.s b/c64/kernal/f4a5.load.s index bb43f88f..1cfc2d3b 100644 --- a/c64/kernal/f4a5.load.s +++ b/c64/kernal/f4a5.load.s @@ -31,8 +31,10 @@ LOAD: // Reset status jsr kernalstatus_reset +#if CONFIG_MEMORY_MODEL_60K // We need our helpers to get to filenames under ROMs or IO area jsr install_ram_routines +#endif // Allow platform-specific routine to takeover the flow TARGET_HOOK_LOAD() diff --git a/c64/kernal/fda3.ioinit.s b/c64/kernal/fda3.ioinit.s index c9fef15b..a64b1fc4 100644 --- a/c64/kernal/fda3.ioinit.s +++ b/c64/kernal/fda3.ioinit.s @@ -20,23 +20,51 @@ IOINIT: sta CPU_R6510 stx CPU_D6510 - // Silence the SID chips under common addresses + // Silence the SID chips, depending on the configuration +#if !CONFIG_SID_D4XX + lda SID_SIGVOL + and #$F0 + sta SID_SIGVOL +#endif // !CONFIG_SID_D4XX + +#if CONFIG_SID_D4XX || CONFIG_SID_D5XX ldy #$00 !: - // SIDs under $D4xx + +#if CONFIG_SID_D4XX lda SID_SIGVOL, Y and #$F0 sta SID_SIGVOL, Y +#endif // CONFIG_SID_D4XX + +#if CONFIG_SID_D5XX // SIDs under $D5xx lda SID_SIGVOL + $100, Y and #$F0 sta SID_SIGVOL + $100, Y +#endif // CONFIG_SID_D4XX + tya clc adc #$20 tay bne !- +#endif // CONFIG_SID_D4XX || CONFIG_SID_D5XX + +#if CONFIG_SID_2ND + lda SID_SIGVOL - SID_BASE + CONFIG_SID_2ND_ADDRESS + and #$F0 + sta SID_SIGVOL - SID_BASE + CONFIG_SID_2ND_ADDRESS +#endif // CONFIG_SID_2ND + +#if CONFIG_SID_3RD + lda SID_SIGVOL - SID_BASE + CONFIG_SID_3RD_ADDRESS + and #$F0 + sta SID_SIGVOL - SID_BASE + CONFIG_SID_3RD_ADDRESS +#endif // CONFIG_SID_3RD + + // Initialize CIAs // XXX: calibrate TOD for both CIA's, see here: https://codebase64.org/doku.php?id=base:efficient_tod_initialisation diff --git a/c64/kernal/lvs_helpers.s b/c64/kernal/lvs_helpers.s index b4e20e98..c74295a2 100644 --- a/c64/kernal/lvs_helpers.s +++ b/c64/kernal/lvs_helpers.s @@ -8,8 +8,14 @@ lvs_send_file_name: lvs_send_file_name_loop: cpy FNLEN beq lvs_send_file_name_done - ldx #