123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181 |
- "use strict";
- /**
- * @constructor
- * @param {CPU} cpu
- */
- function DMA(cpu)
- {
- /** @const @type {CPU} */
- this.cpu = cpu;
- this.channel_addr = new Int32Array(4);
- this.channel_count = new Int32Array(4);
- this.lsb_msb_flipflop = 0;
- var io = cpu.io;
- io.register_write(0x04, this, this.port_write.bind(this, 0x04));
- io.register_write(0x05, this, this.port_write.bind(this, 0x05));
- io.register_write(0x0A, this, this.portA_write);
- io.register_write(0x0B, this, this.portB_write);
- io.register_write(0x0C, this, this.portC_write);
- io.register_write(0x81, this, this.port81_write);
- }
- DMA.prototype.get_state = function()
- {
- return [
- this.channel_addr,
- this.channel_count,
- this.lsb_msb_flipflop,
- ];
- };
- DMA.prototype.set_state = function(state)
- {
- this.channel_addr = state[0];
- this.channel_count = state[1];
- this.lsb_msb_flipflop = state[2];
- };
- DMA.prototype.port_write = function(port, data_byte)
- {
- dbg_log("port " + port + " write " + data_byte, LOG_DMA);
- if(port < 8)
- {
- var channel = port >> 1;
- if(port & 1)
- {
- this.channel_count[channel] = this.flipflop_get(this.channel_count[channel], data_byte);
- }
- else
- {
- this.channel_addr[channel] = this.flipflop_get(this.channel_addr[channel], data_byte);
- }
- }
- };
- DMA.prototype.port_read = function(port)
- {
- if(port < 8)
- {
- var channel = port >> 1;
- if(port & 1)
- {
- return this.channel_count[channel];
- }
- else
- {
- // Bug?
- return this.channel_addr[channel];
- }
- }
- else
- {
- dbg_log("port " + h(port) + " read", LOG_DMA);
- }
- };
- DMA.prototype.portA_write = function(data_byte)
- {
- dbg_log("port A write: " + h(data_byte), LOG_DMA);
- };
- DMA.prototype.portB_write = function(data_byte)
- {
- dbg_log("port B write: " + h(data_byte), LOG_DMA);
- };
- DMA.prototype.portC_write = function(data_byte)
- {
- this.lsb_msb_flipflop = 0;
- }
- DMA.prototype.port81_write = function(data_byte)
- {
- this.channel_addr[2] = this.channel_addr[2] & 0xFFFF | data_byte << 16;
- }
- // read data, write to memory
- DMA.prototype.do_read = function(buffer, start, len, channel, fn)
- {
- var read_count = this.channel_count[channel] + 1,
- addr = this.channel_addr[channel];
- dbg_log("DMA write channel " + channel, LOG_DMA);
- dbg_log("to " + h(addr) + " len " + h(read_count), LOG_DMA);
- if(len < read_count)
- {
- dbg_log("DMA should read more than provided: " + h(len) + " " + h(read_count), LOG_DMA);
- }
- if(start + read_count > buffer.byteLength)
- {
- dbg_log("DMA read outside of buffer", LOG_DMA);
- fn(true);
- }
- else
- {
- var cpu = this.cpu;
- this.channel_addr[channel] += read_count;
- buffer.get(start, read_count, function(data)
- {
- cpu.write_blob(data, addr);
- fn(false);
- });
- }
- };
- // write data, read memory
- DMA.prototype.do_write = function(buffer, start, len, channel, fn)
- {
- var read_count = this.channel_count[channel],
- addr = this.channel_addr[channel];
- dbg_log("DMA write channel " + channel, LOG_DMA);
- dbg_log("to " + h(addr) + " len " + h(read_count), LOG_DMA);
- if(len < read_count)
- {
- dbg_log("DMA should read more than provided", LOG_DMA);
- }
- if(start + read_count > buffer.byteLength)
- {
- dbg_log("DMA write outside of buffer", LOG_DMA);
- fn(true);
- }
- else
- {
- this.channel_addr[channel] += read_count;
- buffer.set(start,
- this.cpu.mem8.subarray(addr, addr + read_count + 1),
- function() {
- fn(false);
- }
- );
- }
- }
- DMA.prototype.flipflop_get = function(old_dword, new_byte)
- {
- this.lsb_msb_flipflop ^= 1;
- if(this.lsb_msb_flipflop)
- {
- // low byte
- return old_dword & ~0xFF | new_byte;
- }
- else
- {
- // high byte
- return old_dword & ~0xFF00 | new_byte << 8;
- }
- }
|