From 74dd8fe80ba77f8d16efd44f28b2635dded7fe6b Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sun, 2 Feb 2025 20:46:49 +0100 Subject: [PATCH] %output library header generation depends on compiler target fileselector example tweaks --- .../prog8/codegen/cpu6502/AssemblyProgram.kt | 11 ++++- .../compiler/astprocessing/AstPreprocessor.kt | 3 +- docs/source/binlibrary.rst | 42 +++++++++--------- docs/source/programming.rst | 2 +- examples/cx16/fileselector/EXAMPLE.BAS | 11 +++++ examples/cx16/fileselector/Makefile | 7 +-- examples/cx16/fileselector/fselector.p8 | 6 ++- examples/cx16/fileselector/main.p8 | 4 +- examples/cx16/fileselector/standalone.p8 | 3 ++ examples/test.p8 | 43 ------------------- 10 files changed, 59 insertions(+), 73 deletions(-) create mode 100644 examples/cx16/fileselector/EXAMPLE.BAS diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/AssemblyProgram.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/AssemblyProgram.kt index 8f3774af4..aac8d325b 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/AssemblyProgram.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/AssemblyProgram.kt @@ -3,8 +3,10 @@ package prog8.codegen.cpu6502 import prog8.code.ast.PtLabel import prog8.code.core.* import prog8.code.target.AtariTarget +import prog8.code.target.C128Target import prog8.code.target.C64Target import prog8.code.target.Neo6502Target +import prog8.code.target.PETTarget import java.nio.file.Path @@ -56,8 +58,13 @@ internal class AssemblyProgram( binFile } OutputType.LIBRARY -> { - command.add("--cbm-prg") // include the 2-byte PRG header on library .bins, so they can be easily loaded on the correct memory address even on C64 - println("\nCreating binary library file for target ${compTarget.name}.") + if(compTarget.name in listOf(C64Target.NAME, C128Target.NAME, PETTarget.NAME)) { + println("\nCreating binary library file with header for target ${compTarget.name}.") + command.add("--cbm-prg") + } else { + println("\nCreating binary library file without header for target ${compTarget.name}.") + command.add("--nostart") // should be headerless bin, because basic has problems doing a normal LOAD"lib",8,1 - need to use BLOAD + } binFile } else -> throw AssemblyError("invalid output type") diff --git a/compiler/src/prog8/compiler/astprocessing/AstPreprocessor.kt b/compiler/src/prog8/compiler/astprocessing/AstPreprocessor.kt index 39a6f6cea..6df355ea0 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstPreprocessor.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstPreprocessor.kt @@ -275,7 +275,8 @@ class AstPreprocessor(val program: Program, if(targetStatement is Subroutine) { for(arg in call.args.zip(targetStatement.parameters)) { if(arg.first.inferType(program).isBytes && arg.second.type.isString) { - errors.err("cannot use byte value for string parameter", arg.first.position) + if((arg.first as? NumericLiteral)?.number!=0.0) + errors.err("cannot use byte value for string parameter", arg.first.position) } } } diff --git a/docs/source/binlibrary.rst b/docs/source/binlibrary.rst index 0d3d09dba..8c029058f 100644 --- a/docs/source/binlibrary.rst +++ b/docs/source/binlibrary.rst @@ -48,21 +48,22 @@ Binary output and loaded into a fixed memory address it is not ran like a normal program. Also, because it is not possible to create position independent code with prog8, a fixed load address has to be decided on and the library must be compiled - with that address as the load address. For convenience (and compatibility with older CBM - target machines such as the C64 and C128) it's easiest if the resulting library - program includes a PRG load header: 2 bytes at the start of the library that contain - the load address. This allows BASIC to load the library via a simple ``LOAD "LIB.BIN",8,1`` for example. + with that address as the load address. ``%output library`` ^^^^^^^^^^^^^^^^^^^ -Most (but not all) of the above requirements can be fulfilled by setting various directives in your +Most of the above requirements can be fulfilled by setting various directives in your source code such as %launcher, %zeropage and so on. But there is a single directive that does it correctly for you in one go (and makes sure there won't be any initialization code left at all): ``%output library`` Together with ``%address`` and possibly ``%memtop`` -to tell the compiler what the load address of the library should be- it will create a "library.bin" file that fulfills the requirements of a loadable binary library program as listed above. +For older CBM targets (C64, C128 and PET) the library file will have a load address header, +because these targets require a header to easily load files. For the other targets such as the Commander X16, +the library will be a headerless binary file that can then be loaded given the correct load address. + The entrypoint (= the start subroutine) that must be called to initialize the variables, will be the very first thing at the beginning of the library. @@ -89,21 +90,16 @@ But the users of the library are none the wiser and it just seems as if it is pa Loading and using the library ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Assuming the load address of the library is $A000 (40960): +These examples below assume the target is the Commander X16. +Assuming the load address of the library is $A000: -**From BASIC** (the example is from the Commander X16):: +**From BASIC**:: - LOAD "LIBRARY.BIN",8,1 + BLOAD "LIBRARY.BIN",8,1,$A000 SYS $A000 : REM TO INITIALIZE VARIABLES, REQUIRED! SYS $A004 : REM CALL FIRST ROUTINE SYS $A008 : REM CALL SECOND ROUTINE, ETC. -For the Commodore 64 and such this works the same but you'll have to type the SYS addresses as decimal numbers. -The Commander X16 also has the BLOAD command to load binary data files, where you have to specify the memory -location where the file has to be loaded to. But for Prog8 library files you don't have to do that, just use LOAD; -the correct address is in the header of the library file. Loading the library to a different memory address -is not possible, because it will only work on the address it was compiled for (it's not possible to create -position independent code on the 6502). **From Prog8**:: @@ -116,10 +112,12 @@ position independent code on the 6502). extsub $A008 = lib_func2() clobbers(A,X,Y) sub start() { - if diskio.load("library.bin", 0) != 0 { + if diskio.load_raw("library.bin", $a000) != 0 { lib_init() lib_func1() lib_func2() + + repeat { } } } } @@ -132,7 +130,11 @@ position independent code on the 6502). void (*lib_init)(void) = (void (*)()) 0xa000; void (*lib_func1)(void) = (void (*)()) 0xa004; void (*lib_func2)(void) = (void (*)()) 0xa008; - cbm_load("library.bin", 8, 0); + + cbm_k_setlfs(0, 8, 2); + cbm_k_setnam("library.bin"); + cbm_k_load(0, 0xa000); + lib_init(); lib_func1(); lib_func2(); @@ -146,13 +148,13 @@ position independent code on the 6502). ldx #$a000 jsr $ffd5 ; LOAD lda #13 jsr $ffd2 ; CHROUT diff --git a/docs/source/programming.rst b/docs/source/programming.rst index 1373b2fe3..81f75b28d 100644 --- a/docs/source/programming.rst +++ b/docs/source/programming.rst @@ -419,7 +419,7 @@ Directives - type ``raw`` : no header at all, just the raw machine code data - type ``prg`` : C64 program (with load address header) - type ``xex`` : Atari xex program - - type ``library`` : loadable library file (with CBM style load address header) See :ref:`loadable_library`. + - type ``library`` : loadable library file. See :ref:`loadable_library`. .. data:: %zeropage