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