1 // license:BSD-3-Clause
2 // copyright-holders:ElSemi
3
4 #include "emu.h"
5 #include "naomibd.h"
6
7 /*
8 Naomi ROM board info from ElSemi:
9
10 NAOMI_ROM_OFFSETH = 0x5f7000,
11 NAOMI_ROM_OFFSETL = 0x5f7004,
12 NAOMI_ROM_DATA = 0x5f7008,
13 NAOMI_DMA_OFFSETH = 0x5f700C,
14 NAOMI_DMA_OFFSETL = 0x5f7010,
15 NAOMI_DMA_COUNT = 0x5f7014,
16 NAOMI_COMM_OFFSET = 0x5F7050,
17 NAOMI_COMM_DATA = 0x5F7054,
18 NAOMI_BOARDID_WRITE = 0x5F7078,
19 NAOMI_BOARDID_READ = 0x5F707C,
20 each port is 16 bit wide, to access the rom in PIO mode, just set an offset in ROM_OFFSETH/L and read from ROM_DATA, each access reads 2 bytes and increases the offset by 2.
21
22 the BOARDID regs access the password protected eeprom in the game board. the main board eeprom is read through port 0x1F800030
23
24 To access the board using DMA, use the DMA_OFFSETL/H. DMA_COUNT is in units of 0x20 bytes. Then trigger a GDROM DMA request.
25
26 Cartridge protection info from Deunan Knute:
27
28 NAOMI cart can hold up to 512MB of data, so the highest bits are used for other, dark and scary purposes.
29 I call those bits "mode selector".
30
31 First it's important to note that DMA and PIO seem to have separate address counters, as well as separate mode selector registers.
32
33 * bit 31 (mode bit 3) is auto-advance bit
34 When set to one the address will be automatically incremented when data is read, so you need only set it once and can just keep polling
35 the PIO port. When zero it will stay on current address. Now this works exactly the same for DMA, and even if DMA engine is 32-byte
36 per block it will repeatedly read only the first 16-bit word.
37
38 * bit 30 (mode bit 2)
39 DMA_OFFSET: 0 = enable DMA (all cart types), enabled during trasfer only because there can be other devices which uses G1 bus DMA (comm.board, multiboard, etc)
40 ROM_OFFSET:
41 "M2" type carts: 1 = select decryption/decompression device registers or its RAM space
42 "M1" type carts: ???
43 "M4" type carts: 1 = enable data decryption, for both PIO and DMA.
44 is most often as special mode switch
45 DMA transfer with this bit set will hang. PIO will return semi-random data (floating bus?). So one function of that bit is "disable".
46 PIO read will return all ones if DMA mode has this bit cleared, so it seems you can do either PIO or DMA but not both at the same time.
47 In other words, disable DMA once before using PIO (most games using both access types do that when the DMA terminates).
48 This bit is also used to reset the chip's internal protection mechanism on "Oh! My Goddess" to a known state.
49
50 * bit 29 (mode bit 1)
51 "M2" type carts: DMA_OFFSET - no effect, ROM_OFFSET - ROM size/mapping select, 0 - 4MB ROM-mode, 1 - 8MB ROM mode. for both PIO and DMA
52 "M1" type carts: DMA_OFFSET 0 = enable decryptyon/decompression during DMA transfer, ROM_OFFSET - ROM size/mapping select similar to M2 cart type
53 "M4" type carts: no effect, ROM_OFFSET bit 29 when read return 1 if security PIC present, used by BIOS to determine this cart is encrypted and require bit 30 set when read ROM header
54
55 * bit 28 (mode bit 0)
56 "M2" type carts: ROM_OFFSET - master/slave ROM board select
57
58 * bit 0 can be set for "M4" type carts, function unknown
59
60 Normal address starts with 0xa0000000 to enable auto-advance and 8MB ROM addressing mode.
61 */
62
submap(address_map & map)63 void naomi_board::submap(address_map &map)
64 {
65 map(0x00, 0xff).r(FUNC(naomi_board::default_r));
66
67 map(0x00, 0x01).w(FUNC(naomi_board::rom_offseth_w));
68 map(0x02, 0x03).w(FUNC(naomi_board::rom_offsetl_w));
69 map(0x04, 0x05).rw(FUNC(naomi_board::rom_data_r), FUNC(naomi_board::rom_data_w));
70 map(0x06, 0x07).w(FUNC(naomi_board::dma_offseth_w));
71 map(0x08, 0x09).w(FUNC(naomi_board::dma_offsetl_w));
72 map(0x0a, 0x0b).w(FUNC(naomi_board::dma_count_w));
73 map(0x3c, 0x3d).w(FUNC(naomi_board::boardid_w));
74 map(0x3e, 0x3f).r(FUNC(naomi_board::boardid_r));
75 }
76
naomi_board(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)77 naomi_board::naomi_board(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
78 : naomi_g1_device(mconfig, type, tag, owner, clock),
79 eeprom(*this, finder_base::DUMMY_TAG)
80 {
81 }
82
device_start()83 void naomi_board::device_start()
84 {
85 naomi_g1_device::device_start();
86
87 save_item(NAME(rom_offset));
88 save_item(NAME(dma_offset));
89 save_item(NAME(dma_count));
90 save_item(NAME(dma_cur_offset));
91 save_item(NAME(pio_ready));
92 save_item(NAME(dma_ready));
93 }
94
device_reset()95 void naomi_board::device_reset()
96 {
97 naomi_g1_device::device_reset();
98 rom_offset = 0;
99 dma_offset = 0;
100 dma_cur_offset = 0;
101 pio_ready = false;
102 dma_ready = false;
103 }
104
dma_get_position(uint8_t * & base,uint32_t & limit,bool to_mainram)105 void naomi_board::dma_get_position(uint8_t *&base, uint32_t &limit, bool to_mainram)
106 {
107 if(!to_mainram) {
108 base = nullptr;
109 limit = 0;
110 return;
111 }
112
113 if(!dma_ready) {
114 if(!(dma_offset & 0x80000000))
115 throw emu_fatalerror("NAOMI BOARD: Unsupported, non-incrementing DMA.\n");
116 board_setup_address(dma_offset, true);
117 dma_cur_offset = 0;
118 dma_ready = true;
119 }
120
121 board_get_buffer(base, limit);
122 uint32_t blimit = 0x20*dma_count - dma_cur_offset;
123 if(0 && limit > blimit)
124 limit = blimit;
125 }
126
dma_advance(uint32_t size)127 void naomi_board::dma_advance(uint32_t size)
128 {
129 dma_cur_offset += size;
130 board_advance(size);
131 }
132
rom_offseth_w(uint16_t data)133 void naomi_board::rom_offseth_w(uint16_t data)
134 {
135 rom_offset = (rom_offset & 0x0000ffff) | (data << 16);
136 pio_ready = false;
137 }
138
rom_offsetl_w(uint16_t data)139 void naomi_board::rom_offsetl_w(uint16_t data)
140 {
141 rom_offset = (rom_offset & 0xffff0000) | data;
142 pio_ready = false;
143 }
144
rom_data_r()145 uint16_t naomi_board::rom_data_r()
146 {
147 if(!pio_ready) {
148 board_setup_address(rom_offset, false);
149 pio_ready = true;
150 }
151
152 uint8_t *buffer;
153 uint32_t size;
154 uint16_t res;
155 board_get_buffer(buffer, size);
156 assert(size > 1);
157 res = buffer[0] | (buffer[1] << 8);
158 if(rom_offset & 0x80000000)
159 board_advance(2);
160 return res;
161 }
162
rom_data_w(uint16_t data)163 void naomi_board::rom_data_w(uint16_t data)
164 {
165 board_write(rom_offset, data);
166
167 if(rom_offset & 0x80000000)
168 rom_offset += 2;
169 }
170
dma_offseth_w(uint16_t data)171 void naomi_board::dma_offseth_w(uint16_t data)
172 {
173 dma_offset = (dma_offset & 0x0000ffff) | (data << 16);
174 dma_ready = false;
175 }
176
dma_offsetl_w(uint16_t data)177 void naomi_board::dma_offsetl_w(uint16_t data)
178 {
179 dma_offset = (dma_offset & 0xffff0000) | data;
180 dma_ready = false;
181 }
182
dma_count_w(uint16_t data)183 void naomi_board::dma_count_w(uint16_t data)
184 {
185 dma_count = data;
186 }
187
boardid_w(uint16_t data)188 void naomi_board::boardid_w(uint16_t data)
189 {
190 eeprom->write_cs((data >> 2) & 1);
191 eeprom->write_rst((data >> 3) & 1);
192 eeprom->write_scl((data >> 1) & 1);
193 eeprom->write_sda((data >> 0) & 1);
194 }
195
boardid_r()196 uint16_t naomi_board::boardid_r()
197 {
198 return eeprom->read_sda() << 15;
199 }
200
default_r(offs_t offset)201 uint16_t naomi_board::default_r(offs_t offset)
202 {
203 logerror("NAOMIBD: unmapped read at %02x\n", offset);
204 return 0xffff;
205 }
206
board_write(offs_t offset,uint16_t data)207 void naomi_board::board_write(offs_t offset, uint16_t data)
208 {
209 logerror("NAOMIBD: unhandled board write %08x, %04x\n", offset, data);
210 }
211