base:memmanage
no way to compare when less than two revisions
Differences
This shows you the differences between two versions of the page.
— | base:memmanage [2015-04-17 04:32] (current) – created - external edit 127.0.0.1 | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== Memory Management ====== | ||
+ | |||
+ | ===== The processor' | ||
+ | |||
+ | The Commodore 64 has access to more memory than its processor can directly handle. This is possible by banking the memory. There are five user configurable inputs that affect the banking. Three of them can be controlled by program, and the rest two serve as control lines on the memory expansion port. | ||
+ | |||
+ | The 6510 MPU has an integrated I/O port with six I/O lines. This port is accessed through the memory locations 0 and 1. The location 0 is the Data Direction Register for the Peripheral data Register, which is mapped to the other location. When a bit in the DDR is set, the corresponding PR bit controls the state of a corresponding Peripheral line as an output. When it is clear, the state of the Peripheral line is reflected by the Peripheral register. The Peripheral lines are numbered from 0 to 5, and they are mapped to the DDR and PR bits 0 - 5, respectively. The 8502 processor, which is used in the Commodore 128, has seven Peripheral lines in its I/O port. The pin P6 is connected to the ASC/CC key (Caps lock in English versions). | ||
+ | |||
+ | < | ||
+ | The I/O lines have the following functions: | ||
+ | |||
+ | | ||
+ | | ||
+ | out P5 | ||
+ | in | ||
+ | out P3 | ||
+ | out P2 | ||
+ | out P1 HIRAM | ||
+ | out P0 LORAM | ||
+ | </ | ||
+ | |||
+ | The default value of the DDR register is $2F, so all lines except Cassette sense are outputs. The default PR value is $37 (Datassette motor stopped, and all three memory management lines high). If you turn any memory management line to input, the external pull-up resistors make it to look like it is outputting logical " | ||
+ | |||
+ | The two remaining memory management lines are -EXROM and -GAME on the cartridge port. Each line has a pull-up resistor, so the lines are " | ||
+ | |||
+ | Even though the memory banking has been implemented with a 82S100 Programmable _Logic_ Array, there is only one control line that seems to behave logically at first sight, the -CHAREN line. It is mostly used to choose between I/O address space and the character generator ROM. The following memory map introduces the oddities of -CHAREN and the other memory management lines. It is based on the memory maps in the Commodore 64 Programmer' | ||
+ | |||
+ | The leftmost column of the table contains addresses in hexadecimal notation. The columns aside it introduce all possible memory configurations. The default mode is on the left, and the absolutely most rarely used Ultimax game console configuration is on the right. (Has anybody ever seen any Ultimax games?) Each memory configuration column has one or more four-digit binary numbers as a title. The bits, from left to right, represent the state of the -LORAM, -HIRAM, -GAME and -EXROM lines, respectively. The bits whose state does not matter are marked with " | ||
+ | |||
+ | < | ||
+ | default | ||
+ | | ||
+ | 10000 | ||
+ | ---------------------------------------------------------------------- | ||
+ | F000 | ||
+ | | ||
+ | E000 | ||
+ | ---------------------------------------------------------------------- | ||
+ | | ||
+ | ---------------------------------------------------------------------- | ||
+ | | ||
+ | ---------------------------------------------------------------------- | ||
+ | B000 | ||
+ | | ||
+ | A000 | ||
+ | ---------------------------------------------------------------------- | ||
+ | 9000 | ||
+ | | ||
+ | 8000 | ||
+ | ---------------------------------------------------------------------- | ||
+ | 7000 | ||
+ | |||
+ | 6000 | ||
+ | | ||
+ | 5000 | ||
+ | |||
+ | 4000 | ||
+ | ---------------------------------------------------------------------- | ||
+ | 3000 | ||
+ | |||
+ | | ||
+ | |||
+ | 1000 | ||
+ | ---------------------------------------------------------------------- | ||
+ | | ||
+ | ---------------------------------------------------------------------- | ||
+ | |||
+ | *) Internal memory does not respond to write accesses to these | ||
+ | | ||
+ | </ | ||
+ | |||
+ | < | ||
+ | Legend: Kernal | ||
+ | |||
+ | IO/C D000-DFFF | ||
+ | generator ROM, selected by | ||
+ | -CHAREN. If the CHAREN bit is | ||
+ | clear, the character generator | ||
+ | ROM will be selected. If it is | ||
+ | set, the I/O chips are | ||
+ | accessible. | ||
+ | |||
+ | IO/ | ||
+ | selected by -CHAREN. If the | ||
+ | CHAREN bit is clear, the | ||
+ | character generator ROM will | ||
+ | be selected. If it is set, the | ||
+ | internal RAM is accessible. | ||
+ | |||
+ | I/O | ||
+ | The -CHAREN line has no effect. | ||
+ | |||
+ | BASIC | ||
+ | |||
+ | ROMH A000-BFFF or External ROM with the -ROMH line | ||
+ | E000-FFFF | ||
+ | |||
+ | ROML 8000-9FFF | ||
+ | connected to its -CS line. | ||
+ | |||
+ | RAM | ||
+ | |||
+ | - | ||
+ | A000-CFFF | ||
+ | do not detect any memory accesses | ||
+ | to this area except the VIC-II' | ||
+ | DMA and memory refreshes. | ||
+ | |||
+ | NOTE: | ||
+ | (Kernal, BASIC, CHAROM, ROML, ROMH), the data will get | ||
+ | " | ||
+ | |||
+ | For this reason, you can easily copy data from ROM to RAM, | ||
+ | without any bank switching. But implementing external | ||
+ | memory expansions without DMA is very hard, as you have to | ||
+ | use a 256 byte window on the I/O1 or I/O2 area, like | ||
+ | GEORAM, or the Ultimax memory configuration, | ||
+ | want the data to be written both to internal and external | ||
+ | RAM. | ||
+ | |||
+ | However, this is not true for the Ultimax video game | ||
+ | configuration. In that mode, the internal RAM ignores all | ||
+ | memory accesses outside the area $0000-$0FFF, | ||
+ | are performed by the VIC, and you can write to external | ||
+ | memory at $1000-$CFFF and $E000-$FFFF, | ||
+ | changing the contents of the internal RAM. | ||
+ | </ | ||
+ | |||
+ | ===== A note concerning the I/O area ===== | ||
+ | |||
+ | < | ||
+ | The I/O area of the Commodore 64 is divided as follows: | ||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | </ | ||
+ | |||
+ | As you can see, the address ranges for the chips are much larger than required. Because of this, you can access the chips through multiple memory areas. The VIC-II appears in its window every $40 addresses. For instance, the addresses $D040 and $D080 are both mapped to the Sprite 0 X co-ordinate register. The SID has one register selection line less, thus it appears at every $20 bytes. The CIA chips have only 16 registers, so there are 16 copies of each in their memory area. | ||
+ | |||
+ | However, you should not use other addresses than those specified by Commodore. For instance, the Commodore 128 mapped its additional I/O chips to this same memory area, and the SID responds only to the addresses D400-D4FF, also when in C64 mode. And the Commodore 65, or the C64DX, which unfortunately did not make its way to the market, could narrow the memory window reserved for its CSG 4567 VIC-III. | ||
+ | |||
+ | ===== The video chip ===== | ||
+ | |||
+ | The MOS 6567/6569 VIC-II Video Interface Controller has access to only 16 kilobytes at a time. To enable the VIC-II to access the whole 64 kB memory space, the main memory is divided to four banks of 16 kB each. The lines PA0 and PA1 of the second CIA are the inverse of the virtual VIC-II address lines VA14 and VA15, respectively. To select a VIC-II bank other than the default, you must program the CIA lines to output the desired bit pair. For instance, the following code selects the memory area $4000-$7FFF (bank 1) for the video controller: | ||
+ | |||
+ | < | ||
+ | LDA $DD02 ; Data Direction Register A | ||
+ | ORA #$03 ; Set pins PA0 and PA1 to outputs | ||
+ | STA $DD02 | ||
+ | LDA $DD00 | ||
+ | AND #$FC ; Mask the lowmost bit pair off | ||
+ | ORA #$02 ; Select VIC-II bank 1 (the inverse of binary 01 is 10) | ||
+ | STA $DD00 | ||
+ | </ | ||
+ | |||
+ | Why should you set the pins to outputs? Hardware RESET resets all I/O lines to inputs, and thanks to the CIA's internal pull-up resistors, the inputs actually output logical high voltage level. So, upon -RESET, the video bank 0 is selected automatically, | ||
+ | |||
+ | Note that the VIC-II always fetches its information from the internal RAM, totally ignoring the memory configuration lines. There is only one exception to this rule: The character generator ROM. Unless the Ultimax mode is selected, VIC-II " | ||
+ | |||
+ | ===== Accessing the memory places 0 and 1 ===== | ||
+ | |||
+ | Although the addresses 0 and 1 of the processor are hard-wired to its on-chip I/O port registers, you can access the memory places 0 and 1. The video chip always reads from RAM (or character generator ROM), so you can use it to read also from 0 and 1. Enable the bit-map screen and set the start address of the graphics screen to 0. Now you can see these two memory locations in the upper left corner. Alternatively, | ||
+ | |||
+ | But how can you write to these locations? If you execute the command POKE 53265,59, you will see that the memory place 1 changes its value wildly. If you disable the interrupts (POKE53664, | ||
+ | |||
+ | On the C128 in its 2 MHz mode, you can write to the memory places with an easier kludge. Just make sure that the video chip is not performing the memory refresh (as it would slow down to 1 MHz in that case), and use some instruction that reads from a proper memory location before writing to 0 or 1. Indexed zero-page addressing modes are good for it. I tested this trick with LDX#1 followed by STA $FF,X. As you can read from the instruction timing section of this document, the instruction first reads from $FF (the base address) and then writes to 0. The timing can be done with a simple LDA$D012: | ||
+ | |||
+ | You can also read the memory places 0 and 1 much faster than with sprite collisions. Just make the video chip to read from 0 or 1, and then read from non-connected address space ($DE00-$DFFF on a stock C64; also $D700-$D7FF on C128' | ||
+ | |||
+ | These tricks unfortunately do not work reliably on all units. So far I have had the opportunity to try it on three computers, two of which were Commodore 128 DCR's (C128' | ||
+ | |||
base/memmanage.txt · Last modified: 2015-04-17 04:32 by 127.0.0.1