Convert DMA to prototypical definition
This commit is contained in:
parent
e0fa1bd3fa
commit
6ce08cfe02
279
src/dma.js
279
src/dma.js
|
@ -5,164 +5,165 @@
|
|||
*/
|
||||
function DMA(dev)
|
||||
{
|
||||
var io = dev.io,
|
||||
memory = dev.memory,
|
||||
this.io = dev.io;
|
||||
this.memory = dev.memory;
|
||||
|
||||
channels = [
|
||||
{ address: 0, count: 0 },
|
||||
{ address: 0, count: 0 },
|
||||
{ address: 0, count: 0 },
|
||||
{ address: 0, count: 0 }
|
||||
],
|
||||
this.channels = [
|
||||
{ address: 0, count: 0 },
|
||||
{ address: 0, count: 0 },
|
||||
{ address: 0, count: 0 },
|
||||
{ address: 0, count: 0 }
|
||||
];
|
||||
|
||||
lsb_msb_flipflop = 0;
|
||||
this.lsb_msb_flipflop = 0;
|
||||
|
||||
io.register_write(0x04, port_write.bind(0, 0x04));
|
||||
io.register_write(0x05, port_write.bind(0, 0x05));
|
||||
io.register_write(0x0A, portA_write);
|
||||
io.register_write(0x0B, portB_write);
|
||||
io.register_write(0x0C, portC_write);
|
||||
io.register_write(0x81, port81_write);
|
||||
this.io.register_write(0x04, this.port_write.bind(this, 0x04));
|
||||
this.io.register_write(0x05, this.port_write.bind(this, 0x05));
|
||||
this.io.register_write(0x0A, this.portA_write.bind(this));
|
||||
this.io.register_write(0x0B, this.portB_write.bind(this));
|
||||
this.io.register_write(0x0C, this.portC_write.bind(this));
|
||||
this.io.register_write(0x81, this.port81_write.bind(this));
|
||||
};
|
||||
|
||||
function port_write(port, data_byte)
|
||||
DMA.prototype.port_write = function(port, data_byte)
|
||||
{
|
||||
dbg_log("port " + port + " write " + data_byte, LOG_DMA);
|
||||
|
||||
if(port < 8)
|
||||
{
|
||||
dbg_log("port " + port + " write " + data_byte, LOG_DMA);
|
||||
var channel = port >> 1;
|
||||
|
||||
if(port < 8)
|
||||
if(port & 1)
|
||||
{
|
||||
var channel = port >> 1;
|
||||
|
||||
if(port & 1)
|
||||
{
|
||||
channels[channel].count = flipflop_get(channels[channel].count, data_byte);
|
||||
}
|
||||
else
|
||||
{
|
||||
channels[channel].address = flipflop_get(channels[channel].address, data_byte);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function port_read(port)
|
||||
{
|
||||
if(port < 8)
|
||||
{
|
||||
var channel = port >> 1;
|
||||
|
||||
if(port & 1)
|
||||
{
|
||||
return channels[channel].count;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Bug?
|
||||
return channels[channel].address;
|
||||
}
|
||||
this.channels[channel].count = this.flipflop_get(this.channels[channel].count, data_byte);
|
||||
}
|
||||
else
|
||||
{
|
||||
dbg_log("port " + h(port) + " read", LOG_DMA);
|
||||
}
|
||||
};
|
||||
|
||||
function portA_write(data_byte)
|
||||
{
|
||||
dbg_log("port A write: " + h(data_byte), LOG_DMA);
|
||||
};
|
||||
|
||||
function portB_write(data_byte)
|
||||
{
|
||||
dbg_log("port B write: " + h(data_byte), LOG_DMA);
|
||||
};
|
||||
|
||||
function portC_write(data_byte)
|
||||
{
|
||||
lsb_msb_flipflop = 0;
|
||||
}
|
||||
|
||||
function port81_write(data_byte)
|
||||
{
|
||||
channels[2].address = channels[2].address & 0xFFFF | data_byte << 16;
|
||||
}
|
||||
|
||||
// read data, write to memory
|
||||
this.do_read = function(buffer, start, len, channel, fn)
|
||||
{
|
||||
var read_count = channels[channel].count + 1,
|
||||
addr = channels[channel].address;
|
||||
|
||||
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
|
||||
{
|
||||
channels[channel].address += read_count;
|
||||
|
||||
buffer.get(start, read_count, function(data)
|
||||
{
|
||||
memory.write_blob(data, addr);
|
||||
fn(false);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// write data, read memory
|
||||
this.do_write = function(buffer, start, len, channel, fn)
|
||||
{
|
||||
var read_count = channels[channel].count,
|
||||
addr = channels[channel].address;
|
||||
|
||||
dbg_log("DMA write channel " + channel, LOG_DMA);
|
||||
dbg_log("to " + h(addr) + " len " + h(read_count), LOG_DMA);
|
||||
//dbg_log(channels[channel], 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
|
||||
{
|
||||
channels[channel].address += read_count;
|
||||
|
||||
buffer.set(start,
|
||||
new Uint8Array(memory.buffer, addr, read_count + 1),
|
||||
function() {
|
||||
fn(false);
|
||||
}
|
||||
);
|
||||
this.channels[channel].address = this.flipflop_get(this.channels[channel].address, data_byte);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function flipflop_get(old_dword, new_byte)
|
||||
DMA.prototype.port_read = function(port)
|
||||
{
|
||||
if(port < 8)
|
||||
{
|
||||
lsb_msb_flipflop ^= 1;
|
||||
var channel = port >> 1;
|
||||
|
||||
if(lsb_msb_flipflop)
|
||||
if(port & 1)
|
||||
{
|
||||
// low byte
|
||||
return old_dword & ~0xFF | new_byte;
|
||||
return this.channels[channel].count;
|
||||
}
|
||||
else
|
||||
{
|
||||
// high byte
|
||||
return old_dword & ~0xFF00 | new_byte << 8;
|
||||
// Bug?
|
||||
return this.channels[channel].address;
|
||||
}
|
||||
}
|
||||
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.channels[2].address = this.channels[2].address & 0xFFFF | data_byte << 16;
|
||||
}
|
||||
|
||||
// read data, write to memory
|
||||
DMA.prototype.do_read = function(buffer, start, len, channel, fn)
|
||||
{
|
||||
var read_count = this.channels[channel].count + 1,
|
||||
addr = this.channels[channel].address;
|
||||
|
||||
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 memory = this.memory;
|
||||
this.channels[channel].address += read_count;
|
||||
|
||||
buffer.get(start, read_count, function(data)
|
||||
{
|
||||
memory.write_blob(data, addr);
|
||||
fn(false);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// write data, read memory
|
||||
DMA.prototype.do_write = function(buffer, start, len, channel, fn)
|
||||
{
|
||||
var read_count = this.channels[channel].count,
|
||||
addr = this.channels[channel].address;
|
||||
|
||||
dbg_log("DMA write channel " + channel, LOG_DMA);
|
||||
dbg_log("to " + h(addr) + " len " + h(read_count), LOG_DMA);
|
||||
//dbg_log(this.channels[channel], 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.channels[channel].address += read_count;
|
||||
|
||||
buffer.set(start,
|
||||
new Uint8Array(this.memory.buffer, 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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue