- Fixed RAM expansion handling w/Bank switching

This commit is contained in:
tudnai 2020-05-27 17:16:49 -07:00
parent e18173605b
commit d008094078
7 changed files with 190 additions and 61 deletions

View File

@ -18,8 +18,6 @@
32440B64247C9C9C000F9DA1 /* merlin_assembler_1.woz in Resources */ = {isa = PBXBuildFile; fileRef = 32440B61247C9C2D000F9DA1 /* merlin_assembler_1.woz */; };
32440B65247C9C9C000F9DA1 /* merlin_assembler_2.woz in Resources */ = {isa = PBXBuildFile; fileRef = 32440B62247C9C2D000F9DA1 /* merlin_assembler_2.woz */; };
32440B66247C9C9C000F9DA1 /* merlin_assembler_3.woz in Resources */ = {isa = PBXBuildFile; fileRef = 32440B63247C9C2D000F9DA1 /* merlin_assembler_3.woz */; };
32440B6A247CA1CE000F9DA1 /* 65C02.c in Sources */ = {isa = PBXBuildFile; fileRef = 32440B69247CA1CE000F9DA1 /* 65C02.c */; };
32440B6B247CA1E0000F9DA1 /* 65C02.c in Sources */ = {isa = PBXBuildFile; fileRef = 32440B69247CA1CE000F9DA1 /* 65C02.c */; };
32440B75247CAA00000F9DA1 /* Merlin Pro v2.23 DOS3.3 (The Yegg-Men Crack).woz in Resources */ = {isa = PBXBuildFile; fileRef = 32440B72247CAA00000F9DA1 /* Merlin Pro v2.23 DOS3.3 (The Yegg-Men Crack).woz */; };
32440B76247CAA00000F9DA1 /* Merlin Pro 2.45 (DOS) Disk 1-2.woz in Resources */ = {isa = PBXBuildFile; fileRef = 32440B73247CAA00000F9DA1 /* Merlin Pro 2.45 (DOS) Disk 1-2.woz */; };
32440B77247CAA00000F9DA1 /* Merlin Pro 2.45 (DOS) Disk 2-2.woz in Resources */ = {isa = PBXBuildFile; fileRef = 32440B74247CAA00000F9DA1 /* Merlin Pro 2.45 (DOS) Disk 2-2.woz */; };
@ -29,6 +27,8 @@
32440B80247CB66C000F9DA1 /* Merlin Assembler (early version, 40-column, DOS 3.3) side A.woz in Resources */ = {isa = PBXBuildFile; fileRef = 32440B7E247CB66C000F9DA1 /* Merlin Assembler (early version, 40-column, DOS 3.3) side A.woz */; };
32440B81247CB66C000F9DA1 /* Merlin Assembler (early version, 40-column, DOS 3.3) side B.woz in Resources */ = {isa = PBXBuildFile; fileRef = 32440B7F247CB66C000F9DA1 /* Merlin Assembler (early version, 40-column, DOS 3.3) side B.woz */; };
32440B83247CC4C0000F9DA1 /* Wavy Navy (4am crack).woz in Resources */ = {isa = PBXBuildFile; fileRef = 32440B82247CC4C0000F9DA1 /* Wavy Navy (4am crack).woz */; };
32440B84247E27D3000F9DA1 /* 6502.c in Sources */ = {isa = PBXBuildFile; fileRef = 32439F7422ECD8AD0077AAE0 /* 6502.c */; };
32440B85247E27D7000F9DA1 /* 6502.c in Sources */ = {isa = PBXBuildFile; fileRef = 32439F7422ECD8AD0077AAE0 /* 6502.c */; };
325EB62F23F8856F00C6B4A4 /* woz.c in Sources */ = {isa = PBXBuildFile; fileRef = 325EB62E23F8856F00C6B4A4 /* woz.c */; };
325EB63623F8F78300C6B4A4 /* disk.c in Sources */ = {isa = PBXBuildFile; fileRef = 325EB63523F8F78300C6B4A4 /* disk.c */; };
325EB63923F9E48100C6B4A4 /* common.c in Sources */ = {isa = PBXBuildFile; fileRef = 325EB63823F9E48100C6B4A4 /* common.c */; };
@ -891,7 +891,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
32440B6B247CA1E0000F9DA1 /* 65C02.c in Sources */,
32440B85247E27D7000F9DA1 /* 6502.c in Sources */,
325EB67623FBC44400C6B4A4 /* common.c in Sources */,
32A9F74B2467B60B004902A1 /* speaker.c in Sources */,
325EB67823FBC45300C6B4A4 /* disk.c in Sources */,
@ -923,13 +923,13 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
32440B6A247CA1CE000F9DA1 /* 65C02.c in Sources */,
325EB63623F8F78300C6B4A4 /* disk.c in Sources */,
325EB63923F9E48100C6B4A4 /* common.c in Sources */,
32A9F74A2467B60B004902A1 /* speaker.c in Sources */,
32BFFB5D22EACC630003B53F /* ViewController.swift in Sources */,
325EB69323FE6C6200C6B4A4 /* HiRes.swift in Sources */,
32C4532E233345430000EBA1 /* MonitorView.swift in Sources */,
32440B84247E27D3000F9DA1 /* 6502.c in Sources */,
325EB62F23F8856F00C6B4A4 /* woz.c in Sources */,
32BFFB5B22EACC630003B53F /* AppDelegate.swift in Sources */,
32C45306232E3EEF0000EBA1 /* RepeatingTimer.swift in Sources */,

View File

@ -153,6 +153,14 @@
<ContextState
contextName = "PLA:6502_instr_stack.h">
</ContextState>
<ContextState
contextName = "memwrite8_high:mmio.h">
<PersistentStrings>
<PersistentString
value = "WRHIMEM[addr]">
</PersistentString>
</PersistentStrings>
</ContextState>
<ContextState
contextName = "LDA:6502_instr_load_store.h">
</ContextState>
@ -574,6 +582,12 @@
<PersistentString
value = "m6502.PC">
</PersistentString>
<PersistentString
value = "MEMcfg.RAM_16K">
</PersistentString>
<PersistentString
value = "MEMcfg.RAM_128K">
</PersistentString>
</PersistentStrings>
</ContextState>
<ContextState
@ -584,6 +598,17 @@
</PersistentString>
</PersistentStrings>
</ContextState>
<ContextState
contextName = "memwrite8_bank2:mmio.h">
<PersistentStrings>
<PersistentString
value = "WRD0MEM">
</PersistentString>
<PersistentString
value = "WRHIMEM">
</PersistentString>
</PersistentStrings>
</ContextState>
<ContextState
contextName = "read_rom:6502.c">
<PersistentStrings>

View File

@ -40,6 +40,7 @@ const unsigned long long startup_MHz_6502 = 32 * M;
unsigned long long MHz_6502 = default_MHz_6502;
unsigned long long clk_6502_per_frm = default_MHz_6502 / fps;
unsigned long long clk_6502_per_frm_set = default_MHz_6502 / fps;
unsigned long long clk_6502_per_frm_max_sound = 4 * default_MHz_6502 / fps;
unsigned long long clk_6502_per_frm_max = 0;
@ -729,6 +730,8 @@ void m6502_Run() {
for ( ; ; )
#endif
{
printDisassembly(outdev);
#ifdef INTERRUPT_CHECK_PER_STEP
if ( m6502.IF ) {

View File

@ -19,6 +19,7 @@ extern unsigned long long MHz_6502;
extern unsigned long long clk_6502_per_frm;
extern unsigned long long clk_6502_per_frm_set;
extern unsigned long long clk_6502_per_frm_max;
extern unsigned long long clk_6502_per_frm_max_sound;
extern unsigned int clkfrm;

View File

@ -140,56 +140,60 @@ char spkr_state = 0;
void spkr_toggle() {
// TODO: This is very slow!
// printf("io_KBDSTRB\n");
spkr_play_time = spkr_play_timeout;
spkr_play_time = 0;
// push a click into the speaker buffer
// (we will play the entire buffer at the end of the frame)
spkr_sample_idx = (clkfrm / (default_MHz_6502 / spkr_sample_rate)) * 2;
if ( spkr_state ) {
// down edge
spkr_state = 0;
if ( clk_6502_per_frm_set < clk_6502_per_frm_max_sound ) {
float fadeLevel = spkr_level - SPKR_LEVEL_MIN;
spkr_play_time = spkr_play_timeout;
while ( fadeLevel > +1 ) {
spkr_samples[ spkr_sample_idx++ ] = SPKR_LEVEL_MIN + fadeLevel;
spkr_samples[ spkr_sample_idx++ ] = SPKR_LEVEL_MIN + fadeLevel;
// push a click into the speaker buffer
// (we will play the entire buffer at the end of the frame)
spkr_sample_idx = (clkfrm / (default_MHz_6502 / spkr_sample_rate)) * 2;
if ( spkr_state ) {
// down edge
spkr_state = 0;
// how smooth we want the speeker to decay, so we will hear no pops and crackles
// 0.9 gives you a kind of saw wave at 1KHz (beep)
// 0.7 is better, but Xonix gives you a bit distorted speech and Donkey Kong does not sound the same
fadeLevel *= 0.16;
}
spkr_level = SPKR_LEVEL_MIN;
}
else {
// up edge
spkr_state = 1;
float fadeLevel = spkr_level - SPKR_LEVEL_MAX;
while ( fadeLevel < -1 ) {
spkr_samples[ spkr_sample_idx++ ] = SPKR_LEVEL_MAX + fadeLevel;
spkr_samples[ spkr_sample_idx++ ] = SPKR_LEVEL_MAX + fadeLevel;
float fadeLevel = spkr_level - SPKR_LEVEL_MIN;
// how smooth we want the speeker to decay, so we will hear no pops and crackles
// 0.9 gives you a kind of saw wave at 1KHz (beep)
// 0.7 is better, but Xonix gives you a bit distorted speech and Donkey Kong does not sound the same
fadeLevel *= 0.32;
while ( fadeLevel > +1 ) {
spkr_samples[ spkr_sample_idx++ ] = SPKR_LEVEL_MIN + fadeLevel;
spkr_samples[ spkr_sample_idx++ ] = SPKR_LEVEL_MIN + fadeLevel;
// how smooth we want the speeker to decay, so we will hear no pops and crackles
// 0.9 gives you a kind of saw wave at 1KHz (beep)
// 0.7 is better, but Xonix gives you a bit distorted speech and Donkey Kong does not sound the same
fadeLevel *= 0.16;
}
spkr_level = SPKR_LEVEL_MIN;
}
else {
// up edge
spkr_state = 1;
float fadeLevel = spkr_level - SPKR_LEVEL_MAX;
while ( fadeLevel < -1 ) {
spkr_samples[ spkr_sample_idx++ ] = SPKR_LEVEL_MAX + fadeLevel;
spkr_samples[ spkr_sample_idx++ ] = SPKR_LEVEL_MAX + fadeLevel;
// how smooth we want the speeker to decay, so we will hear no pops and crackles
// 0.9 gives you a kind of saw wave at 1KHz (beep)
// 0.7 is better, but Xonix gives you a bit distorted speech and Donkey Kong does not sound the same
fadeLevel *= 0.32;
}
spkr_level = SPKR_LEVEL_MAX;
}
spkr_level = SPKR_LEVEL_MAX;
}
//spkr_samples[sample_idx] = spkr_level;
for ( int i = spkr_sample_idx; i < spkr_buf_size + spkr_extra_buf; i++ ) {
spkr_samples[i] = spkr_level;
//spkr_samples[sample_idx] = spkr_level;
for ( int i = spkr_sample_idx; i < spkr_buf_size + spkr_extra_buf; i++ ) {
spkr_samples[i] = spkr_level;
}
// memset(spkr_samples + spkr_sample_idx, spkr_level, spkr_buf_size * sizeof(spkr_samples[0]));
}
// memset(spkr_samples + spkr_sample_idx, spkr_level, spkr_buf_size * sizeof(spkr_samples[0]));
}

View File

@ -43,10 +43,11 @@ uint8_t * const AUX = Apple2_64K_AUX; // Pointer to the Auxiliary Memo
uint8_t * const RAM = Apple2_64K_RAM; // Pointer to the Main Memory so we can use this from Swift
uint8_t * const MEM = Apple2_64K_MEM; // Pointer to the Shadow Memory Map so we can use this from Swift
uint8_t * const RDLOMEM = Apple2_64K_MEM; // Pointer to the Shadow Memory Map so we can use this from Swift
uint8_t * const WRLOMEM = Apple2_64K_MEM; // Pointer to the Shadow Memory Map so we can use this from Swift
uint8_t * const RDHIMEM = Apple2_64K_MEM; // Pointer to the Shadow Memory Map so we can use this from Swift
uint8_t * const WRHIMEM = Apple2_Dummy_RAM; // Pointer to the Shadow Memory Map so we can use this from Swift
uint8_t * const RDLOMEM = Apple2_64K_MEM; // for Read $0000 - $BFFF (shadow memory)
uint8_t * const WRLOMEM = Apple2_64K_MEM; // for Write $0000 - $BFFF (shadow memory)
uint8_t * const RDHIMEM = Apple2_64K_MEM; // for Read / Write $0000 - $BFFF (shadow memory)
uint8_t * WRD0MEM = Apple2_Dummy_RAM; // for writing $D000 - $DFFF
uint8_t * WRHIMEM = Apple2_Dummy_RAM; // for writing $E000 - $FFFF
#define DEF_RAM_PAGE(mem,pg) \
@ -281,14 +282,26 @@ enum mmio {
io_RDALTZP = 0xC016, // ECG R7 Status of Main/Aux Stack and Zero Page
io_RDC3ROM = 0xC017, // E G R7 Status of Slot 3/Aux Slot ROM
io_RSTYINT = 0xC017, // C R Reset Mouse Y0 Interrupt
io_MEM_RDRAM_NOWR_2 = 0xC080,
io_MEM_RDROM_WRAM_2 = 0xC081,
io_MEM_RDROM_NOWR_2 = 0xC082,
io_MEM_RDRAM_WRAM_2 = 0xC083,
io_MEM_RDRAM_NOWR_2_ = 0xC084,
io_MEM_RDROM_WRAM_2_ = 0xC085,
io_MEM_RDROM_NOWR_2_ = 0xC086,
io_MEM_RDRAM_WRAM_2_ = 0xC087,
io_MEM_RDRAM_NOWR_1 = 0xC088,
io_MEM_RDROM_WRAM_1 = 0xC089,
io_MEM_RDROM_NOWR_1 = 0xC08A,
io_MEM_RDRAM_WRAM_1 = 0xC08B,
io_MEM_RDRAM_NOWR_1_ = 0xC08C,
io_MEM_RDROM_WRAM_1_ = 0xC08D,
io_MEM_RDROM_NOWR_1_ = 0xC08E,
io_MEM_RDRAM_WRAM_1_ = 0xC08F,
};
@ -397,6 +410,9 @@ void auxMemorySelect() {
}
uint8_t * current_RAM_bank = Apple2_64K_AUX + 0xC000;
INLINE uint8_t ioRead( uint16_t addr ) {
// if (outdev) fprintf(outdev, "ioRead:%04X\n", addr);
// printf("ioRead:%04X (PC:%04X)\n", addr, m6502.PC);
@ -499,24 +515,53 @@ INLINE uint8_t ioRead( uint16_t addr ) {
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_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:
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;
// save the content of Shadow Memory in needed
if ( MEMcfg.WR_RAM ) {
// printf("Saving RAM Bank %d to %p\n", MEMcfg.RAM_BANK_2 + 1, current_RAM_bank);
memcpy(current_RAM_bank, Apple2_64K_MEM + 0xD000, 0x1000);
memcpy(Apple2_64K_AUX + 0xE000, Apple2_64K_MEM + 0xE000, 0x2000);
}
// RAM Bank 1 or 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:
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_:
// printf("RAM_BANK_2\n");
MEMcfg.RAM_BANK_2 = 1;
RAM_BANK = Apple2_64K_AUX + 0xD000;
break;
default:
// printf("RAM_BANK_1\n");
MEMcfg.RAM_BANK_2 = 0;
RAM_BANK = Apple2_64K_AUX + 0xC000;
break;
@ -528,23 +573,28 @@ INLINE uint8_t ioRead( uint16_t addr ) {
case (uint8_t)io_MEM_RDRAM_WRAM_2:
case (uint8_t)io_MEM_RDRAM_NOWR_1:
case (uint8_t)io_MEM_RDRAM_WRAM_1:
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_:
// printf("RD_RAM\n");
MEMcfg.RD_RAM = 1;
uint8_t * shadow = Apple2_64K_MEM + 0xD000;
// save the content of Shadow Memory
memcpy(Apple2_64K_RAM + 0xD000, shadow, 0x3000);
// load the content of Aux Memory
memcpy(Apple2_64K_MEM + 0xD000, Apple2_64K_AUX, 0x3000);
memcpy(Apple2_64K_MEM + 0xD000, RAM_BANK, 0x1000);
memcpy(Apple2_64K_MEM + 0xE000, Apple2_64K_AUX + 0xE000, 0x2000);
// set the RAM extension to read on the upper memory area
break;
default:
// printf("RD_ROM\n");
MEMcfg.RD_RAM = 0;
shadow = Apple2_64K_MEM + 0xD000;
// save the content of Shadow Memory
memcpy(Apple2_64K_AUX + 0xD000, shadow, 0x3000);
// load the content of ROM Memory
memcpy(Apple2_64K_MEM + 0xD000, Apple2_16K_ROM + 0x1000, 0x3000);
@ -555,19 +605,52 @@ INLINE uint8_t ioRead( uint16_t addr ) {
// is RAM Writeable?
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_RDROM_WRAM_2_:
case (uint8_t)io_MEM_RDROM_WRAM_1_:
// printf("RD_ROM + WR_AUX\n");
// will write directly to Auxiliary RAM, and mark it as NO need to commit from Shadow RAM
MEMcfg.WR_RAM = 0;
if ( MEMcfg.RAM_BANK_2 ) {
WRD0MEM = Apple2_64K_AUX; // for Write $D000 - $DFFF (shadow memory) - BANK 2
}
else {
WRD0MEM = Apple2_64K_AUX - 0x1000; // for Write $D000 - $DFFF (shadow memory) - BANK 1
}
WRHIMEM = Apple2_64K_AUX; // for Write $E000 - $FFFF (shadow memory)
break;
case (uint8_t)io_MEM_RDRAM_WRAM_2:
case (uint8_t)io_MEM_RDRAM_WRAM_1:
case (uint8_t)io_MEM_RDRAM_WRAM_2_:
case (uint8_t)io_MEM_RDRAM_WRAM_1_:
// printf("RD_RAM + WR_RAM\n");
// will write to Shadow RAM, and mark it as need to commit from Shadow RAM
MEMcfg.WR_RAM = 1;
// set the RAM extension to read from the upper memory area
WRD0MEM = Apple2_64K_MEM; // for Write $D000 - $DFFF (shadow memory) - BANK X
WRHIMEM = Apple2_64K_MEM; // for Write $E000 - $FFFF (shadow memory)
break;
default:
// printf("RD_ROM + NO_WR\n");
// No writing (Readonly), and mark it as NO need to commit from Shadow RAM
MEMcfg.WR_RAM = 0;
// set the ROM to read on the upper memory area
WRD0MEM = Apple2_Dummy_RAM; // for Discarding any writes to $D000 - $DFFF - BANK X
WRHIMEM = Apple2_Dummy_RAM; // for Discarding any writes to $E000 - $FFFF
break;
}
current_RAM_bank = RAM_BANK;
// printf("Set current_RAM_bank %d to %p\n", MEMcfg.RAM_BANK_2 + 1, current_RAM_bank);
} // if there is RAM expansion card installed
break;
@ -869,6 +952,9 @@ INLINE uint8_t memread( uint16_t addr ) {
INLINE void memwrite8_low( uint16_t addr, uint8_t data ) {
WRLOMEM[addr] = data;
}
INLINE void memwrite8_bank2( uint16_t addr, uint8_t data ) {
WRD0MEM[addr] = data;
}
INLINE void memwrite8_high( uint16_t addr, uint8_t data ) {
WRHIMEM[addr] = data;
}
@ -877,11 +963,21 @@ INLINE void memwrite( uint16_t addr, uint8_t data ) {
if (addr < 0xC100) {
ioWrite(addr, data);
}
else if (addr < 0xD000) {
// this could be either Peripherial ROM or Internal ROM
memwrite8_high(addr, data);
}
else if (addr < 0xE000) {
// Aux RAM Bank 1 or 2
memwrite8_bank2(addr, data);
}
else {
memwrite8_high(addr, data);
// ROM (dummy memory to screape writings) or Aux RAM
memwrite8_high(addr, data);
}
}
else {
// RAM
memwrite8_low(addr, data);
}

View File

@ -91,7 +91,7 @@ INLINE void printDisassembly( FILE * f ) {
fprintf( f, "%llu\t%llu %s: %-11s%-4s%s\t0x%02X\t0x%02X\t0x%02X\t0x%02X\t0x%02X\t;\t%s\n", // Virtual ][ style
++discnt,
m6502.clktime,
m6502.clktime + clkfrm,
disassembly.addr,
disassembly.opcode,
disassembly.inst,