- Speed improvements

- Keyboard Up
- HiRes optimized (battery save) refresh / Refresh by blocks that modified
This commit is contained in:
tudnai 2020-05-05 08:35:57 -07:00
parent 092c40a7cb
commit 2eead2f4ad
8 changed files with 875 additions and 232 deletions

View File

@ -13,9 +13,6 @@
</PersistentString>
</PersistentStrings>
</ContextState>
<ContextState
contextName = "rel_addr:Apple2_mmio.h">
</ContextState>
<ContextState
contextName = "read_rom:6502.c">
<PersistentStrings>
@ -36,6 +33,9 @@
</PersistentString>
</PersistentStrings>
</ContextState>
<ContextState
contextName = "rel_addr:Apple2_mmio.h">
</ContextState>
<ContextState
contextName = "addr_ind_Y:Apple2_mmio.h">
</ContextState>
@ -142,6 +142,20 @@
<ContextState
contextName = "memread8:Apple2_mmio.h">
</ContextState>
<ContextState
contextName = "textPageSelect:mmio.h">
<PersistentStrings>
<PersistentString
value = "AUX[0x22]">
</PersistentString>
<PersistentString
value = "RAM[0x22]">
</PersistentString>
<PersistentString
value = "MEMcfg">
</PersistentString>
</PersistentStrings>
</ContextState>
<ContextState
contextName = "ioRead:Apple2_mmio.h">
<PersistentStrings>
@ -177,17 +191,6 @@
</PersistentString>
</PersistentStrings>
</ContextState>
<ContextState
contextName = "textPageSelect:mmio.h">
<PersistentStrings>
<PersistentString
value = "AUX[0x22]">
</PersistentString>
<PersistentString
value = "RAM[0x22]">
</PersistentString>
</PersistentStrings>
</ContextState>
<ContextState
contextName = "CPY:6502_instr_compare_test.h">
<PersistentStrings>
@ -256,7 +259,7 @@
contextName = "HiRes.draw(_:):HiRes.swift">
<PersistentStrings>
<PersistentString
value = "ctx?.bitsPerComponent">
value = "(blockH7 | ( block &amp; bitMask ))">
</PersistentString>
<PersistentString
value = "ctx?.data">
@ -283,13 +286,21 @@
value = "shadowScreen">
</PersistentString>
<PersistentString
value = "(blockH7 | ( block &amp; bitMask ))">
value = "ctx?.height">
</PersistentString>
<PersistentString
value = "linAddr">
</PersistentString>
<PersistentString
value = "ctx?.height">
value = "ctx?.bitsPerComponent">
</PersistentString>
</PersistentStrings>
</ContextState>
<ContextState
contextName = "ioRead:mmio.h">
<PersistentStrings>
<PersistentString
value = "m6502.PC">
</PersistentString>
</PersistentStrings>
</ContextState>
@ -377,6 +388,14 @@
<ContextState
contextName = "STA:6502_instr_load_store.h">
</ContextState>
<ContextState
contextName = "addr_abs:mmio.h">
<PersistentStrings>
<PersistentString
value = "cache">
</PersistentString>
</PersistentStrings>
</ContextState>
<ContextState
contextName = "m6502_Step:6502.c">
<PersistentStrings>

View File

@ -61,8 +61,8 @@
</TestAction>
<LaunchAction
buildConfiguration = "Release"
selectedDebuggerIdentifier = ""
selectedLauncherIdentifier = "Xcode.IDEFoundation.Launcher.PosixSpawn"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"

View File

@ -134,7 +134,8 @@ class HiRes: NSView {
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
initHiResLineAddresses()
HiRes.context?.clear( CGRect(x: 0, y: 0, width: frame.width, height: frame.height) )
// currentContext?.setShouldAntialias(false)
// currentContext?.interpolationQuality = CGInterpolationQuality.none
@ -586,17 +587,11 @@ class HiRes: NSView {
}
}
override func draw(_ rect: CGRect) {
// print("HIRESSLOW\n")
// if was > 100 {
// return
// }
// was += 1
func Update() {
var height = HiRes.PixelHeight
// do not even render it...
if videoMode.text == 1 {
return
@ -612,17 +607,13 @@ class HiRes: NSView {
HiResBufferPointer = HiResBuffer1
}
}
var pixelAddr = 0
// var minX = 9999
// var minY = 9999
// var maxX = 0
// var maxY = 0
//
// var x = 0
var y = 0
blockChanged = [Bool](repeating: false, count: HiRes.blockRows * HiRes.blockCols / 2)
HiRes.context?.clear( CGRect(x: 0, y: 0, width: frame.width, height: frame.height) )
for lineAddr in HiResLineAddrTbl {
@ -636,67 +627,80 @@ class HiRes: NSView {
var prev = 0
for blockHorIdx in 0 ..< HiRes.blockCols / 2 {
// print("blockVertIdx:", blockVertIdx, " blockHorIdx:", blockHorIdx)
let blockH = Int(HiResBufferPointer[ Int(lineAddr + blockHorIdx * 2) ])
let blockH7 = ( blockH >> 5 ) & 0x04
let blockL = Int(HiResBufferPointer[ Int(lineAddr + blockHorIdx * 2) + 1 ])
let blockL7 = ( blockL >> 5 ) & 0x04
let block = ( blockL << 7 ) | ( blockH & 0x7F ) & 0x3FFF
let block8 = ( blockL << 8 ) | blockH
let screenIdx = y * HiRes.blockCols + blockHorIdx
if ( shadowScreen[ screenIdx ] != block ) {
blockChanged[ blockVertIdx + blockHorIdx ] = true
}
else {
blockChanged[ blockVertIdx + blockHorIdx ] = false
}
shadowScreen[ screenIdx ] = block
for px in 0 ... 2 {
// let bitMask = 3 << ( px * 2 )
let pixel = blockH7 | ( (block >> (px * 2)) & 3 )
hiresColorPixel(pixelAddr: pixelAddr, pixel: pixel, prev: prev )
pixelAddr += 8
prev = pixel
// if ( minX > x ) { minX = x }
// if ( minY > y ) { minY = y }
// if ( maxX < x ) { maxX = x }
// if ( maxY < y ) { maxY = y }
//
// x += 2
}
let pixel = blockH7 | ( (block >> (3 * 2)) & 3 )
// get all changed blocks
blockChanged[ blockVertIdx + blockHorIdx ] = blockChanged[ blockVertIdx + blockHorIdx ] || shadowScreen[ screenIdx ] != block8
shadowScreen[ screenIdx ] = block8
for px in 0 ... 2 {
// let bitMask = 3 << ( px * 2 )
let pixel = blockH7 | ( (block >> (px * 2)) & 3 )
hiresColorPixel(pixelAddr: pixelAddr, pixel: pixel, prev: prev )
pixelAddr += 8
prev = pixel
for px in 4 ... 6 {
// let bitMask = 3 << ( px * 2 )
let pixel = blockL7 | ( (block >> (px * 2)) & 3 )
hiresColorPixel(pixelAddr: pixelAddr, pixel: pixel, prev: prev )
pixelAddr += 8
prev = pixel
// if ( minX > x ) { minX = x }
// if ( minY > y ) { minY = y }
// if ( maxX < x ) { maxX = x }
// if ( maxY < y ) { maxY = y }
//
// x += 2
}
}
// else {
// pixelAddr += 4 * 7
// x += 7
// }
// }
let pixel = blockH7 | ( (block >> (3 * 2)) & 3 )
hiresColorPixel(pixelAddr: pixelAddr, pixel: pixel, prev: prev )
pixelAddr += 8
prev = pixel
for px in 4 ... 6 {
// let bitMask = 3 << ( px * 2 )
let pixel = blockL7 | ( (block >> (px * 2)) & 3 )
hiresColorPixel(pixelAddr: pixelAddr, pixel: pixel, prev: prev )
pixelAddr += 8
prev = pixel
}
}
y += 1
// x = 0
}
// refresh changed block only
let blockScreenWidth = Int(frame.width) / HiRes.blockCols * 2
let blockScreenHeigth = Int(frame.height) / HiRes.blockRows
for blockVertIdx in 0 ..< HiRes.blockRows {
for blockHorIdx in 0 ..< HiRes.blockCols / 2 {
if blockChanged[ blockVertIdx * HiRes.blockCols / 2 + blockHorIdx ] {
// refresh the entire screen
let boundingBox = CGRect(
x: blockHorIdx * blockScreenWidth - 2,
y: Int(frame.height) - blockVertIdx * blockScreenHeigth - blockScreenHeigth - 2,
width: blockScreenWidth + 4,
height: blockScreenHeigth + 4)
self.setNeedsDisplay( boundingBox )
}
}
}
// needsDisplay = true // refresh the entire screen
}
override func draw(_ rect: CGRect) {
// print("HIRESSLOW\n")
// if was > 100 {
// return
// }
// was += 1
// HiRes.context?.setShouldAntialias(true)
// HiRes.context?.interpolationQuality = CGInterpolationQuality.low

View File

@ -332,6 +332,8 @@ class ViewController: NSViewController {
}
#endif
kbdUp()
}
// override func flagsChanged(with event: NSEvent) {
// switch event.modifierFlags.intersection(.deviceIndependentFlagsMask) {
@ -564,7 +566,8 @@ class ViewController: NSViewController {
// only refresh graphics view when needed (aka not in text mode)
if ( videoMode.text == 0 ) {
self.hires.needsDisplay = true
// self.hires.needsDisplay = true
self.hires.Update()
}
// }
#endif
@ -601,6 +604,8 @@ class ViewController: NSViewController {
// txtClear[ y * (textCols + lineEndChars) + textCols * 2 + 1 ] = "\n"
// }
hires.needsDisplay = true;
woz_loadFile( Bundle.main.resourcePath, "Apple DOS 3.3 January 1983.woz" )

View File

@ -159,6 +159,7 @@ extern void tst6502(void);
extern void m6502_ColdReset( const char * bundlePath, const char * romFilePath );
extern void m6502_Run(void);
extern void kbdInput ( uint8_t code );
extern void kbdUp ();
extern void setIO ( uint16_t ioaddr, uint8_t val );
extern void interrupt_IRQ(void);

View File

@ -10,9 +10,9 @@
#define __6502_INSTR_BRANCH_H__
INLINE void BRA( int8_t reladdr ) {
uint8_t pg = m6502.PC >> 8;
m6502.PC += reladdr;
#ifdef CLK_ABSOLUTE_PRECISE
uint8_t pg = m6502.PC >> 8;
m6502.clktime += m6502.PC >> 8 == pg ? 1 : 2;
#else
m6502.clktime++;

View File

@ -402,17 +402,18 @@ INLINE uint8_t ioRead( uint16_t addr ) {
uint8_t currentMagnet = 0;
switch (addr) {
case io_KBD:
switch ( (uint8_t)addr ) {
case (uint8_t)io_KBD:
// if ( RAM[io_KBD] > 0x7F ) printf("io_KBD:%04X\n", addr);
return Apple2_64K_RAM[io_KBD];
case io_KBDSTRB:
case (uint8_t)io_KBDSTRB:
// TODO: This is very slow!
// printf("io_KBDSTRB\n");
return Apple2_64K_RAM[io_KBD] &= 0x7F;
Apple2_64K_RAM[io_KBD] &= 0x7F;
return Apple2_64K_RAM[io_KBDSTRB];
case io_SPKR:
case (uint8_t)io_SPKR:
// TODO: This is very slow!
// printf("io_KBDSTRB\n");
@ -428,93 +429,93 @@ INLINE uint8_t ioRead( uint16_t addr ) {
// videoMode.col80 = 1;
// break;
//
case io_VID_RDTEXT:
case (uint8_t)io_VID_RDTEXT:
return videoMode.text << 7;
case io_VID_ALTCHAR:
case (uint8_t)io_VID_ALTCHAR:
return videoMode.altChr << 7;
case io_VID_RD80VID:
case (uint8_t)io_VID_RD80VID:
return videoMode.col80 << 7;
case io_TAPEIN:
case (uint8_t)io_TAPEIN:
return MEMcfg.txt_page_2 << 7;
case io_RDCXROM:
case (uint8_t)io_RDCXROM:
return MEMcfg.int_Cx_ROM << 7;
case io_RDALTZP:
case (uint8_t)io_RDALTZP:
return MEMcfg.ALT_ZP << 7;
case io_RDC3ROM:
case (uint8_t)io_RDC3ROM:
return MEMcfg.slot_C3_ROM << 7;
case io_RD80STORE:
case (uint8_t)io_RD80STORE:
return MEMcfg.is_80STORE << 7;
case io_VID_TXTPAGE1:
case (uint8_t)io_VID_TXTPAGE1:
// printf("io_VID_TXTPAGE1\n");
MEMcfg.txt_page_2 = 0;
textPageSelect();
break;
case io_VID_TXTPAGE2:
case (uint8_t)io_VID_TXTPAGE2:
// printf("io_VID_TXTPAGE2\n");
MEMcfg.txt_page_2 = 1;
textPageSelect();
break;
case io_VID_Text_OFF:
case (uint8_t)io_VID_Text_OFF:
videoMode.text = 0;
break;
case io_VID_Text_ON:
case (uint8_t)io_VID_Text_ON:
videoMode.text = 1;
break;
case io_VID_Mixed_OFF:
case (uint8_t)io_VID_Mixed_OFF:
videoMode.mixed = 0;
break;
case io_VID_Mixed_ON:
case (uint8_t)io_VID_Mixed_ON:
videoMode.mixed = 1;
break;
case io_VID_Hires_OFF:
case (uint8_t)io_VID_Hires_OFF:
videoMode.hires = 0;
break;
case io_VID_Hires_ON:
case (uint8_t)io_VID_Hires_ON:
videoMode.hires = 1;
break;
case io_PDL0:
case io_PDL1:
case io_PDL2:
case io_PDL3:
case (uint8_t)io_PDL0:
case (uint8_t)io_PDL1:
case (uint8_t)io_PDL2:
case (uint8_t)io_PDL3:
// if ( RAM[addr] > 127 ) {
// RAM[addr]--;
// }
return Apple2_64K_RAM[addr];
case io_MEM_RDRAM_NOWR_2:
case io_MEM_RDROM_WRAM_2:
case io_MEM_RDROM_NOWR_2:
case io_MEM_RDRAM_WRAM_2:
case io_MEM_RDRAM_NOWR_1:
case io_MEM_RDROM_WRAM_1:
case io_MEM_RDROM_NOWR_1:
case io_MEM_RDRAM_WRAM_1:
case (uint8_t)io_MEM_RDRAM_NOWR_2:
case (uint8_t)io_MEM_RDROM_WRAM_2:
case (uint8_t)io_MEM_RDROM_NOWR_2:
case (uint8_t)io_MEM_RDRAM_WRAM_2:
case (uint8_t)io_MEM_RDRAM_NOWR_1:
case (uint8_t)io_MEM_RDROM_WRAM_1:
case (uint8_t)io_MEM_RDROM_NOWR_1:
case (uint8_t)io_MEM_RDRAM_WRAM_1:
if ( MEMcfg.RAM_16K || MEMcfg.RAM_128K ) {
uint8_t * RAM_BANK = Apple2_64K_AUX + 0xC000;
// RAM Bank 1 or 2?
switch (addr) {
case io_MEM_RDRAM_NOWR_2:
case io_MEM_RDROM_WRAM_2:
case io_MEM_RDROM_NOWR_2:
case io_MEM_RDRAM_WRAM_2:
switch ((uint8_t)addr) {
case (uint8_t)io_MEM_RDRAM_NOWR_2:
case (uint8_t)io_MEM_RDROM_WRAM_2:
case (uint8_t)io_MEM_RDROM_NOWR_2:
case (uint8_t)io_MEM_RDRAM_WRAM_2:
MEMcfg.RAM_BANK_2 = 1;
RAM_BANK = Apple2_64K_AUX + 0xD000;
break;
@ -526,11 +527,11 @@ INLINE uint8_t ioRead( uint16_t addr ) {
}
// is RAM to read or ROM?
switch (addr) {
case io_MEM_RDRAM_NOWR_2:
case io_MEM_RDRAM_WRAM_2:
case io_MEM_RDRAM_NOWR_1:
case io_MEM_RDRAM_WRAM_1:
switch ((uint8_t)addr) {
case (uint8_t)io_MEM_RDRAM_NOWR_2:
case (uint8_t)io_MEM_RDRAM_WRAM_2:
case (uint8_t)io_MEM_RDRAM_NOWR_1:
case (uint8_t)io_MEM_RDRAM_WRAM_1:
MEMcfg.RD_RAM = 1;
uint8_t * shadow = Apple2_64K_MEM + 0xD000;
@ -556,11 +557,11 @@ INLINE uint8_t ioRead( uint16_t addr ) {
}
// is RAM Writeable?
switch (addr) {
case io_MEM_RDROM_WRAM_2:
case io_MEM_RDRAM_WRAM_2:
case io_MEM_RDROM_WRAM_1:
case io_MEM_RDRAM_WRAM_1:
switch ((uint8_t)addr) {
case (uint8_t)io_MEM_RDROM_WRAM_2:
case (uint8_t)io_MEM_RDRAM_WRAM_2:
case (uint8_t)io_MEM_RDROM_WRAM_1:
case (uint8_t)io_MEM_RDRAM_WRAM_1:
MEMcfg.WR_RAM = 1;
// set the RAM extension to read from the upper memory area
break;
@ -575,10 +576,10 @@ INLINE uint8_t ioRead( uint16_t addr ) {
break;
// TODO: Make code "card insertable to slot" / aka slot independent and dynamically add/remove
case io_DISK_PHASE0_OFF + SLOT6:
case io_DISK_PHASE1_OFF + SLOT6:
case io_DISK_PHASE2_OFF + SLOT6:
case io_DISK_PHASE3_OFF + SLOT6:
case (uint8_t)io_DISK_PHASE0_OFF + SLOT6:
case (uint8_t)io_DISK_PHASE1_OFF + SLOT6:
case (uint8_t)io_DISK_PHASE2_OFF + SLOT6:
case (uint8_t)io_DISK_PHASE3_OFF + SLOT6:
currentMagnet = (addr - io_DISK_PHASE0_OFF - SLOT6) / 2;
disk.phase.magnet &= ~(1 << currentMagnet);
printf("io_DISK_PHASE%u_OFF (S%u, ps:%X) ", currentMagnet, 6, disk.phase.magnet);
@ -586,10 +587,10 @@ INLINE uint8_t ioRead( uint16_t addr ) {
disk_phase();
return 0;
case io_DISK_PHASE0_ON + SLOT6:
case io_DISK_PHASE1_ON + SLOT6:
case io_DISK_PHASE2_ON + SLOT6:
case io_DISK_PHASE3_ON + SLOT6: {
case (uint8_t)io_DISK_PHASE0_ON + SLOT6:
case (uint8_t)io_DISK_PHASE1_ON + SLOT6:
case (uint8_t)io_DISK_PHASE2_ON + SLOT6:
case (uint8_t)io_DISK_PHASE3_ON + SLOT6: {
currentMagnet = (addr - io_DISK_PHASE0_ON - SLOT6) / 2;
disk.phase.magnet |= 1 << currentMagnet;
printf("io_DISK_PHASE%u_ON (S%u, ps:%X) ", currentMagnet, 6, disk.phase.magnet);
@ -598,35 +599,35 @@ INLINE uint8_t ioRead( uint16_t addr ) {
return 0;
}
case io_DISK_POWER_OFF + SLOT6:
case (uint8_t)io_DISK_POWER_OFF + SLOT6:
dbgPrintf2("io_DISK_POWER_OFF (S%u)\n", 6);
return 0;
case io_DISK_POWER_ON + SLOT6:
case (uint8_t)io_DISK_POWER_ON + SLOT6:
dbgPrintf2("io_DISK_POWER_ON (S%u)\n", 6);
return 0;
case io_DISK_SELECT_1 + SLOT6:
case (uint8_t)io_DISK_SELECT_1 + SLOT6:
dbgPrintf2("io_DISK_SELECT_1 (S%u)\n", 6);
return 0;
case io_DISK_SELECT_2 + SLOT6:
case (uint8_t)io_DISK_SELECT_2 + SLOT6:
dbgPrintf2("io_DISK_SELECT_2 (S%u)\n", 6);
return 0;
case io_DISK_READ + SLOT6:
case (uint8_t)io_DISK_READ + SLOT6:
return disk_read();
case io_DISK_WRITE + SLOT6:
case (uint8_t)io_DISK_WRITE + SLOT6:
dbgPrintf2("io_DISK_WRITE (S%u)\n", 6);
return 0;
case io_DISK_CLEAR + SLOT6:
case (uint8_t)io_DISK_CLEAR + SLOT6:
dbgPrintf2("io_DISK_CLEAR (S%u)\n", 6);
return 0;
case io_DISK_SHIFT + SLOT6:
case (uint8_t)io_DISK_SHIFT + SLOT6:
dbgPrintf2("io_DISK_SHIFT (S%u)\n", 6);
return 0;
@ -672,6 +673,12 @@ void kbdInput ( uint8_t code ) {
}
void kbdUp () {
RAM[io_KBDSTRB] &= 0x7F;
}
INLINE void ioWrite( uint16_t addr, uint8_t val ) {
// if (outdev) fprintf(outdev, "ioWrite:%04X (A:%02X)\n", addr, m6502.A);
switch (addr) {