Skip to content

Commit

Permalink
zsim: Introduced new Z80 memory.
Browse files Browse the repository at this point in the history
  • Loading branch information
maziac committed Mar 22, 2020
1 parent 313b494 commit 52d399a
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 24 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# 0.13.4
- Fix: Internal simulator: Write watchpoint was indicated as read watchpoint.

- Fix: Internal simulator: corrected "LD (IX/IY+d),n".

# 0.13.3
- PC jumps to correct location after state restore.
Expand Down
67 changes: 59 additions & 8 deletions src/remotes/zxsimulator/zxmemory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ import {MemBuffer} from '../../misc/membuffer';
/**
* Represents the memory, banking and slots of a ZX Spectrum
* and ZX Next.
*
* For performance reasons the memory is arranged as 64k continuous block.
* Apart from this another memory exists with 256 Banks of 8k.
* The banking is realized as mem copies between these 2 memories.
*/
export class ZxMemory {
// The bank size.
Expand All @@ -23,17 +27,20 @@ export class ZxMemory {
// Screen width
public static SCREEN_WIDTH=256;

// Holds the memory banks. Views to the 'wholeMemory'.
// Holds the memory banks. Views to the 'AllBanksRam'.
protected banks: Array<Uint8Array>;

// The memory in one big block.
protected RAM: ArrayBuffer;
// The memory banks in one big block.
protected AllBanksRam: ArrayBuffer;

// Holds the slot assignments to the banks.
// Note: I use 254 for ROM 0-0x1FFF and 255 for ROM 0x2000-0x3FFF.
// The ZXNext defines both at 255.
protected slots: number[]=[254, 255, 10, 11, 4, 5, 0, 1];

// The 64k memory that hte Z80 addresses.
protected z80Memory: Uint8Array;

// Visual memory: shows the access as an image.
// The image is just 1 pixel high.
protected visualMemory: Array<number>;
Expand All @@ -50,11 +57,12 @@ export class ZxMemory {
/// Constructor.
constructor() {
// Create RAM
this.RAM=new ArrayBuffer(ZxMemory.NUMBER_OF_BANKS*ZxMemory.MEMORY_BANK_SIZE);
this.AllBanksRam=new ArrayBuffer(ZxMemory.NUMBER_OF_BANKS*ZxMemory.MEMORY_BANK_SIZE);
this.z80Memory=new Uint8Array(0x10000);
// Create memory banks
this.banks=new Array<Uint8Array>(ZxMemory.NUMBER_OF_BANKS);
for (let b=0; b<ZxMemory.NUMBER_OF_BANKS; b++) {
const bank=new Uint8Array(this.RAM, b*ZxMemory.MEMORY_BANK_SIZE, ZxMemory.MEMORY_BANK_SIZE);
const bank=new Uint8Array(this.AllBanksRam, b*ZxMemory.MEMORY_BANK_SIZE, ZxMemory.MEMORY_BANK_SIZE);
this.banks[b]=bank;
}
// Create visual memory
Expand Down Expand Up @@ -82,13 +90,16 @@ export class ZxMemory {
* Serializes the object.
*/
public serialize(memBuffer: MemBuffer) {
// Copy Z80 memory to banks before serialization
this.copyZ80MemToBanks();

// Get slot/bank mapping
memBuffer.write8(this.slots.length);
for (const bank of this.slots)
memBuffer.write8(bank);

// Get RAM
memBuffer.writeArrayBuffer(this.RAM);
memBuffer.writeArrayBuffer(this.AllBanksRam);
}


Expand All @@ -104,10 +115,13 @@ export class ZxMemory {

// Create memory banks
const buffer=memBuffer.readArrayBuffer();
assert(buffer.length==this.RAM.byteLength);
const dst=new Uint8Array(this.RAM);
assert(buffer.length==this.AllBanksRam.byteLength);
const dst=new Uint8Array(this.AllBanksRam);
dst.set(buffer);

// Copy from banks to Z80 memory
this.copyBanksToZ80Mem();

// Clear visual memory
this.clearVisualMemory();
}
Expand Down Expand Up @@ -303,6 +317,43 @@ export class ZxMemory {
}


/**
* Copies the memory banks into the Z80 memory.
* Called e.g. after deserialization or after loading.
*/
public copyBanksToZ80Mem() {
let offset=0;
let slotIndex=0;
while (offset<0x10000) {
const bank=this.slots[slotIndex];
const memBank=this.banks[bank];
this.z80Memory.set(memBank, offset);
// Next
offset+=ZxMemory.MEMORY_BANK_SIZE;
slotIndex++;
}
}


/**
* Copies the Z80 memory into the banks.
* Called e.g. before serialization or before saving.
*/
public copyZ80MemToBanks() {
let offset=0;
let slotIndex=0;
while (offset<0x10000) {
const bank=this.slots[slotIndex];
const memBank=this.banks[bank];
const z80SlotMem=new Uint8Array(this.z80Memory.buffer, offset, ZxMemory.MEMORY_BANK_SIZE);
memBank.set(z80SlotMem);
// Next
offset+=ZxMemory.MEMORY_BANK_SIZE;
slotIndex++;
}
}


/**
* Loads the 48K Spectrum roms in bank 0xFE and 0xFF
*/
Expand Down
6 changes: 0 additions & 6 deletions src/remotes/zxsimulator/zxports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,6 @@ export class ZxPorts {
protected ports: Uint8Array;


// TODO: Remove
public hitAddress: number=-1
;

/// Constructor.
constructor() {
this.ports=new Uint8Array(0x10000);
Expand Down Expand Up @@ -65,8 +61,6 @@ export class ZxPorts {

// Write 1 byte. Used by the CPU.
public write(port: number, data: number) {
if(port==0x7ffd)
this.hitAddress=port;
}

// Change the port value. Simulates HW access.
Expand Down
21 changes: 12 additions & 9 deletions src/remotes/zxsimulator/zxsimremote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,18 @@ export class ZxSimulatorRemote extends DzrpRemote {
}



/**
* Loads .nex or .sna files.
* Assures that the memory banks are copied to the Z80 memory.
*/
protected async loadBin(filePath: string): Promise<void> {
await super.loadBin(filePath);
// Copy memory banks
this.zxMemory.copyBanksToZ80Mem();
}


/**
* Sets a specific register value.
* @param reg E.g. Z80_REG.PC or Z80_REG.A
Expand Down Expand Up @@ -399,15 +411,6 @@ export class ZxSimulatorRemote extends DzrpRemote {
}
}

// TODO: Remove: check port access
if (this.zxPorts.hitAddress>=0) {
// Yes, read or write access
breakNumber=(false)? BREAK_REASON_NUMBER.WATCHPOINT_READ:BREAK_REASON_NUMBER.WATCHPOINT_WRITE;
breakData=this.zxPorts.hitAddress;
this.zxPorts.hitAddress=-1;
break;
}

// Check if watchpoint is hit
if (this.zxMemory.hitAddress>=0) {
// Yes, read or write access
Expand Down

0 comments on commit 52d399a

Please sign in to comment.