6502 without the memory maze¶
The processor may see 64 KiB at a time. Your D/BASIC program is not a 64 KiB program.
The 6502 is an important D/BASIC destination, not a novelty mode. It brings a wonderfully small, understandable processor into a language with objects, widgets, large arrays, packaged resources, and modern operating-system services. The trick is not pretending the processor has a different address bus. The trick is making that address bus the runner's responsibility rather than yours.
The first profile targets 512 KiB¶
Many older BASIC environments were squeezed into 16–64 KiB alongside the interpreter, screen, operating system, source text, variables, and string heap. Programs learned to survive through overlays, tiny buffers, bank registers, and machine-specific copy routines.
D/BASIC removes that ceiling from the language model. Its first 6502 target profile sets a nominal useful workspace target of 512 KiB. Later target profiles can offer more without adding a new dialect or requiring a source rewrite. The 512 KiB figure is the first target profile, not a permanent language limit, a flat pointer, or an unconditional allocation receipt.
Before execution, the runner admits the image, static state, and the program's
known minimum workload. Dynamic demand can still arise later from REDIM,
growing strings, new objects, resources, or provider work. Each such allocation
is admitted atomically when requested: if capacity is unavailable, the runner
refuses the request and leaves the old binding and published state intact. A
smaller machine never continues with a half-applied allocation on the strength
of a marketing number.
This distinction matters:
| Fact | Who deals with it? |
|---|---|
| the 6502 has a 16-bit address window | runner and hardware adapter |
| a particular byte currently lives in a bank or page | memory provider |
| an array has 100,001 elements | D/BASIC program |
| a target cannot satisfy an admitted allocation | governed capacity refusal |
You still design within a real machine's published capacity. You simply do it with values and bounds instead of addresses and bank numbers.
Write DIM, not a bank-switching ritual¶
DIM Samples%(0 TO 4095)
ARRAYFILL Samples%(), -1
Samples%(2048) = 42
PRINT Samples%(2048)
ERASE Samples%
END
That program contains no far pointer, page call, bank selector, or copy-through
buffer. DIM asks for an array with a shape. The runtime chooses storage,
pages values as needed, validates every access, and keeps the binding
authoritative until ERASE releases it.
Arrays, variable strings, objects, and other dynamic values live behind governed handles. A handle is never a machine address. It can name storage in a resident region, a banked pool, or another admitted tier while the same DBC image keeps the same meaning.
Banking is deliberately invisible¶
The toolchain and runner own code and constant placement. The 6502 runner keeps a bounded working set in reach and pages immutable DBC regions through its private adapter. On a miss, the runner performs the bounded bank transaction and then continues the same bytecode operation.
None of these implementation details enter application source:
- no bank register names;
- no overlay annotations;
- no near/far pointer types;
- no “copy this bank into conventional memory first” API; and
- no target test around an array, object, or procedure call.
If a bank is selected on entry to a runner operation, the runner restores its required mapping before returning. Event delivery, object identity, array bounds, and refusal behavior therefore do not depend on which page happened to be resident.
One optional memory policy, still no banking¶
By default, a runner may satisfy governed storage from every tier it honestly offers: fast resident memory, the ordinary program pool, and a slower media tier. Most programs should keep that default.
OPTION TIER RAM is the one source-visible memory ceiling. It excludes the
media tier when an application requires RAM-only latency; it does not select a
bank, choose an address, or promise that every allocation will fit. Exhausting
the allowed tiers produces a capacity refusal instead of a silent spill or
corruption.
Intents are the acceleration API¶
Memory transparency solves capacity. Intents solve the other classic 6502 problem: asking a small CPU to perform every pixel, floating-point operation, digest, transfer, and database step one byte at a time.
INTENT GFX.BEGIN_FRAME()
INTENT GFX.FILL_RECT(0, 0, 320, 192, 2081)
INTENT GFX.DRAW_TEXT(12, 12, "HELLO FROM D/BASIC", 3, -1, 2081)
INTENT GFX.PRESENT()
The Intent API describes meaning. A 6502 runner can route an admitted request to a composed display head, math engine, bulk-memory provider, storage service, or other accelerator. A desktop runner may perform the same request through its own local route. D/BASIC code sees one operation, one ordering rule, and one result.
Acceleration is never a hidden second application. When several conforming routes exist, the runner selects the best available one. When no honest route can satisfy a required operation, admission or execution refuses by name rather than fabricating success.
Give the optimizer a big idea¶
A 6502 benefits most when source says what a whole operation means:
These verbs give the compiler and runner a semantic unit that can be sliced,
accelerated, or reduced locally. ARRAYSWAP exchanges two bindings in constant
work; it does not walk either array. Pure floating-point expression trees can
likewise become one ordered MATH request instead of a crossing per operator.
The developer-friendly rule is simple: write the clearest large operation. The toolchain handles placement and crossing reduction.
What still belongs to the programmer¶
Hidden banking does not mean imaginary resources. Good 6502-friendly D/BASIC still has a shape:
- Use the smallest honest numeric type for large collections.
- State whole-array work with
ARRAYFILL,ARRAYCOPY, andARRAYSWAP. - Keep resource and network operations bounded and asynchronous.
- Repaint damaged regions instead of every unchanged control.
- Release arrays, objects, streams, and sessions when their ownership ends.
- Declare required capability families with
APP ... NEEDSand query optional capabilities only when the application has two useful experiences to offer. - Test the exact DBC on every intended target profile.
What you do not manage is just as important: bank layouts, resident trampolines, provider mailboxes, accelerator command packets, and restoration of the machine's mapping state. Those are runner contracts.
The promise in one line¶
A learner gets DIM, arrays, classes, and widgets. An experienced 6502
developer gets a real small-machine target without carrying three decades of
manual memory machinery into every application. That is the point: the charm
of the 6502 remains; its old application ceiling does not.