mirror of
https://github.com/KarolS/millfork.git
synced 2026-04-21 09:16:34 +00:00
Allow initializing writable variables on cartridge targets
This commit is contained in:
@@ -67,8 +67,6 @@ Default: the same as `encoding`.
|
||||
|
||||
* `emit_z80` – whether the compiler should emit Zilog Z80 instructions not covered by `emit_x80`, default is `true` on compatible processors and `false` elsewhere
|
||||
|
||||
* `ro_arrays` – (deprecated) whether the compiler should warn upon array writes, default is `false`
|
||||
|
||||
* `prevent_jmp_indirect_bug` – whether the compiler should try to avoid the indirect JMP bug,
|
||||
default is `false` on 65C02-compatible or non-6502 processors and `true` elsewhere
|
||||
|
||||
@@ -132,6 +130,10 @@ Default: `default`. In all options below, `NAME` refers to a segment name.
|
||||
Note that the default segment for uninitialized arrays and variables is always `default`.
|
||||
Default: `default`
|
||||
|
||||
* `ram_init_segment` – the segment storing a copy of initial values for preinitialized writable arrays and variables.
|
||||
The segment cannot be `default`. See [the ROM vs RAM guide](./rom-vs-ram.md) for more information.
|
||||
Default: none.
|
||||
|
||||
* `segment_NAME_start` – the first address used for automatic allocation in the segment.
|
||||
Note that on 6502-like targets, the `default` segment shouldn't start before $200, as the $0-$1FF range is reserved for the zeropage and the stack.
|
||||
The `main` function will be placed as close to the beginning of its segment as possible, but not necessarily at `segment_NAME_start`
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
[< back to index](../index.md)
|
||||
|
||||
### ROM vs RAM targets
|
||||
|
||||
By default, Millfork assumes that the target platform loads the program into RAM.
|
||||
Code, read-only data and preinitialized writable data are all mixed together.
|
||||
The program after loading can modify its contents, including preinitialized variables,
|
||||
almost immediately and without any extra preparation.
|
||||
|
||||
When compiling for a cartridge based target, the preinitialized data cannot be writable,
|
||||
as they are not loaded into RAM, but stored in ROM.
|
||||
To make working with preinitialized data easier,
|
||||
Millfork can create a copy of preinitialized writable date in ROM,
|
||||
which can then be loaded into RAM when the program starts.
|
||||
|
||||
The steps are as follows:
|
||||
|
||||
* Add the `ram_init_segment=SEGMENT` option to the `[allocation]` section in your platform definition file,
|
||||
where `SEGMENT` is the ROM segment that will store the initial values.
|
||||
|
||||
* Near the beginning of your program, call the `init_rw_memory` function.
|
||||
It is imported automatically, you don't need to add any import statements.
|
||||
If you are targeting both RAM-based and ROM-based platforms, wrap the call in `#if INIT_RW_MEMORY`...`#endif`,
|
||||
as the `init_rw_memory` function is not available for RAM-based targets. For example:
|
||||
|
||||
void main() {
|
||||
#if INIT_RW_MEMORY
|
||||
// do a bankswitch to the SEGMENT segment if applicable
|
||||
init_rw_memory()
|
||||
#endif
|
||||
// ... rest of the code
|
||||
}
|
||||
|
||||
If the default implementation of `init_rw_memory` is unsatisfactory for your needs,
|
||||
consider implementing your own and putting it in the `init_rw_memory` module
|
||||
in the same directory as your main source file, to override the standard one.
|
||||
|
||||
|
||||
Using the `ram_init_segment` option adds the following restrictions:
|
||||
|
||||
* Preinitialized writable variables and arrays can be put only in the `default` segment.
|
||||
|
||||
* Preinitialized writable variables and arrays cannot be given a fixed address.
|
||||
|
||||
* On 6502-based targets, the zeropage pseudoregister has to have size of at least 4,
|
||||
unless the size of the `default` segment is 256 bytes or less (out of currently supported targets, only Atari 2600 has such small RAM),
|
||||
which uses a different, smaller and faster implementation of `init_rw_memory` that doesn't require a zeropage pseudoregister.
|
||||
You can force the compiler to use this smaller implementation by adding a preprocessor feature `TINY_RW_MEMORY = 1`.
|
||||
It works only if the total size of writable memory to initialize is 255 bytes or less.
|
||||
@@ -9,6 +9,9 @@ but it may be expanded to support other 6502-based and Z80-based platforms in th
|
||||
|
||||
To add a custom platform yourself, see [the custom platform adding guide](./custom-platform.md).
|
||||
|
||||
If you are compiling for a cartridge-based target,
|
||||
you need to take special precautions; see [the ROM vs RAM guide](./rom-vs-ram.md)
|
||||
|
||||
## Supported platforms
|
||||
|
||||
The following platforms are currently supported:
|
||||
@@ -92,6 +95,3 @@ The compiler emits COM files.
|
||||
* `dos_com` – a COM file for DOS on IBM PC. (very experimental)
|
||||
|
||||
The primary and most tested platform is Commodore 64.
|
||||
|
||||
Currently, targets that assume that the program will be loaded from disk or tape are better tested.
|
||||
Cartridge targets may exhibit unexpected bugs.
|
||||
|
||||
@@ -54,6 +54,9 @@ The following features are defined based on the chosen CPU and compilation optio
|
||||
`CPUFEATURE_8080`, `CPUFEATURE_8085`, `CPUFEATURE_GAMEBOY`, `CPUFEATURE_Z80`,
|
||||
`CPUFEATURE_6502_ILLEGALS`, `CPUFEATURE_8085_ILLEGALS`, `CPUFEATURE_Z80_ILLEGALS` – 1 if given instruction subset is enabled, 0 otherwise
|
||||
|
||||
* `INIT_RW_MEMORY` – 1 if the option `ram_init_segment` is defined, 0 otherwise.
|
||||
See [the ROM vs RAM guide](../api/rom-vs-ram.md) for more information.
|
||||
|
||||
* `OPTIMIZE_FOR_SIZE`, `OPTIMIZE_FOR_SPEED`, `OPTIMIZE_INLINE`, `OPTIMIZE_IPO`
|
||||
– 1 if given optimization setting is enabled, 0 otherwise
|
||||
|
||||
@@ -63,6 +66,8 @@ The following features are defined based on the chosen CPU and compilation optio
|
||||
|
||||
* `ZPREG_SIZE` – size of the pseudoregister in bytes, or 0 on platforms that don't use it
|
||||
|
||||
* `TINY_MAIN_RAM` – 1 if the main ram is 256 bytes or less, 0 otherwise
|
||||
|
||||
* `USES_IX_STACK`, `USES_IY_STACK` – 1 if given index register is used as a base pointer for stack-allocated variables, 0 otherwise
|
||||
|
||||
* `USES_SHADOW_REGISTERS` – 1 if interrupts preserve old registers in the shadow registers, 0 if they do it on stack
|
||||
|
||||
@@ -4,6 +4,16 @@ Definitions on the following list are frequently provided by the default automat
|
||||
|
||||
However, as they are not the part of the standard library, they might not be available on all targets:
|
||||
|
||||
#### `void init_rw_memory()`
|
||||
|
||||
Initializes all writable arrays and variables with their initial values.
|
||||
|
||||
If the preprocessor feature `INIT_RW_MEMORY` is defined and non-zero,
|
||||
then `init_rw_memory` is available and should be called before accessing any preinitialized writable object.
|
||||
|
||||
If the preprocessor feature `INIT_RW_MEMORY` is not defined or is zero,
|
||||
then `init_rw_memory` is not available.
|
||||
|
||||
#### `void putchar(byte char)`
|
||||
|
||||
Prints a single character.
|
||||
|
||||
Reference in New Issue
Block a user