9 HD6844::HD6844(VM *parent_vm, EMU *parent_emu) : DEVICE(parent_vm, parent_emu)
13 init_output_signals(&interrupt_line);
14 init_output_signals(&halt_line);
24 for(ch = 0; ch < 4; ch++) {
25 addr_reg[ch] = 0xffff;
26 words_reg[ch] = 0xffff;
27 fixed_addr[ch] = 0x0000;
29 first_transfer[ch] = false;
31 channel_control[ch] = 0;
32 transfering[ch] = false;
33 if(event_dmac[ch] >= 0) cancel_event(this, event_dmac[ch]);
43 void HD6844::initialize()
47 for(ch = 0; ch < 4; ch++) {
53 void HD6844::write_data8(uint32 addr, uint32 data)
55 uint8 ch = addr & 0x03;
57 uint32 channel = (addr >> 2) & 3;
63 tmpd.w.l = addr_reg[channel];
65 tmpd.b.h = data & 0xff;
66 addr_reg[channel] = tmpd.d;
69 tmpd.w.l = addr_reg[channel];
70 tmpd.b.l = data & 0xff;
71 addr_reg[channel] = tmpd.d;
74 tmpd.w.l = words_reg[channel];
75 tmpd.b.h = data & 0xff;
76 words_reg[channel] = tmpd.w.l;
79 tmpd.w.l = words_reg[channel];
80 tmpd.b.l = data & 0xff;
81 words_reg[channel] = tmpd.w.l;
84 } else if((addr >= 0x10) && (addr < 0x14)) { // $10-$13
85 channel_control[addr - 0x10] = (channel_control[addr - 0x10] & 0xc0 ) | (data & 0x0f);
86 } else if(addr == 0x14) {
87 priority_reg = data & 0x8f;
88 } else if(addr == 0x15) {
89 interrupt_reg = (interrupt_reg & 0x80) | (data & 0x0f);
90 } else if(addr == 0x16) {
91 datachain_reg = (datachain_reg & 0xf0) | (data & 0x0f);
96 uint32 HD6844::read_data8(uint32 addr)
98 uint8 ch = addr & 0x03;
100 uint32 channel = (addr >> 2) & 3;
101 uint32 retval = 0xff;
107 tmpd.d = addr_reg[channel];
108 retval = tmpd.b.h & 0x00ff;
111 tmpd.d = addr_reg[channel];
112 retval = tmpd.b.l & 0x00ff;
115 tmpd.w.l = words_reg[channel];
116 retval = tmpd.b.h & 0x00ff;
119 tmpd.w.l = words_reg[channel];
120 retval = tmpd.b.l & 0x00ff;
123 } else if((addr >= 0x10) && (addr < 0x14)) { // $10-$13
124 retval = channel_control[addr - 0x10];
125 channel_control[addr - 0x10] &= 0x7f;
126 } else if(addr == 0x14) {
127 retval = priority_reg;
128 } else if(addr == 0x15) {
129 retval = ((datachain_reg >> 4) | 0x80) & interrupt_reg;
130 interrupt_reg &= 0x7f;
131 datachain_reg &= 0x0f;
132 write_signals(&interrupt_line, 0x00);
133 } else if(addr == 0x16) {
134 retval = datachain_reg & 0x0f;
139 uint32 HD6844::read_signal(int id)
142 case HD6844_SET_CONST_OFFSET:
145 case HD6844_SRC_FIXED_ADDR_CH0:
146 return fixed_addr[0];
148 case HD6844_SRC_FIXED_ADDR_CH1:
149 return fixed_addr[1];
151 case HD6844_SRC_FIXED_ADDR_CH2:
152 return fixed_addr[2];
154 case HD6844_SRC_FIXED_ADDR_CH3:
155 return fixed_addr[3];
157 case HD6844_ADDR_REG_0:
160 case HD6844_ADDR_REG_1:
163 case HD6844_ADDR_REG_2:
166 case HD6844_ADDR_REG_3:
169 case HD6844_WORDS_REG_0:
172 case HD6844_WORDS_REG_1:
175 case HD6844_WORDS_REG_2:
178 case HD6844_WORDS_REG_3:
181 case HD6844_IS_TRANSFER_0:
182 return transfering[0] ? 0xffffffff : 0;
184 case HD6844_IS_TRANSFER_1:
185 return transfering[1] ? 0xffffffff : 0;
187 case HD6844_IS_TRANSFER_2:
188 return transfering[2] ? 0xffffffff : 0;
190 case HD6844_IS_TRANSFER_3:
191 return transfering[3] ? 0xffffffff : 0;
199 void HD6844::write_signal(int id, uint32 data, uint32 mask)
201 bool val_b = ((data & mask) != 0);
202 uint32 ch = (data & mask) & 0x03;
205 case HD6844_SET_CONST_OFFSET:
208 case HD6844_SRC_FIXED_ADDR_CH0:
209 fixed_addr[0] = data;
211 case HD6844_SRC_FIXED_ADDR_CH1:
212 fixed_addr[1] = data;
214 case HD6844_SRC_FIXED_ADDR_CH2:
215 fixed_addr[2] = data;
217 case HD6844_SRC_FIXED_ADDR_CH3:
218 fixed_addr[3] = data;
220 case HD6844_TRANSFER_START:
221 if(transfering[ch]) return;
222 if((words_reg[ch] == 0) || (words_reg[ch] == 0xffff)) return;
223 channel_control[ch] = channel_control[ch] & 0x8f;
224 first_transfer[ch] = true;
225 if(event_dmac[ch] < 0) register_event(this, HD6844_EVENT_START_TRANSFER + ch,
226 50.0, false, &event_dmac[ch]);
228 case HD6844_DO_TRANSFER:
229 if(!transfering[ch]) return;
230 if(((channel_control[ch] & 0x02) != 0) && (!cycle_steal)) cycle_steal = true;
232 this->write_signals(&halt_line, 0xffffffff);
234 if(((words_reg[ch] & 0x0f) == 1) || (first_transfer[ch])){
235 first_transfer[ch] = false;
236 register_event(this, HD6844_EVENT_DO_TRANSFER + ch,
237 (double)(0x10 / 2), false, NULL); // HD68B44
247 void HD6844::do_transfer(int ch)
249 if(!transfering[ch]) return;
250 if((priority_reg & 0x01) == 0) {
251 transfering[ch] = false;
252 if(!cycle_steal) this->write_signals(&halt_line, 0);
256 if(words_reg[ch] == 0) {
257 transfering[ch] = false;
258 if(!cycle_steal) this->write_signals(&halt_line, 0);
260 channel_control[ch] = (channel_control[ch] & 0x0f) | 0x80;
263 //if(((channel_control[ch] & 0x02) != 0) && (!cycle_steal)) cycle_steal = true;
265 if((channel_control[ch] & 0x01) == 0) {
266 data_reg[ch] = src[ch]->read_io8(fixed_addr[ch]) & 0xff;
267 dest[ch]->write_dma_io8((uint32)addr_reg[ch] + addr_offset, data_reg[ch]);
268 //p_emu->out_debug_log(_T("HD6844: FIXED -> SRC: %04x, %02x\n"), addr_reg[ch] + addr_offset, data_reg[ch]);
270 data_reg[ch] = dest[ch]->read_dma_io8((uint32)addr_reg[ch] + addr_offset) & 0xff;
271 src[ch]->write_io8(fixed_addr[ch], data_reg[ch]);
272 //p_emu->out_debug_log(_T("HD6844: SRC -> FIXED: %04x, %02x\n"), addr_reg[ch] + addr_offset, data_reg[ch]);
275 if((channel_control[ch] & 0x08) != 0) {
280 addr_reg[ch] = addr_reg[ch] & 0xffff;
281 if(!cycle_steal) this->write_signals(&halt_line, 0);
283 if(words_reg[ch] == 0) {
284 if((datachain_reg & 0x07) == 0x01) {
285 addr_reg[0] = addr_reg[3];
286 addr_reg[1] = addr_reg[0];
287 addr_reg[2] = addr_reg[1];
288 addr_reg[3] = addr_reg[2];
290 words_reg[0] = words_reg[3];
291 words_reg[1] = words_reg[0];
292 words_reg[2] = words_reg[1];
295 transfering[ch] = false;
297 channel_control[ch] = (channel_control[ch] & 0x0f) | 0x80;
298 datachain_reg = datachain_reg | 0x10;
299 if((interrupt_reg & 0x01) != 0) {
300 interrupt_reg |= 0x80;
301 write_signals(&interrupt_line, 0xffffffff);
303 //p_emu->out_debug_log(_T("HD6844: Complete transfer ch %d\n"), ch);
308 void HD6844::event_callback(int event_id, int err)
312 if((event_id >= HD6844_EVENT_START_TRANSFER) && (event_id < (HD6844_EVENT_START_TRANSFER + 4))) {
313 ch = event_id - HD6844_EVENT_START_TRANSFER;
315 channel_control[ch] = (channel_control[ch] & 0x0f) | 0x40;
316 transfering[ch] = true;
317 //p_emu->out_debug_log(_T("HD6844: Start to transfer ch %d Words = $%04x $%04x $%04x $%04x:\n"), ch, words_reg[0], words_reg[1], words_reg[2], words_reg[3]);
318 } else if((event_id >= HD6844_EVENT_DO_TRANSFER) && (event_id < (HD6844_EVENT_DO_TRANSFER + 4))) {
319 ch = event_id - HD6844_EVENT_DO_TRANSFER;