diff options
Diffstat (limited to '')
| -rw-r--r-- | src/cpu/cpu.spec.ts | 31 | ||||
| -rw-r--r-- | src/cpu/cpu.ts | 46 |
2 files changed, 59 insertions, 18 deletions
diff --git a/src/cpu/cpu.spec.ts b/src/cpu/cpu.spec.ts index b1bc876..969b51c 100644 --- a/src/cpu/cpu.spec.ts +++ b/src/cpu/cpu.spec.ts @@ -26,6 +26,23 @@ describe('cpu', () => { ]); }); + it('should correctly sort the events when added in reverse order', () => { + const cpu = new CPU(new Uint16Array(1024), 0x1000); + const events: ITestEvent[] = []; + for (const i of [10, 4, 1]) { + cpu.addClockEvent(() => events.push([i, cpu.cycles]), i); + } + for (let i = 0; i < 10; i++) { + cpu.cycles++; + cpu.tick(); + } + expect(events).toEqual([ + [1, 1], + [4, 4], + [10, 10], + ]); + }); + describe('updateClockEvent', () => { it('should update the number of cycles for the given clock event', () => { const cpu = new CPU(new Uint16Array(1024), 0x1000); @@ -65,6 +82,20 @@ describe('cpu', () => { [10, 10], ]); }); + + it('should return false if the provided clock event is not scheduled', () => { + const cpu = new CPU(new Uint16Array(1024), 0x1000); + const event4 = cpu.addClockEvent(() => 0, 4); + const event10 = cpu.addClockEvent(() => 0, 10); + cpu.addClockEvent(() => 0, 1); + + // Both event should be successfully removed + expect(cpu.clearClockEvent(event4)).toBe(true); + expect(cpu.clearClockEvent(event10)).toBe(true); + // And now we should get false, as these events have already been removed + expect(cpu.clearClockEvent(event4)).toBe(false); + expect(cpu.clearClockEvent(event10)).toBe(false); + }); }); }); }); diff --git a/src/cpu/cpu.ts b/src/cpu/cpu.ts index e7a2544..a609222 100644 --- a/src/cpu/cpu.ts +++ b/src/cpu/cpu.ts @@ -173,23 +173,29 @@ export class CPU implements ICPU { } } - private updateClockEvents() { - this.clockEvents.sort((a, b) => a.cycles - b.cycles); - this.nextClockEvent = this.clockEvents[0]?.cycles ?? 0; - } - addClockEvent(callback: AVRClockEventCallback, cycles: number) { const entry = { cycles: this.cycles + Math.max(1, cycles), callback }; - this.clockEvents.push(entry); - this.updateClockEvents(); + // Add the new entry while keeping the array sorted + const { clockEvents } = this; + if (!clockEvents.length || clockEvents[clockEvents.length - 1].cycles <= entry.cycles) { + clockEvents.push(entry); + } else if (clockEvents[0].cycles >= entry.cycles) { + clockEvents.unshift(entry); + } else { + for (let i = 1; i < clockEvents.length; i++) { + if (clockEvents[i].cycles >= entry.cycles) { + clockEvents.splice(i, 0, entry); + break; + } + } + } + this.nextClockEvent = this.clockEvents[0].cycles; return callback; } updateClockEvent(callback: AVRClockEventCallback, cycles: number) { - const entry = this.clockEvents.find((item) => item.callback === callback); - if (entry) { - entry.cycles = this.cycles + Math.max(1, cycles); - this.updateClockEvents(); + if (this.clearClockEvent(callback)) { + this.addClockEvent(callback, cycles); return true; } return false; @@ -199,18 +205,22 @@ export class CPU implements ICPU { const index = this.clockEvents.findIndex((item) => item.callback === callback); if (index >= 0) { this.clockEvents.splice(index, 1); - this.updateClockEvents(); + this.nextClockEvent = this.clockEvents[0]?.cycles ?? 0; + return true; } + return false; } tick() { - if (this.nextClockEvent && this.nextClockEvent <= this.cycles) { - const clockEvent = this.clockEvents.shift(); - clockEvent?.callback(); - this.nextClockEvent = this.clockEvents[0]?.cycles ?? 0; + const { nextClockEvent, clockEvents } = this; + if (nextClockEvent && nextClockEvent <= this.cycles) { + clockEvents.shift()?.callback(); + this.nextClockEvent = clockEvents[0]?.cycles ?? 0; } - if (this.interruptsEnabled && this.nextInterrupt >= 0) { - const interrupt = this.pendingInterrupts[this.nextInterrupt]; + + const { nextInterrupt } = this; + if (this.interruptsEnabled && nextInterrupt >= 0) { + const interrupt = this.pendingInterrupts[nextInterrupt]; avrInterrupt(this, interrupt.address); if (!interrupt.constant) { this.clearInterrupt(interrupt); |
