trunk/src/mess/machine/ti99/mapper8.c
| r26590 | r26591 | |
| 14 | 14 | |
| 15 | 15 | Note: The TI-99/8's internal codename was "Armadillo" |
| 16 | 16 | |
| 17 | ============================== |
| 18 | Mapper (codename "Amigo") |
| 19 | ============================== |
| 20 | |
| 17 | 21 | Initial setting of mapper (as defined in the power-up routine, TI-99/4A mode) |
| 18 | 22 | |
| 19 | 23 | 0 00ff0000 -> Unmapped; logical address 0000...0fff = ROM0 |
| r26590 | r26591 | |
| 33 | 37 | E 00006800 -> DRAM; e000 = 006800, efff = 0077ff |
| 34 | 38 | F 00007800 -> DRAM; f000 = 007800, ffff = 0087ff |
| 35 | 39 | |
| 36 | | Informations taken from |
| 37 | | [1] ARMADILLO PRODUCT SPECIFICATIONS |
| 38 | | [2] TI-99/8 Graphics Programming Language interpreter |
| 39 | | |
| 40 | 40 | Format of map table entry (not emulated) |
| 41 | 41 | |
| 42 | | * bit 0: WTPROT: page is write protected if 1 |
| 43 | | * bit 1: XPROT: page is execute protected if 1 |
| 44 | | * bit 2: RDPROT: page is read protected if 1 |
| 45 | | * bit 3: reserved, value is ignored |
| 46 | | * bits 4-7: reserved, always forced to 0 |
| 47 | | * bits 8-23: page base address in 24-bit virtual address space |
| 42 | +------+------+------+------+---+---+---+---------+----------+---------+ |
| 43 | | WProt| XProt| RProt| * | 0 | 0 | 0 | Upper | High | Low | |
| 44 | +------+------+------+------+---+---+---+---------+----------+---------+ |
| 48 | 45 | |
| 49 | | Format of mapper control register: |
| 50 | | * bit 0-4: unused??? |
| 51 | | * bit 5-6: map file to load/save (0 for file 0, 1 for file 1, etc.) |
| 52 | | * bit 7: 0 -> load map file from RAM, 1 -> save map file to RAM |
| 46 | WProt: Write protection if set to 1 |
| 47 | XProt: Execute protection if set to 1 |
| 48 | RProt: Read protection if set to 1 |
| 53 | 49 | |
| 54 | | Format of mapper status register (cleared by read): |
| 55 | | * bit 0: WPE - Write-Protect Error |
| 56 | | * bit 1: XCE - eXeCute Error |
| 57 | | * bit 2: RPE - Read-Protect Error |
| 58 | | * bits 3-7: unused??? |
| 50 | When a protection violation occurs, the tms9901 INT1* pin is pulled low |
| 51 | (active). The pin remains low until the mapper status register is read. |
| 59 | 52 | |
| 60 | | Memory error interrupts are enabled by setting WTPROT/XPROT/RDPROT. When |
| 61 | | an error occurs, the tms9901 INT1* pin is pulled low (active). The pin |
| 62 | | remains low until the mapper status register is read. |
| 53 | Address handling |
| 54 | ---------------- |
| 55 | Physical address is (Upper * 2^16) + (High * 2^8) + Low |
| 63 | 56 | |
| 64 | | 24-bit address map: |
| 65 | | * >000000->00ffff: console RAM |
| 66 | | * >010000->feffff: expansion? |
| 67 | | * >ff0000->ff0fff: empty??? |
| 68 | | * >ff1000->ff3fff: unused??? |
| 69 | | * >ff4000->ff5fff: DSR space |
| 70 | | * >ff6000->ff7fff: cartridge space |
| 71 | | * >ff8000->ff9fff(???): >4000 ROM (normally enabled with a write to CRU >2700) |
| 72 | | * >ffa000->ffbfff(?): >2000 ROM |
| 73 | | * >ffc000->ffdfff(?): >6000 ROM |
| 57 | The mapper calculates the actual physical address by looking up the |
| 58 | table entry from the first four bits of the logical address and then |
| 59 | *adding* the remaining 12 bits of the logical address on the map value. |
| 74 | 60 | |
| 61 | The value 0xff0000 is used to indicate a non-mapped area. |
| 75 | 62 | |
| 76 | | CRU map: |
| 77 | | Since the tms9995 supports full 15-bit CRU addresses, the >1000->17ff |
| 78 | | (>2000->2fff) range was assigned to support up to 16 extra expansion slot. |
| 79 | | The good thing with using >1000->17ff is the fact that older expansion |
| 80 | | cards that only decode 12 address bits will think that addresses |
| 81 | | >1000->17ff refer to internal TI99 peripherals (>000->7ff range), which |
| 82 | | suppresses any risk of bus contention. |
| 83 | | * >0000->001f (>0000->003e): tms9901 |
| 84 | | - P4: 1 -> MMD (Memory Mapped Devices?) at >8000, ROM enabled |
| 85 | | - P5: 1 -> no P-CODE GROMs |
| 86 | | * >0800->17ff (>1000->2ffe): Peripheral CRU space |
| 87 | | * >1380->13ff (>2700->27fe): Internal DSR, with two output bits: |
| 88 | | - >2700: Internal DSR select (parts of Basic and various utilities) |
| 89 | | - >2702: SBO -> hardware reset |
| 63 | Mapper control register |
| 64 | ----------------------- |
| 65 | The mapper control register is used to initiate a map load/save operation. |
| 90 | 66 | |
| 67 | +---+---+---+---+---+---+---+---+ |
| 68 | | 0 | 0 | 0 | 0 | Map File | RW| |
| 69 | +---+---+---+---+---+---+---+---+ |
| 91 | 70 | |
| 92 | | Memory map (TMS9901 P4 == 1): |
| 93 | | When TMS9901 P4 output is set, locations >8000->9fff are ignored by mapper. |
| 94 | | * >8000->83ff: SRAM (>8000->80ff is used by the mapper DMA controller |
| 95 | | to hold four map files) (r/w) |
| 96 | | * >8400: sound port (w) |
| 97 | | * >8410->87ff: SRAM (r/w) |
| 98 | | * >8800: VDP data read port (r) |
| 99 | | * >8802: VDP status read port (r) |
| 100 | | * >8810: memory mapper status and control registers (r/w) |
| 101 | | * >8c00: VDP data write port (w) |
| 102 | | * >8c02: VDP address and register write port (w) |
| 103 | | * >9000: speech synthesizer read port (r) |
| 104 | | * >9400: speech synthesizer write port (w) |
| 105 | | * >9800 GPL data read port (r) |
| 106 | | * >9802 GPL address read port (r) |
| 107 | | * >9c00 GPL data write port -- unused (w) |
| 108 | | * >9c02 GPL address write port (w) |
| 71 | The map file is a number from 0-7 indicating the set of map values for the |
| 72 | operation, which means the location in SRAM where the next 64 values are |
| 73 | loaded from or stored into. |
| 109 | 74 | |
| 75 | RW = 1: load from SRAM into mapper |
| 76 | RW = 0: store from mapper into SRAM |
| 110 | 77 | |
| 111 | | Memory map (TMS9901 P5 == 0): |
| 112 | | When TMS9901 P5 output is cleared, locations >f840->f8ff(?) are ignored by |
| 113 | | mapper. |
| 114 | | * >f840: data port for P-code grom library 0 (r?) |
| 115 | | * >f850: data port for P-code grom library 1 (r?) |
| 116 | | * >f860: data port for P-code grom library 2 (r?) |
| 117 | | * >f842: address port for P-code grom library 0 (r/w?) |
| 118 | | * >f852: address port for P-code grom library 1 (r/w?) |
| 119 | | * >f862: address port for P-code grom library 2 (r/w?) |
| 78 | When read, the mapper register returns the violation flags: |
| 79 | +------+------+------+---+---+---+---+---+ |
| 80 | | WProt| XProt| RProt| 0 | 0 | 0 | 0 | 0 | |
| 81 | +------+------+------+---+---+---+---+---+ |
| 120 | 82 | |
| 83 | Logical address space (LAS) |
| 84 | =========================== |
| 85 | The LAS is the address space as seen by the TMS 9995 CPU. It is 64 KiB large. |
| 86 | The LAS can be configured in two ways: |
| 87 | - the native (99/8) mode |
| 88 | - and the compatibility mode (99/4A) |
| 89 | |
| 90 | Both modes are selected by CRU bit 20 on base 0000 (named "CRUS"). |
| 91 | |
| 92 | The console starts up in compatibility mode. |
| 93 | |
| 94 | The compatibility mode organizes the LAS in a similar way as the TI-99/4A. |
| 95 | This means that machine language programs should run with no or only minor |
| 96 | changes. In particular, game cartridges work without problems. |
| 97 | |
| 98 | The native mode rearranges the address space and puts memory-mapped devices |
| 99 | to other positions. |
| 100 | |
| 101 | TI-99/4A compatibility mode (CRUS=1) |
| 102 | ------------------------------------ |
| 103 | 0000-1fff: 2 KiB ROM0 |
| 104 | 2000-7fff: Free area |
| 105 | 8000-87ff: 2 KiB SRAM |
| 106 | 8000-81ff: mapper files (8 files with 16*4 bytes each) |
| 107 | 8200-82ff: Free RAM |
| 108 | 8300-83ff: Scratch-pad RAM as in the 99/4A |
| 109 | 8400-840f: Sound chip |
| 110 | 8800-880f: VDP read port (data, status) |
| 111 | 8810-881f: Mapper access port |
| 112 | 8820-8bff: Free area |
| 113 | 8c00-8c0f: VDP write port (data, address) |
| 114 | 8c10-8fff: Free area |
| 115 | 9000-900f: Speech synthesizer read (on-board) |
| 116 | 9010-93ff: Free area |
| 117 | 9400-940f: Speech synthesizer write (on-board) |
| 118 | 9410-97ff: Free area |
| 119 | 9800-980f: System GROM read (data, address) |
| 120 | 9810-9bff: Free area |
| 121 | 9c00-9c0f: System GROM write (data, address) |
| 122 | 9c10-fffb: Free area |
| 123 | fffc-ffff: NMI vector |
| 124 | |
| 125 | TI-99/8 native mode (CRUS=0) |
| 126 | ---------------------------- |
| 127 | 0000-efff: Free area |
| 128 | f000-f7ff: 2 KiB SRAM |
| 129 | f000-f1ff: mapper files (8 files with 16*4 bytes each) |
| 130 | f200-f7ff: Free RAM |
| 131 | f800-f80f: Sound chip |
| 132 | f810-f81f: VDP read (data, status) and write (data, address) |
| 133 | f820-f82f: Speech synthesizer read/write |
| 134 | f830-f83f: System GROM read/write |
| 135 | f840-f86f: Free area |
| 136 | f870-f87f: Mapper access port |
| 137 | f880-fffb: Free area |
| 138 | fffc-ffff: NMI vector |
| 139 | |
| 140 | Note that ROM0 is not visible in the native mode. |
| 141 | |
| 142 | If CRU bit 21 (PTGEN*) is set to 0, Pascal GROMs appear in the LAS in either |
| 143 | mode. It is highly recommended to use native mode when turning on these |
| 144 | GROMs, because the area where they appear may be occupied by a program in |
| 145 | 99/4A mode. |
| 146 | |
| 147 | Pascal and Text-to-speech GROM enabled (PTGEN*=0) |
| 148 | ------------------------------------------------- |
| 149 | f840-f84f: Text-to-speech GROM read/write |
| 150 | f850-f85f: P-Code library #1 GROM read/write |
| 151 | f860-f86f: P-Code library #2 GROM read/write |
| 152 | |
| 153 | Physical address space (PAS) |
| 154 | ============================ |
| 155 | The PAS is 24 bits wide and accessed via the custom mapper chip nicknamed |
| 156 | "Amigo". The mapper exchanges map definitions with SRAM (see LAS). That |
| 157 | means, a map can be prepared in SRAM, and for activating it, the mapper |
| 158 | is accessed on its port, telling it to load or save a map. |
| 159 | |
| 160 | 000000-00ffff: 64 KiB console DRAM |
| 161 | 010000-efffff: undefined |
| 162 | f00000-f03fff: P-Code ROM (not mentioned in [1]) |
| 163 | f04000-feffff: undefined |
| 164 | ff0000 : unmapped (code for mapper) |
| 165 | ff0001-ff3fff: undefined |
| 166 | ff4000-ff5fff: DSR ROM in Peripheral Box, Hexbus DSR (CRU 1700) or additional ROM (CRU 2700) |
| 167 | ff6000-ff9fff: Cartridge ROM space |
| 168 | ffa000-ffdfff: 16 KiB ROM1 |
| 169 | ffe000-ffe00f: Interrupt level sense |
| 170 | ffe010-ffffff: undefined |
| 171 | |
| 172 | |
| 173 | CRU map (I/O address space) |
| 174 | =========================== |
| 175 | 0000-003e: TMS9901 system interface (see ti99_8.c) |
| 176 | 1700-17fe: Hexbus |
| 177 | 2000-26fe: Future external devices |
| 178 | 2700-27fe: Additional ROM ("internal DSR") |
| 179 | 2702: System reset (when set to 1) |
| 180 | 2800-3ffe: Future external devices |
| 181 | 4000-fffe: Future external devices |
| 182 | |
| 183 | The TMS9995 offers the full 15-bit CRU address space. Devices designed for |
| 184 | the TI-99/4A should only be accessed in the area 1000-1ffe. They will (by |
| 185 | design) incompletely decode the CRU address and be mirrored in the higher areas. |
| 186 | |
| 121 | 187 | Michael Zapf, October 2010 |
| 122 | 188 | February 2012: Rewritten as class |
| 123 | 189 | |
| 190 | Informations taken from |
| 191 | [1] ARMADILLO PRODUCT SPECIFICATIONS |
| 192 | [2] TI-99/8 Graphics Programming Language interpreter |
| 193 | |
| 124 | 194 | ***************************************************************************/ |
| 125 | 195 | |
| 126 | 196 | #include "mapper8.h" |
| r26590 | r26591 | |
| 524 | 594 | *value = m_rom1[0x2000 | (pas_address & 0x1fff)]; |
| 525 | 595 | if (TRACE_MEM) LOG("mainboard_998: (ROM) %06x -> %02x\n", pas_address, *value); |
| 526 | 596 | break; |
| 597 | case MAP8_PCODE: |
| 598 | *value = m_pcode[pas_address & 0x3fff]; |
| 599 | if (TRACE_MEM) LOG("mainboard_998: (PCDOE) %06x -> %02x\n", pas_address, *value); |
| 600 | break; |
| 527 | 601 | case MAP8_INTS: |
| 528 | 602 | // Interrupt sense |
| 529 | 603 | LOG("mainboard_998: ILSENSE not implemented.\n"); |
| r26590 | r26591 | |
| 562 | 636 | case MAP8_ROM1C0: |
| 563 | 637 | if (TRACE_MEM) LOG("mainboard_998: (ROM1) %06x <- %02x (ignored)\n", pas_address, data); |
| 564 | 638 | break; |
| 639 | case MAP8_PCODE: |
| 640 | if (TRACE_MEM) LOG("mainboard_998: (PCODE) %06x <- %02x (ignored)\n", pas_address, data); |
| 641 | break; |
| 565 | 642 | case MAP8_INTS: |
| 566 | 643 | // Interrupt sense |
| 567 | 644 | LOG("ti99_8: write to ilsense ignored\n"); |
| r26590 | r26591 | |
| 609 | 686 | LOG("ti99_8: Starting mapper\n"); |
| 610 | 687 | |
| 611 | 688 | // String values of the pseudo constants, used in the configuration. |
| 612 | | const char *const pseudodev[6] = { SRAMNAME, ROM0NAME, ROM1A0NAME, ROM1C0NAME, DRAMNAME, INTSNAME }; |
| 689 | const char *const pseudodev[7] = { SRAMNAME, ROM0NAME, ROM1A0NAME, ROM1C0NAME, DRAMNAME, PCODENAME, INTSNAME }; |
| 613 | 690 | |
| 614 | 691 | const mapper8_config *conf = reinterpret_cast<const mapper8_config *>(static_config()); |
| 615 | 692 | |
| r26590 | r26591 | |
| 620 | 697 | m_dram = machine().root_device().memregion(DRAM_TAG)->base(); |
| 621 | 698 | m_rom0 = machine().root_device().memregion(ROM0_TAG)->base(); |
| 622 | 699 | m_rom1 = machine().root_device().memregion(ROM1_TAG)->base(); |
| 700 | m_pcode = machine().root_device().memregion(PCODEROM_TAG)->base(); |
| 623 | 701 | |
| 624 | 702 | // Clear the lists |
| 625 | 703 | m_logcomp.reset(); |
| r26590 | r26591 | |
| 641 | 719 | device_t *dev = NULL; |
| 642 | 720 | mapper8_device_kind kind = MAP8_UNDEF; |
| 643 | 721 | |
| 644 | | for (int j=1; (j < 7) && (kind == MAP8_UNDEF); j++) |
| 722 | for (int j=1; (j < 8) && (kind == MAP8_UNDEF); j++) |
| 645 | 723 | { |
| 646 | 724 | // Pseudo devices are enumerated as 1 ... 6 (see MAP8_SRAM etc.) |
| 647 | 725 | if (strcmp(entry[i].name, pseudodev[j-1])==0) kind = (mapper8_device_kind)j; |