diff --git a/ACME_Lib/cbm/c128/mmu.a b/ACME_Lib/cbm/c128/mmu.a index d62e5b9..dc4363e 100644 --- a/ACME_Lib/cbm/c128/mmu.a +++ b/ACME_Lib/cbm/c128/mmu.a @@ -3,24 +3,143 @@ !ifdef lib_cbm_c128_mmu_a !eof lib_cbm_c128_mmu_a = 1 -; mirrored registers, available in every configuration: -mmu_cr = $ff00 -mmu_lcra = $ff01 -mmu_lcrb = $ff02 -mmu_lcrc = $ff03 -mmu_lcrd = $ff04 +; Memory Management Unit (MMU) 8722 -; "normal" registers, only available when accessing i/o space: -;mmu_cr = $d500; need not be defined: If $d500 works, $ff00 does as well. -mmu_pcra = $d501 -mmu_pcrb = $d502 -mmu_pcrc = $d503 -mmu_pcrd = $d504 +; registers in i/o area (i/o needs to be enabled to access these): + +; configuration register +mmu_cr_d500 = $d500 ; same as "mmu_cr" at $ff00. Use "mmu_cr" instead, as that is *always* available. +; preconfiguration registers (internal format just like mmu_cr) +mmu_pcr_a = $d501 ; c128 kernel default is $3f (BANK 0) +mmu_pcr_b = $d502 ; c128 kernel default is $7f (BANK 1) +mmu_pcr_c = $d503 ; c128 kernel default is $01 (BANK 14) +mmu_pcr_d = $d504 ; c128 kernel default is $41 (all system roms, with ram 1) + ; contents of cr and all four pcr: + mmu_CR_RAMBANK_MASK = %##...... ; this controls which RAM bank is used in areas where RAM is enabled +; mmu_CR_RAMBANK_0 = %........ + mmu_CR_RAMBANK_1 = %.#...... + mmu_CR_RAMBANK_2 = %#....... ; on an unmodified c128, there is no ram bank 2 (0 will be used instead) + mmu_CR_RAMBANK_3 = %##...... ; on an unmodified c128, there is no ram bank 3 (1 will be used instead) + + mmu_CR_HIGH_MASK = %..##.... ; this controls the "high area" (c000..ffff), but i/o (d000..dfff) is separate +; mmu_CR_HIGH_SYSROM = %........ ; editor, charset (or i/o, see below), kernel + mmu_CR_HIGH_INTFUNCROM = %...#.... + mmu_CR_HIGH_EXTFUNCROM = %..#..... + mmu_CR_HIGH_RAM = %..##.... + + mmu_CR_MID_MASK = %....##.. ; this controls the "middle area" (8000..bfff) +; mmu_CR_MID_SYSROM = %........ ; this is the upper half of basic + mmu_CR_MID_INTFUNCROM = %.....#.. + mmu_CR_MID_EXTFUNCROM = %....#... + mmu_CR_MID_RAM = %....##.. + + mmu_CR_LOW_MASK = %......#. ; this controls the "low area" (4000..7fff) +; mmu_CR_LOW_SYSROM = %........ ; this is the lower half of basic + mmu_CR_LOW_RAM = %......#. + + mmu_CR_IO_MASK = %.......# ; this controls i/o space (d000..dfff) +; mmu_CR_IO_ON = %........ + mmu_CR_IO_OFF = %.......# ; if i/o is off, contents depend on "high area" + + ; configuration register values used by C128 firmware (lookup table at $f7f0, see end of file): + mmu_CR_BANK0 = $3f ; full 64 KiB ram bank 0 + mmu_CR_BANK1 = $7f ; full 64 KiB ram bank 1 + mmu_CR_BANK2 = $bf ; full 64 KiB ram bank 2 + mmu_CR_BANK3 = $ff ; full 64 KiB ram bank 3 + mmu_CR_BANK4 = $16 ; 32 KiB bank 0; 32 KiB IFROM with i/o overlay + mmu_CR_BANK5 = $56 ; 32 KiB bank 1; 32 KiB IFROM with i/o overlay + mmu_CR_BANK6 = $96 ; 32 KiB bank 2; 32 KiB IFROM with i/o overlay + mmu_CR_BANK7 = $d6 ; 32 KiB bank 3; 32 KiB IFROM with i/o overlay + mmu_CR_BANK8 = $2a ; 32 KiB bank 0; 32 KiB EFROM with i/o overlay + mmu_CR_BANK9 = $6a ; 32 KiB bank 1; 32 KiB EFROM with i/o overlay + mmu_CR_BANK10 = $aa ; 32 KiB bank 2; 32 KiB EFROM with i/o overlay + mmu_CR_BANK11 = $ea ; 32 KiB bank 3; 32 KiB EFROM with i/o overlay + mmu_CR_BANK12 = $06 ; 32 KiB bank 0; 16 KiB IFROM; 16 KiB kernel with i/o overlay + mmu_CR_BANK13 = $0a ; 32 KiB bank 0; 16 KiB EFROM; 16 KiB kernel with i/o overlay + mmu_CR_BANK14 = $01 ; 16 KiB bank 0; 32 KiB basic; 16 KiB kernel with font overlay + mmu_CR_BANK15 = $00 ; 16 KiB bank 0; 32 KiB basic; 16 KiB kernel with i/o overlay + ; An unmodified C128 does not have a "ram bank 2" or "ram bank 3". + ; Whenever one of these is activated, ram banks 0 and 1 will be used instead. + ; IFROM means internal function ROM (socket U36) + ; EFROM means external function ROM (socket in a REU, for example) + +; mode configuration register mmu_mcr = $d505 + ; contents: + mmu_MCR_40COLUMNS = %#....... ; 40/80 key: 0 means pressed, 1 means released (writable! if cleared, will always read as 0!) + mmu_MCR_C64MODE = %.#...... ; setting this bit makes the MMU disappear from the memory map :) + mmu_MCR_EXROM = %..#..... ; if zero on boot, system will enter c64 mode (writable!) + mmu_MCR_GAME = %...#.... ; if zero on boot, system will enter c64 mode (writable!) + mmu_MCR_FSDIR_OUTPUT = %....#... ; direction of fast serial bus + mmu_MCR_UNUSED = %.....##. ; always set + mmu_MCR_8502MODE = %.......# ; setting this to zero switches to Z80 cpu + +; ram configuration register mmu_rcr = $d506 -mmu_p0l = $d507 -mmu_p0h = $d508 -mmu_p1l = $d509 -mmu_p1h = $d50a -mmu_vr = $d50b + ; contents: + mmu_RCR_VICBANK_MASK = %##...... ; this controls which RAM bank is "seen" by VIC +; mmu_RCR_VICBANK_0 = %........ + mmu_RCR_VICBANK_1 = %.#...... + mmu_RCR_VICBANK_2 = %#....... ; on an unmodified c128, there is no ram bank 2 (0 will be used instead) + mmu_RCR_VICBANK_3 = %##...... ; on an unmodified c128, there is no ram bank 3 (1 will be used instead) + + mmu_RCR_RAMBLOCK_MASK = %..##.... ; on an unmodified c128, these bits are irrelevant (they select 256 KiB of 1 MiB of memory) +; mmu_RCR_RAMBLOCK_0 = %........ + mmu_RCR_RAMBLOCK_1 = %...#.... ; on an unmodified c128, there is only ram block 0 + mmu_RCR_RAMBLOCK_2 = %..#..... ; on an unmodified c128, there is only ram block 0 + mmu_RCR_RAMBLOCK_3 = %..##.... ; on an unmodified c128, there is only ram block 0 + + mmu_RCR_SHARE_MASK = %....##.. +; mmu_RCR_SHARE_NONE = %........ + mmu_RCR_SHARE_BOTTOM = %.....#.. ; system default + mmu_RCR_SHARE_TOP = %....#... + + mmu_RCR_SHARESIZE_MASK = %......## +; mmu_RCR_SHARESIZE_1K = %........ ; system default + mmu_RCR_SHARESIZE_4K = %.......# + mmu_RCR_SHARESIZE_8K = %......#. + mmu_RCR_SHARESIZE_16K = %......## + +; page pointers. writes to "high" register will be latched (reading gives old value) until "low" register is written to +mmu_p0low = $d507 ; page 0 pointer low (a8..a15), default $00 +mmu_p0high = $d508 ; page 0 pointer high (a16..a19), default $00 (on an unmodified c128, only bit0 is meaningful) +mmu_p1low = $d509 ; page 1 pointer low (a8..a15), default $01 +mmu_p1high = $d50a ; page 1 pointer high (a16..a19), default $00 (on an unmodified c128, only bit0 is meaningful) + mmu_PxH_UNUSED = %####.... ; always set + + mmu_PxH_RAMBLOCK_MASK = %....##.. +; mmu_PxH_RAMBLOCK_0 = %........ + mmu_PxH_RAMBLOCK_1 = %.....#.. ; on an unmodified c128, there is only ram block 0 + mmu_PxH_RAMBLOCK_2 = %....#... ; on an unmodified c128, there is only ram block 0 + mmu_PxH_RAMBLOCK_3 = %....##.. ; on an unmodified c128, there is only ram block 0 + + mmu_PxH_RAMBANK_MASK = %......## +; mmu_PxH_RAMBANK_0 = %........ + mmu_PxH_RAMBANK_1 = %.......# + mmu_PxH_RAMBANK_2 = %......#. ; on an unmodified c128, there is no ram bank 2 (0 will be used instead) + mmu_PxH_RAMBANK_3 = %......## ; on an unmodified c128, there is no ram bank 3 (1 will be used instead) + +; version register +mmu_vr = $d50b ; read-only, value is $20 + mmu_VR_BANKS_MASK = %####.... ; 2 ram banks + mmu_VR_VERSION_MASK = %....#### ; mmu version 0 +; reading addresses up until $d5ff returns $ff + + +; these registers are always available (in *every* memory configuration) unless C64 mode is entered: + +; configuration register +mmu_cr = $ff00 ; always use this instead of $d500 +; load configuration registers: +; a read access will return the value of the corresponding preconfiguration register +; any write access will copy the value of the corresponding preconfiguration register to mmu_cr +mmu_lcr_a = $ff01 ; c128 kernel default is $3f (BANK 0) +mmu_lcr_b = $ff02 ; c128 kernel default is $7f (BANK 1) +mmu_lcr_c = $ff03 ; c128 kernel default is $01 (BANK 14) +mmu_lcr_d = $ff04 ; c128 kernel default is $41 (all system roms, with ram 1) + +; the c128 ROMs contain a look-up table to convert bank numbers to their +; corresponding configuration register values: +; romc_* needs "high rom area" enabled ($c000..$ffff) +romc_bank_to_cr_table = $f7f0 ; 3f 7f bf ff 16 56 96 d6 2a 6a aa ea 06 0a 01 00 diff --git a/ACME_Lib/cbm/c128/vdc.a b/ACME_Lib/cbm/c128/vdc.a index 42529ed..c8d3f67 100644 --- a/ACME_Lib/cbm/c128/vdc.a +++ b/ACME_Lib/cbm/c128/vdc.a @@ -154,3 +154,12 @@ vdcr_enable_start = $22 ; column to enable display in vdcr_enable_end = $23 ; column to disable display in vdcr_dram_refresh = $24 ; RAM refresh rate vdcr_sync_polarity = $25 ; only in type 2 VDCs + +; the c128 ROMs contain look-up tables to convert vic color values to vdc color +; values and vice-versa: +; rom4_* needs "low rom area" enabled ($4000..$7fff) +; rom8_* needs "middle rom area" enabled ($8000..$bfff) +; romc_* needs "high rom area" enabled ($c000..$ffff) +rom4_vic_to_vdc_color_table = $6a4c ; 00 0f 08 07 0b 04 02 0d 0a 0c 09 06 01 05 03 0e +rom8_vdc_to_vic_color_table = $81f3 ; 00 0c 06 0e 05 0d 0b 03 02 0a 08 04 09 07 0f 01 +romc_vic_to_vdc_color_table = $ce5c ; 00 0f 08 07 0b 04 02 0d 0a 0c 09 06 01 05 03 0e diff --git a/ACME_Lib/cbm/c128/vic.a b/ACME_Lib/cbm/c128/vic.a index 820eb90..4353abf 100644 --- a/ACME_Lib/cbm/c128/vic.a +++ b/ACME_Lib/cbm/c128/vic.a @@ -8,3 +8,10 @@ lib_cbm_c128_vic_a = 1 ; registers only present in the C128 variant of this chip: vic_keyboard = $d02f vic_clock = $d030 + +; the c128 ROMs contain two copies of a look-up table to convert vic color +; values to their corresponding petscii color codes: +; rom4_* needs "low rom area" enabled ($4000..$7fff) +; romc_* needs "high rom area" enabled ($c000..$ffff) +rom4_vic_to_petscii_color_table = $76b5 ; 90 05 1c 9f 9c 1e 1f 9e 81 95 96 97 98 99 9a 9b +romc_vic_to_petscii_color_table = $ce4c ; 90 05 1c 9f 9c 1e 1f 9e 81 95 96 97 98 99 9a 9b diff --git a/ACME_Lib/cbm/c64/georam.a b/ACME_Lib/cbm/c64/georam.a new file mode 100644 index 0000000..4068fba --- /dev/null +++ b/ACME_Lib/cbm/c64/georam.a @@ -0,0 +1,33 @@ +;ACME 0.94.4 + +!ifdef lib_cbm_c64_georam_a !eof +lib_cbm_c64_georam_a = 1 + +; This file contains definitions for accessing the "GeoRAM" RAM expansion and +; its clones (BBG, BBU, NeoRAM, ...) +; These units allow access to a single page of memory (256 bytes) visible at +; address $de00 in i/o space. Writing to registers allows to change which +; memory page is visible at that location. + +; memory page +georam_page = $de00 + +; control registers (write-only, these registers can not be read) +georam_track = $dffe ; 0..63, i.e. the lower six bits are significant +georam_sector = $dfff ; 0..31, i.e. the lower five bits are significant +; these are the official addresses - actually the registers are accessible +; *everywhere* at $dfxx, but using these locations does not clash with the +; registers of a Commodore REU. + +; Upgraded units and clones may have more memory, in those cases the registers +; will have more significant bits. + +; I could have called the registers "row" and "column" instead of track and +; sector, but the fact that this device was designed with one six-bit register +; and one five-bit register (instead of one eight-bit register and one +; three-bit register) tells me that this was meant as an easily programmable +; RAM disk: A 1541 disk has 35 tracks with (at most) 21 sectors. Numbers in +; these ranges can be written to the GeoRAM registers without the need to +; shift bits around. +; Knowing this is a handy way of remembering the number of significant bits of +; GeoRAM registers. diff --git a/ACME_Lib/cbm/c64/reu.a b/ACME_Lib/cbm/c64/reu.a new file mode 100644 index 0000000..c86261c --- /dev/null +++ b/ACME_Lib/cbm/c64/reu.a @@ -0,0 +1,55 @@ +;ACME 0.94.4 + +!ifdef lib_cbm_c64_reu_a !eof +lib_cbm_c64_reu_a = 1 + +; This file contains definitions for accessing a RAM Expansion Unit (REU) of +; type 1700, 1764, 1750 and compatible. These units contain a chip called REC +; (RAM Expansion Controller) capable of direct memory access (DMA). +; Standard base address of control registers is $df00 in i/o space. + +; status register +rec_status = $df00 ; reading will clear IRQ, END and ERROR bits + rec_STATUS_IRQ = %#....... + rec_STATUS_END = %.#...... + rec_STATUS_ERROR = %..#..... ; for verify command + rec_STATUS_TYPE = %...#.... ; chip type (do not use to determine unit size!) + rec_STATUS_VERSION = %....#### +; command register +rec_command = $df01 + rec_COMMAND_EXECUTE = %#....... + ;reserved = %.#...... + rec_COMMAND_RELOAD = %..#..... + rec_COMMAND_IMMEDIATELY = %...#.... ; do not wait for $ff00 write + ;reserved = %....##.. + rec_COMMAND_MODE_MASK = %......## ; bit mask for the four modes + rec_COMMAND_MODE_STASH = %........ ; computer-to-REU + rec_COMMAND_MODE_FETCH = %.......# ; REU-to-computer + rec_COMMAND_MODE_SWAP = %......#. ; exchange + rec_COMMAND_MODE_VERIFY = %......## ; compare + rec_COMMAND_STASH = %#.#..... ; these wait for $ff00 before + rec_COMMAND_FETCH = %#.#....# ; starting and then reload values. +; internal address (computer RAM) +rec_int_low = $df02 +rec_int_high = $df03 +; external address (expansion RAM) +rec_ext_low = $df04 +rec_ext_high = $df05 +rec_ext_bank = $df06 + ; A stock 1700 unit has two banks (128 KiB). + ; A stock 1764 unit has four banks (256 KiB). + ; A stock 1750 unit has eight banks (512 KiB). + ; Upgraded units and clones may have more, but the REC chip will always + ; "wrap around" after eight banks if crossing bank borders! +; amount of bytes to process +rec_amount_low = $df07 +rec_amount_high = $df08 +; when to request interrupts +rec_irqctrl = $df09 + rec_IRQCTRL_ENABLE = %#....... + rec_IRQCTRL_ON_END = %.#...... + rec_IRQCTRL_ON_ERROR = %..#..... ; for verify errors +; address control (set to zero for normal operation) +rec_addrctrl = $df0a + rec_ADDRCTRL_FIX_INT = %#....... + rec_ADDRCTRL_FIX_EXT = %.#......