protected override bool ExecutePatch() { if (base.PC == 0xFFD2) // CHROUT { CBM_Console.WriteChar((char)A); // fall through to draw character in screen memory too } else if (base.PC == 0xFFCF) // CHRIN { A = CBM_Console.ReadChar(); // SetA equivalent for flags Z = (A == 0); N = ((A & 0x80) != 0); C = false; // RTS equivalent byte lo = base.Pop(); byte hi = base.Pop(); base.PC = (ushort)(((hi << 8) | lo) + 1); return(true); // overriden, so don't execute } return(false); // execute normally }
protected override bool ExecutePatch() { if (base.PC == (ushort)(memory[0xFFFC] | (memory[0xFFFD] << 8))) { CBM_Console.WriteChar((char)147, true); // PET 2001 doesn't initialize screen with chr$(147), so must do it here, supressing next home } else if (base.PC == 0xFFD2) // CHROUT { CBM_Console.WriteChar((char)A); // fall through to draw character in screen memory too } else if (base.PC == 0xFFCF) // CHRIN { A = CBM_Console.ReadChar(); // SetA equivalent for flags Z = (A == 0); N = ((A & 0x80) != 0); C = false; // RTS equivalent byte lo = base.Pop(); byte hi = base.Pop(); base.PC = (ushort)(((hi << 8) | lo) + 1); return(true); // overriden, so don't execute } return(false); // execute normally }
protected override bool ExecutePatch() { if (PC == 0xFFD2) // CHROUT { CBM_Console.WriteChar((char)A); // fall through to draw character in screen memory too } else if (PC == 0xFFCF) // CHRIN { A = CBM_Console.ReadChar(); // SetA equivalent for flags Z = (A == 0); N = ((A & 0x80) != 0); C = false; // RTS equivalent byte lo = Pop(); byte hi = Pop(); PC = (ushort)(((hi << 8) | lo) + 1); return(true); // overriden, and PC changed, so caller should reloop before execution to allow breakpoint/trace/ExecutePatch/etc. } else if (PC == 0xA474 || PC == LOAD_TRAP) // READY { if (StartupPRG != null) // User requested program be loaded at startup { bool is_basic; if (PC == LOAD_TRAP) { is_basic = ( FileVerify == false && FileSec == 0 && // relative load, not absolute LO(FileAddr) == memory[43] && // requested load address matches BASIC start HI(FileAddr) == memory[44]); byte err; if (!FileLoad(out err)) { System.Diagnostics.Debug.WriteLine(string.Format("FileLoad() failed: err={0}, file {1}", err, StartupPRG)); C = true; // signal error A = err; // FILE NOT FOUND or VERIFY // so doesn't repeat StartupPRG = null; LOAD_TRAP = -1; return(true); // overriden, and PC changed, so caller should reloop before execution to allow breakpoint/trace/ExecutePatch/etc. } } else { is_basic = ((C64Memory)memory).LoadStartupPrg(StartupPRG, out FileAddr); } StartupPRG = null; if (is_basic) { //UNNEW that I used in late 1980s, should work well for loading a program too, probably gleaned from BASIC ROM //listed here as reference, adapted to use in this state machine, ExecutePatch() //ldy #0 //lda #1 //sta(43),y //iny //sta(43),y //jsr $a533 ; LINKPRG //clc //lda $22 //adc #2 //sta 45 //lda $23 //adc #0 //sta 46 //lda #0 //jsr $a65e ; CLEAR/CLR //jmp $a474 ; READY // initialize first couple bytes (may only be necessary for UNNEW?) ushort addr = (ushort)(memory[43] | (memory[44] << 8)); memory[addr] = 1; memory[(ushort)(addr + 1)] = 1; // JSR equivalent ushort retaddr = (ushort)(PC - 1); Push(HI(retaddr)); Push(LO(retaddr)); PC = 0xA533; // LINKPRG startup_state = 1; // should be able to regain control when returns... return(true); // overriden, and PC changed, so caller should reloop before execution to allow breakpoint/trace/ExecutePatch/etc. } else { LOAD_TRAP = -1; X = LO(FileAddr); Y = HI(FileAddr); C = false; } } else if (startup_state == 1) { ushort addr = (ushort)(memory[0x22] | (memory[0x23] << 8) + 2); memory[45] = (byte)addr; memory[46] = (byte)(addr >> 8); // JSR equivalent ushort retaddr = (ushort)(PC - 1); Push(HI(retaddr)); Push(LO(retaddr)); PC = 0xA65E; // CLEAR/CLR A = 0; startup_state = 2; // should be able to regain control when returns... return(true); // overriden, and PC changed, so caller should reloop before execution to allow breakpoint/trace/ExecutePatch/etc. } else if (startup_state == 2) { if (PC == LOAD_TRAP) { X = LO(FileAddr); Y = HI(FileAddr); } else { CBM_Console.Push("RUN\r"); PC = 0xA47B; // skip READY message, but still set direct mode, and continue to MAIN } C = false; // signal success startup_state = 0; LOAD_TRAP = -1; return(true); // overriden, and PC changed, so caller should reloop before execution to allow breakpoint/trace/ExecutePatch/etc. } } else if (PC == 0xF13E) // GETIN { //BASIC TEST: //10 GET K$ : REM GETIN //20 IF K$<> "" THEN PRINT ASC(K$) //25 IF K$= "Q" THEN END //30 GOTO 10 A = CBM_Console.GetIn(); if (A == 0) { Z = true; C = false; } else { X = A; Z = false; C = false; } // RTS equivalent byte lo = Pop(); byte hi = Pop(); PC = (ushort)(((hi << 8) | lo) + 1); return(true); // overriden, and PC changed, so caller should reloop before execution to allow breakpoint/trace/ExecutePatch/etc. } else if (PC == 0xF6ED) // STOP { Z = CBM_Console.CheckStop(); // RTS equivalent byte lo = Pop(); byte hi = Pop(); PC = (ushort)(((hi << 8) | lo) + 1); return(true); // overriden, and PC changed, so caller should reloop before execution to allow breakpoint/trace/ExecutePatch/etc. } else if (PC == 0xFE00) // SETLFS { FileNum = A; FileDev = X; FileSec = Y; System.Diagnostics.Debug.WriteLine(string.Format("SETLFS {0},{1},{2}", FileNum, FileDev, FileSec)); } else if (PC == 0xFDF9) // SETNAM { StringBuilder name = new StringBuilder(); ushort addr = (ushort)(X + (Y << 8)); for (int i = 0; i < A; ++i) { name.Append((char)memory[(ushort)(addr + i)]); } System.Diagnostics.Debug.WriteLine(string.Format("SETNAM {0}", name.ToString())); FileName = name.ToString(); } else if (PC == 0xF49E) // LOAD { FileAddr = (ushort)(X + (Y << 8)); string op; if (A == 0) { op = "LOAD"; } else if (A == 1) { op = "VERIFY"; } else { op = string.Format("LOAD (A={0}) ???", A); } FileVerify = (A == 1); System.Diagnostics.Debug.WriteLine(string.Format("{0} @{1:X4}", op, FileAddr)); // RTS equivalent byte lo = Pop(); byte hi = Pop(); PC = (ushort)(((hi << 8) | lo) + 1); if (A == 0 || A == 1) { StartupPRG = FileName; FileName = null; LOAD_TRAP = PC; // Set success C = false; } else { A = 14; // ILLEGAL QUANTITY message C = true; // failure } return(true); // overriden, and PC changed, so caller should reloop before execution to allow breakpoint/trace/ExecutePatch/etc. } else if (PC == 0xF5DD) // SAVE { ushort addr1 = (ushort)(memory[A] + (memory[(ushort)(A + 1)] << 8)); ushort addr2 = (ushort)(X + (Y << 8)); System.Diagnostics.Debug.WriteLine(string.Format("SAVE {0:X4}-{1:X4}", addr1, addr2)); // RTS equivalent byte lo = Pop(); byte hi = Pop(); PC = (ushort)(((hi << 8) | lo) + 1); // Set success C = !FileSave(FileName, addr1, addr2); return(true); // overriden, and PC changed, so caller should reloop before execution to allow breakpoint/trace/ExecutePatch/etc. } return(false); // execute normally }