1: ; This is the RESET routine that is called when a hardware RESET occurs. 2: ; After determining if an expansion cartridge is available - in this case, 3: ; this routine aborts and calls the RESET routine of the cartridge - 4: ; it has to set up the I/O areas and all memory. Afterwards, it calls 5: ; the BASIC through the BASIC cold start vector 6: ; 7: RESET: 8: ldx #<$01FF 9: sei ; no interrupts are allowed (we have not set it up yet) 10: txs ; SP = $FF, so we have maximum stack space 11: cld ; make sure we are in binary mode, not in decimal mode 12: jsr CheckCartridge ; check for an expansion cartridge 13: bne @NoCartridge ; no cartridge -> jump 14: jmp (CART_RESET) ; we have a cartridge, exit and call the RESET routine of the cart 15: 16: ; in case we have no cartridge, proceed with initialisation 17: 18: @NoCartridge: 19: .if CompileComputer >= C64_GENERAL 20: stx VIC + VICII_O_ControlReg2 ; switch to 38 cols mode 21: ; this seems to be cosmetic only. If the C64 already has a visible 22: ; screen, one can clearly see that the RESET makes the left and 23: ; right border smaller on a RESET and/or JSR $FCE2 (SYS 64738) 24: jsr iIOINIT ; initialise the I/O area 25: .endif 26: 27: jsr iRAMTAS ; clear memory and determine RAM areas 28: jsr iRESTOR ; restore the KERNEL jump vectors 29: .if CompileComputer < C64_GENERAL 30: jsr iIOINIT ; initialise the I/O area 31: .endif 32: 33: ; Initialise the video 34: .if CompileComputer >= C64_02 35: jsr iCINT_WITH_PAL_NTSC ; initialise the video. Also make sure to determine PAL or NTSC, and adjust the timings accordingly 36: .else 37: jsr iCINT ; initialise the video. 38: .endif 39: cli 40: jmp (bRESTART) ; call BASIC 41: 42: ; Check if a cartridge is available. 43: ; For this, it checks for the "cartridge magic" 44: ; If there is a cartridge, this routine returns with Z=1 45: ; else with Z=0 46: ; 47: CheckCartridge: 48: ldx #END_Copy_CARTRIDGE_MAGIC - Copy_CARTRIDGE_MAGIC 49: @CheckNext: 50: lda Copy_CARTRIDGE_MAGIC - 1,x 51: cmp CART_MAGIC - 1,x 52: bne @NoCart 53: dex 54: bne @CheckNext 55: @NoCart: 56: rts 57: 58: ; Copy of the cartridge magic 59: ; CheckCartridge checks agains these characters 60: ; to find out if a cartridge is available. 61: ; 62: Copy_CARTRIDGE_MAGIC: 63: .if CompileComputer >= C64_GENERAL 64: asc80 "CBM" 65: .byte "80" 66: .else 67: .byte "A0" 68: asc80 "CBM" 69: .endif 70: END_Copy_CARTRIDGE_MAGIC: 71: 72: ; 73: ; B-23. Function Name: RESTOR 74: ; 75: ; Purpose: Restore default system and interrupt vectors 76: ; Call address: $FF8A (hex) 65418 (decimal) 77: ; Preparatory routines: None 78: ; Error returns: None 79: ; Stack requirements: 2 80: ; Registers affected: A, X, Y 81: ; 82: ; Description: This routine restores the default values of all system 83: ; vectors used in KERNAL and BASIC routines and interrupts. (See the Memory 84: ; Map for the default vector contents). The KERNAL VECTOR routine is used 85: ; to read and alter individual system vectors. 86: ; 87: ; How to Use: 88: ; 1) Call this routine. 89: ; 90: ; EXAMPLE: 91: ; JSR RESTOR 92: ; 93: iRESTOR: 94: ldx #<Copy_of_lCINV 95: ldy #>Copy_of_lCINV 96: clc 97: 98: ; B-39. Function Name: VECTOR 99: ; 100: ; Purpose: Manage RAM vectors 101: ; Call address: $FF8D (hex) 65421 (decimal) 102: ; Communication registers: X, Y 103: ; Preparatory routines: None 104: ; Error returns: None 105: ; Stack requirements: 2 106: ; Registers affected: A, X, Y 107: ; 108: ; 109: ; Description: This routine manages all system vector jump addresses 110: ; stored in RAM. Calling this routine with the the accumulator carry bit 111: ; set stores the current contents of the RAM vectors in a list pointed to 112: ; by the X and Y registers. When this routine is called with the carry 113: ; clear, the user list pointed to by the X and Y registers is transferred 114: ; to the system RAM vectors. The RAM vectors are listed in the memory map. 115: ; 116: ; +-----------------------------------------------------------------------+ 117: ; | NOTE: This routine requires caution in its use. The best way to use it| 118: ; | is to first read the entire vector contents into the user area, alter | 119: ; | the desired vectors, and then copy the contents back to the system | 120: ; | vectors. | 121: ; +-----------------------------------------------------------------------+ 122: ; 123: ; How to Use: 124: ; 125: ; READ THE SYSTEM RAM VECTORS 126: ; 127: ; 1) Set the carry. 128: ; 2) Set the X and y registers to the address to put the vectors. 129: ; 3) Call this routine. 130: ; 131: ; LOAD THE SYSTEM RAM VECTORS 132: ; 133: ; 1) Clear the carry bit. 134: ; 2) Set the X and Y registers to the address of the vector list in RAM 135: ; that must be loaded. 136: ; 3) Call this routine. 137: ; 138: ; 139: ; EXAMPLE: 140: ; ;CHANGE THE INPUT ROUTINES TO NEW SYSTEM 141: ; LDX #<USER 142: ; LDY #>USER 143: ; SEC 144: ; JSR VECTOR ;READ OLD VECTORS 145: ; LDA #<MYINP ;CHANGE INPUT 146: ; STA USER+10 147: ; LDA #>MYINP 148: ; STA USER+11 149: ; LDX #<USER 150: ; LDY #>USER 151: ; CLC 152: ; JSR VECTOR ;ALTER SYSTEM 153: ; ... 154: ; USER *=*+26 155: 156: iVECTOR: 157: ; remember the address where to load/store the vector list 158: stx zMEMUSS 159: sty zMEMUSS + 1 160: 161: ldy #END_Copy_of_lCINV - Copy_of_lCINV - 1 ; get number of bytes to copy 162: @Loop: lda lCINV,y 163: bcs @DoSet ; if C=0, write the buffer to the address at x/y 164: lda (zMEMUSS),y ; if C=1, get the data from x/y and write it to the system buffers 165: @DoSet: sta (zMEMUSS),y 166: sta lCINV,y 167: dey 168: bpl @Loop 169: rts 170: 171: ; the system vectors as set by default 172: 173: Copy_of_lCINV: 174: .addr KIRQ ; lCINV 175: .addr RUNSTOP_RESTORE ; lCNBINV 176: .addr KNMI ; lNMINV 177: .addr KOPEN ; lIOPEN 178: .addr KCLOSE ; lICLOSE 179: .addr KCHKIN ; lICHKIN 180: .addr KCHKOUT ; lICHKOUT 181: .addr KCLRCH ; lICLRCH 182: .addr KBASIN ; lIBASIN 183: .addr KBSOUT ; lIBSOUT 184: .addr KSTOP ; lISTOP 185: .addr KGETIN ; lIGETIN 186: .addr KCLALL ; lICLALL 187: .addr RUNSTOP_RESTORE ; lUSRCMD 188: .addr KLOAD ; lILOAD 189: .addr KSAVE ; lISAVE 190: END_Copy_of_lCINV: 191: 192: ; B.20. Function Name: RAMTAS 193: ; 194: ; Purpose: Perform RAM test 195: ; Call address: $FF87 (hex) 65415 (decimal) 196: ; Communication registers: A, X, Y 197: ; Preparatory routines: None 198: ; Error returns: None 199: ; Stack requirements: 2 200: ; Registers affected: A, X, Y 201: ; 202: ; Description: This routine is used to test RAM and set the top and 203: ; bottom of memory pointers accordingly. It also clears locations $0000 to 204: ; $0101 and $0200 to $03FF. It also allocates the cassette buffer, and sets 205: ; the screen base to $0400. Normally, this routine is called as part of the 206: ; initialization process of a Commodore 64 program cartridge. 207: ; 208: ; EXAMPLE: 209: ; JSR RAMTAS 210: ; 211: iRAMTAS: 212: ; clear zero page and $200-$3ff 213: lda #0 214: .if CompileComputer >= C64_GENERAL 215: tay 216: .else 217: tax 218: .endif 219: 220: @MemClearLoop: 221: 222: .if CompileComputer >= C64_GENERAL 223: sta 2,y ; on the C64, start with ZP address 2 so we do not overwrite $00/$01 (6510 on-chip I/O pins!) 224: sta $200,y 225: sta $300,y 226: iny 227: .else 228: sta 0,x 229: sta $200,x 230: sta $300,x 231: inx 232: .endif 233: bne @MemClearLoop 234: 235: ; set the cassette (tape) buffer address 236: ldx #<lTBUFFR 237: ldy #>lTBUFFR 238: stx zTAPE1 239: sty zTAPE1 + 1 240: 241: ; Check memory for writability by writing 242: ; a pattern to it ($55, then $AA). If the 243: ; addresses contain exactly these values afterwards, 244: ; we have working RAM. 245: 246: .if CompileComputer >= C64_GENERAL 247: tay ; y = 0 248: lda #(>lVIDEORAM)-1 249: sta zSTAL + 1 250: @IncHi: inc zSTAL + 1 251: @Loop: lda (zSTAL),y ; remember original value of the memory location 252: tax ; in X 253: 254: lda #$55 ; write $55 into memory location 255: sta (zSTAL),y 256: cmp (zSTAL),y ; still $55? 257: bne @NotEqual ; no, quit loop 258: 259: rol a ; test $AA pattern instead 260: sta (zSTAL),y 261: cmp (zSTAL),y ; still $AA? 262: bne @NotEqual ; no, quit loop 263: 264: ; 265: ; the old value is only restored if the memory is determined as RAM. 266: ; otherwise, either $55 or $AA remains at the last location. 267: ; this is in contrast to the VIC 20 implementation, which leaves all 268: ; bytes unchanged. 269: ; Ironically, for the VIC20, there is no difference if this byte is 270: ; restored or not. For the C64, however, there is a difference, as 271: ; the RAM under the ROM at $A000 is overwritten with $55 after this 272: ; function has been called if the BASIC ROM is switched on. 273: ; 274: txa ; restore old value 275: sta (zSTAL),y 276: 277: .if CompileComputer = C64_GS 278: nop 279: bne @IncHi 280: .else 281: iny ; proceed to next memory location 282: bne @Loop ; and do it again 283: .endif 284: beq @IncHi ; try next page 285: ; ------------------------------ 286: 287: @NotEqual: 288: tya ; low byte of failed addres 289: tax ; into X 290: ldy zSTAL + 1 ; high byte of failed address into y 291: clc ; (unneccessary, as we call iMEMTOP_Set, not iMEMTOP in the next line) 292: jsr iMEMTOP_Set ; set memory top to x/y 293: 294: lda #>lBASICRAM ; set BASIC start to $0800 295: sta lMEMSTR + 1 ; (low byte is already 0, as we just cleared the ZP) 296: 297: lda #>lVIDEORAM ; set video RAM start to $0400 298: sta lHIBASE 299: rts 300: 301: .else 302: 303: sta zSTAL ; zSTAL low = 0 (unneccessary, as we already cleared ZP to 0) 304: sta zTEMPX ; (unneccessary, as we already cleared ZP to 0) 305: sta lMEMSTR ; BASIC start low = 0 (unneccessary, as we already cleared ZP to 0) 306: tay ; Y = 0 307: 308: lda #>$0400 ; start memory test at the location $0400. 309: ; This is the first address where memory can be available on the VIC20, 310: ; if a 3 KB RAM expansion is present. 311: sta zSTAL + 1 312: 313: @MemTestLoop: 314: ; increment address to be tested. 315: ; Note that the VIC20 will actually start the test at $0401 with this, thus, $0400 will not be tested at all. 316: 317: inc zSTAL ; increment low byte of address to be tested 318: bne @SkipHighByte 319: inc zSTAL + 1 ; increment high byte, if necessary 320: 321: @SkipHighByte: 322: jsr CheckWritability ; check if byte is writeable RAM (C=1) or not (C=0) 323: 324: lda zTEMPX ; until we found (first) RAM, handle 325: beq @FindMemStart ; the test separately at @FindMemStart 326: 327: ; if we reach here, we have already found the start of RAM somewhere between $0400-$10FF. 328: ; Thus, we continue the loop until we found a non-RAM location 329: 330: bcs @MemTestLoop ; if we still have RAM, test the next location 331: 332: ; here, we found the end of RAM 333: 334: ldy zSTAL + 1 ; get end of RAM pointer into x/y 335: ldx zSTAL 336: cpy #>$2000 ; end of RAM below $2000? 337: bcc @Panic ; then panic, we have a severe problem, as we did not even find the RAM every VIC20 has! 338: 339: cpy #>$2100 ; end of RAM >= $2100? 340: bcs @MemConf2 ; yet, set "configuration type 2", expanded with more than 3 KB RAM 341: 342: ; we have an unexpanded VIC20 (or expanded with not more than 3KB) 343: ldy #>$1E00 ; put screen memory at $1E00 (- $1FFF) 344: sty lHIBASE 345: ; put memory top at $1E00 346: 347: @SetMemTop: 348: jmp iMEMTOP_Set 349: 350: @MemConf2: 351: lda #>$1200 ; set user basic start to $1200 352: sta lMEMSTR + 1 353: lda #>$1000 ; set screen memory to $1000 354: sta lHIBASE 355: bne @SetMemTop ; set memory top to what was determined (in x/y) 356: ; ------------------ 357: 358: @FindMemStart: 359: ; if we reach here, we are not sure if there is memory at $0400-$0FFF (3 KB expansion) 360: ; thus, we proceed when we have NOT yet found writeable RAM. 361: 362: bcc @MemTestLoop ; no RAM --> jump 363: 364: ; here, we have found the start of RAM 365: lda zSTAL + 1 ; remember the start of RAM 366: sta lMEMSTR + 1 ; at (lMEMSTR) 367: sta zTEMPX ; remember we already found start of RAM. 368: ; with this, we will not jump to @FindMemStart anymore 369: cmp #>$1100 370: bcc @MemTestLoop ; if start of RAM is below $1100, continue 371: 372: ; otherwise, we have a severe error, as RAM *must* start at $1000 in every VIC20. 373: ; Thus, stop booting with a: 374: 375: ; endless loop: stop boot 376: @Panic: 377: jsr SET_VIC_DEFAULTS 378: jmp @Panic 379: .endif 380: 381: 382: ; TODO 383: 384: TapeIrqVectors: 385: 386: .if CompileComputer = C64_GS 387: .addr NMI_End 388: .addr NMI_End 389: .addr NMI_End 390: .addr NMI_End 391: .else 392: 393: VecTapeIrqWritePreamble: 394: .addr TapeIrqWritePreamble 395: VecTapeIrqWrite: 396: .addr TapeIrqWrite 397: VecKIRQ: 398: .addr KIRQ 399: VecTapeIrqRead: 400: .addr TapeIrqRead 401: 402: .endif 403: 404: ; B-13. Function Name: IOINIT 405: ; 406: ; Purpose: Initialize I/O devices 407: ; Call Address: $FF84 (hex) 65412 (decimal) 408: ; Communication registers: None 409: ; Preparatory routines: None 410: ; Error returns: 411: ; Stack requirements: None 412: ; Registers affected: A, X, Y 413: ; 414: ; Description: This routine initializes all input/output devices and 415: ; routines. It is normally called as part of the initialization procedure 416: ; of a Commodore 64 program cartridge. 417: ; 418: ; EXAMPLE: 419: ; JSR IOINIT 420: ; 421: 422: iIOINIT: 423: .if CompileComputer >= C64_GENERAL 424: 425: ; clear all bits in the interrupt control register. 426: ; Thus, no CIA will generate any interrupts until 427: ; reprogrammed 428: lda #~CIA_ICR_BW_SET 429: sta CIA1 + CIA_O_ICR 430: sta CIA2 + CIA_O_ICR 431: 432: ; (A = $7F) 433: sta CIA1 + CIA_O_PA 434: 435: ; stop all timers (TA, TB) on CIA1 and CIA2 436: lda #CIA_CRA_B_ONESHOT ; is the same as CIA_CRB_B_ONESHOT! 437: sta CIA1 + CIA_O_CRA 438: sta CIA2 + CIA_O_CRA 439: 440: sta CIA1 + CIA_O_CRB 441: sta CIA2 + CIA_O_CRB 442: 443: ; Port B (PB) of CIA1 and CIA2 are inputs 444: ldx #$00 445: stx CIA1 + CIA_O_DDRB ; keyboard column 446: stx CIA2 + CIA_O_DDRB 447: 448: stx SID + SID_O_FiltMode 449: 450: ; Port A (PA) of CIA1 is output 451: dex ; X = $FF 452: stx CIA1 + CIA_O_DDRA ; keyboard row 453: 454: ; VIC reaches bank 0 ($0000-$1FFF), RS232 TXD is active. IEC lines are all inactive. 455: lda #CIA2_PA_B_VA14 | CIA2_PA_B_VA15 | CIA2_PA_B_RS232_TXD 456: sta CIA2 + CIA_O_PA ; IEC_REG_DATA_CLK_OUT 457: 458: lda #CIA2_PA_B_VA14 | CIA2_PA_B_VA15 | CIA2_PA_B_RS232_TXD | CIA2_PA_B_IEC_ATN_OUT | CIA2_PA_B_IEC_CLK_OUT | CIA2_PA_B_IEC_DATA_OUT ; not: CIA2_PA_B_IEC_CLK_IN and CIA2_PA_B_IEC_DATA_IN 459: sta CIA2 + CIA_O_DDRA ; IEC_DDR 460: 461: lda #P6510_B_LORAM | P6510_B_HIRAM | P6510_B_CHAREN | P6510_B_CASS_MOTOR | P6510_B_UNUSED 462: sta zR6510 463: lda #P6510_B_LORAM | P6510_B_HIRAM | P6510_B_CHAREN | P6510_B_CASS_WRITE | P6510_B_CASS_MOTOR 464: 465: sta zD6510 466: 467: iIOINIT_TIMER: 468: .if CompileComputer >= C64_02 469: lda lTVSFLG 470: beq LFDEC 471: lda #<DEFAULT_INIT_VALUE_CIA1_TA_PAL 472: .else 473: lda #<DEFAULT_INIT_VALUE_CIA1_TA_1MHZ 474: .endif 475: sta CIA1 + CIA_O_TALO 476: 477: .if CompileComputer >= C64_02 478: lda #>DEFAULT_INIT_VALUE_CIA1_TA_PAL 479: jmp LFDF3 480: LFDEC: lda #<DEFAULT_INIT_VALUE_CIA1_TA_NTSC 481: sta CIA1 + CIA_O_TALO 482: lda #>DEFAULT_INIT_VALUE_CIA1_TA_NTSC 483: LFDF3: sta CIA1 + CIA_O_TAHI 484: .else 485: lda #>DEFAULT_INIT_VALUE_CIA1_TA_1MHZ 486: sta CIA1 + CIA_O_TAHI 487: .endif 488: 489: .macro IOINIT_PATCH 490: lda #CIA_ICR_BW_SET |CIA_ICR_B_TA 491: sta CIA1 + CIA_O_ICR 492: lda CIA1 + CIA_O_CRA 493: and #CIA_CRA_B_50HZ ; clear everything but 50/60 Hz flag 494: ora #CIA_CRA_B_FORCE_LOAD | CIA_CRA_B_START ; start timer in continuous mode 495: sta CIA1 + CIA_O_CRA 496: jmp IecClkSet 497: .endmacro 498: 499: .if CompileComputer >= C64_02 500: jmp Patch_IOINIT 501: .else 502: IOINIT_PATCH 503: .endif 504: 505: .else 506: ; this is a VIC20 507: 508: lda #$7F 509: sta VIA1_IEC 510: sta VIA2_IEC 511: lda #$40 512: sta VIA2_ACR 513: lda #$40 514: sta VIA1_ACR 515: lda #$FE 516: sta VIA1_PCR 517: lda #$DE 518: sta VIA2_PCR 519: ldx #$00 520: stx VIA1_DDRB 521: ldx #$FF 522: stx VIA2_DDRB 523: ldx #$00 524: stx VIA2_DDRA 525: ldx #$80 526: stx VIA1_DDRA 527: ldx #$00 528: stx VIA1_PA_NO_HS 529: jsr IecClkClear 530: lda #$82 531: sta VIA1_IEC 532: jsr IecClkSet 533: 534: ;LFE39: 535: iIOINIT_TIMER: 536: lda #$C0 537: sta VIA2_IEC 538: lda #<DEFAULT_VIA2_T1 539: sta VIA2_T1CL 540: lda #>DEFAULT_VIA2_T1 541: sta VIA2_T1CH 542: rts 543: 544: .endif 545: 546: 547: ; B-30. Function Name: SETNAM 548: ; 549: ; Purpose: Set file name 550: ; Call address: $FFBD (hex) 65469 (decimal) 551: ; Communication registers: A, X, Y 552: ; Preparatory routines: 553: ; Stack requirements: 2 554: ; Registers affected: 555: ; 556: ; Description: This routine is used to set up the file name for the OPEN, 557: ; SAVE, or LOAD routines. The accumulator must be loaded with the length of 558: ; the file name. The X and Y registers must be loaded with the address of 559: ; the file name, in standard 6502 low-byte/high-byte format. The address 560: ; can be any valid memory address in the system where a string of 561: ; characters for the file name is stored. If no file name is desired, the 562: ; accumulator must be set to 0, representing a zero file length. The X and 563: ; Y registers can be set to any memory address in that case. 564: ; 565: ; How to Use: 566: ; 567: ; 1) Load the accumulator with the length of the file name. 568: ; 2) Load the X index register with the low order address of the file 569: ; name. 570: ; 3) Load the Y index register with the high order address. 571: ; 4) Call this routine. 572: ; 573: ; EXAMPLE: 574: ; 575: ; LDA #NAME2-NAME ;LOAD LENGTH OF FILE NAME 576: ; LDX #<NAME ;LOAD ADDRESS OF FILE NAME 577: ; LDY #>NAME 578: ; JSR SETNAM 579: ; 580: iSETNAM: 581: sta zFNLEN ; store name of file name 582: stx zFNADR ; and pointer to it 583: sty zFNADR + 1 584: rts 585: 586: ; B-28. Function Name: SETLFS 587: ; 588: ; Purpose: Set up a logical file 589: ; Call address: $FFBA (hex) 65466 (decimal) 590: ; Communication registers: A, X, Y 591: ; Preparatory routines: None 592: ; Error returns: None 593: ; Stack requirements: 2 594: ; Registers affected: None 595: ; 596: ; 597: ; Description: This routine sets the logical file number, device address, 598: ; and secondary address (command number) for other KERNAL routines. 599: ; The logical file number is used by the system as a key to the file 600: ; table created by the OPEN file routine. Device addresses can range from 0 601: ; to 31. The following codes are used by the Commodore 64 to stand for the 602: ; CBM devices listed below: 603: ; 604: ; 605: ; ADDRESS DEVICE 606: ; 607: ; 0 Keyboard 608: ; 1 Datassette(TM) 609: ; 2 RS-232C device 610: ; 3 CRT display 611: ; 4 Serial bus printer 612: ; 8 CBM serial bus disk drive 613: ; 614: ; 615: ; Device numbers 4 or greater automatically refer to devices on the 616: ; serial bus. 617: ; A command to the device is sent as a secondary address on the serial 618: ; bus after the device number is sent during the serial attention 619: ; handshaking sequence. If no secondary address is to be sent, the Y index 620: ; register should be set to 255. 621: ; 622: ; How to Use: 623: ; 624: ; 1) Load the accumulator with the logical file number. 625: ; 2) Load the X index register with the device number. 626: ; 3) Load the Y index register with the command. 627: ; 628: ; 629: ; 630: ; 631: ; EXAMPLE: 632: ; 633: ; FOR LOGICAL FILE 32, DEVICE #4, AND NO COMMAND: 634: ; LDA #32 635: ; LDX #4 636: ; LDY #255 637: ; JSR SETLFS 638: ; 639: ; 640: iSETLFS: 641: sta zLA ; store logical file number 642: stx zFA ; store device number (primary address) 643: sty zSA ; store secondary address 644: rts 645: 646: ; B-22. Function Name: READST 647: ; 648: ; Purpose: Read status word 649: ; Call address: $FFB7 (hex) 65463 (decimal) 650: ; Communication registers: A 651: ; Preparatory routines: None 652: ; Error returns: None 653: ; Stack requirements: 2 654: ; Registers affected: A 655: ; 656: ; Description: This routine returns the current status of the I/O devices 657: ; in the accumulator. The routine is usually called after new communication 658: ; to an I/O device. The routine gives you information about device status, 659: ; or errors that have occurred during the I/O operation. 660: ; The bits returned in the accumulator contain the following information: 661: ; (see table below) 662: ; 663: ; +---------+------------+---------------+------------+-------------------+ 664: ; | ST Bit | ST Numeric | Cassette | Serial | Tape Verify | 665: ; | Position| Value | Read | Bus R/W | + Load | 666: ; +---------+------------+---------------+------------+-------------------+ 667: ; | 0 | 1 | | time out | | 668: ; | | | | write | | 669: ; +---------+------------+---------------+------------+-------------------+ 670: ; | 1 | 2 | | time out | | 671: ; | | | | read | | 672: ; +---------+------------+---------------+------------+-------------------+ 673: ; | 2 | 4 | short block | | short block | 674: ; +---------+------------+---------------+------------+-------------------+ 675: ; | 3 | 8 | long block | | long block | 676: ; +---------+------------+---------------+------------+-------------------+ 677: ; | 4 | 16 | unrecoverable | | any mismatch | 678: ; | | | read error | | | 679: ; +---------+------------+---------------+------------+-------------------+ 680: ; | 5 | 32 | checksum | | checksum | 681: ; | | | error | | error | 682: ; +---------+------------+---------------+------------+-------------------+ 683: ; | 6 | 64 | end of file | EOI line | | 684: ; +---------+------------+---------------+------------+-------------------+ 685: ; | 7 | -128 | end of tape | device not | end of tape | 686: ; | | | | present | | 687: ; +---------+------------+---------------+------------+-------------------+ 688: ; 689: ; 690: ; 691: ; How to Use: 692: ; 693: ; 1) Call this routine. 694: ; 2) Decode the information in the A register as it refers to your pro- 695: ; gram. 696: ; 697: ; EXAMPLE: 698: ; 699: ; ;CHECK FOR END OF FILE DURING READ 700: ; JSR READST 701: ; AND #64 ;CHECK EOF BIT (EOF=END OF FILE) 702: ; BNE EOF ;BRANCH ON EOF 703: ; 704: iREADST: 705: lda zFA ; get device address 706: cmp #FILE_RS232 ; is it a RS232 device? 707: bne iREADST_Normal ; no, return regular status 708: 709: ; here, we have a RS232 device. 710: ; return the special status of the RS232 device 711: ; (not documented in the KERNAL description above!) 712: 713: lda lRSSTAT ; get RS232 status 714: .if CompileComputer >= C64_GENERAL 715: pha ; make sure to remember RS232 status 716: 717: ; Leaving this out for the VIC 20 is obviously a severe bug, which 718: ; makes iREADST for RS232 completely useless on it 719: 720: .endif 721: lda #$00 ; clear RS232 status 722: sta lRSSTAT 723: .if CompileComputer >= C64_GENERAL 724: pla ; get the RS232 status back 725: 726: ; Leaving this out for the VIC 20 is obviously a severe bug, which 727: ; makes iREADST for RS232 completely useless on it 728: 729: .endif 730: rts 731: 732: ; B-29. Function Name: SETMSG 733: ; 734: ; Purpose: Control system message output 735: ; Call address: $FF90 (hex) 65424 (decimal) 736: ; Communication registers: A 737: ; Preparatory routines: None 738: ; Error returns: None 739: ; Stack requirements: 2 740: ; Registers affected: A 741: ; 742: ; Description: This routine controls the printing of error and control 743: ; messages by the KERNAL. Either print error messages or print control mes- 744: ; sages can be selected by setting the accumulator when the routine is 745: ; called. FILE NOT FOUND is an example of an error message. PRESS PLAY ON 746: ; CASSETTE is an example of a control message. 747: ; Bits 6 and 7 of this value determine where the message will come from. 748: ; If bit 7 is 1, one of the error messages from the KERNAL is printed. If 749: ; bit 6 is set, control messages are printed. 750: ; 751: ; How to Use: 752: ; 753: ; 1) Set accumulator to desired value. 754: ; 2) Call this routine. 755: ; 756: ; EXAMPLE: 757: ; 758: ; LDA #$40 759: ; JSR SETMSG ;TURN ON CONTROL MESSAGES 760: ; LDA #$80 761: ; JSR SETMSG ;TURN ON ERROR MESSAGES 762: ; LDA #0 763: ; JSR SETMSG ;TURN OFF ALL KERNAL MESSAGES 764: ; 765: iSETMSG: 766: sta zNSGFLG 767: 768: ; in fact, these three commands belong to iREADST! 769: ; read the status (LFE1A) or set one or more status bits (LFE1C) 770: iREADST_Normal: 771: lda zSTATUS 772: SetStatus: 773: ora zSTATUS 774: sta zSTATUS 775: rts 776: 777: ; B-32. Function Name: SETTMO 778: ; 779: ; Purpose: Set IEEE bus card timeout flag 780: ; Call address: $FFA2 (hex) 65442 (decimal) 781: ; Communication registers: A 782: ; Preparatory routines: None 783: ; Error returns: None 784: ; Stack requirements: 2 785: ; Registers affected: None 786: ; +-----------------------------------------------------------------------+ 787: ; | NOTE: This routine is used ONLY with an IEEE add-on card! | 788: ; +-----------------------------------------------------------------------+ 789: ; Description: This routine sets the timeout flag for the IEEE bus. When 790: ; the timeout flag is set, the Commodore 64 will wait for a device on the 791: ; IEEE port for 64 milliseconds. If the device does not respond to the 792: ; Commodore 64's Data Address Valid (DAV) signal within that time the 793: ; Commodore 64 will recognize an error condition and leave the handshake 794: ; sequence. When this routine is called when the accumulator contains a 0 795: ; in bit 7, timeouts are enabled. A 1 in bit 7 will disable the timeouts. 796: ; 797: ; +-----------------------------------------------------------------------+ 798: ; | NOTE: The Commodore 64 uses the timeout feature to communicate that a | 799: ; | disk file is not found on an attempt to OPEN a file only with an IEEE | 800: ; | card. | 801: ; +-----------------------------------------------------------------------+ 802: ; 803: ; How to Use: 804: ; 805: ; TO SET THE TIMEOUT FLAG 806: ; 1) Set bit 7 of the accumulator to 0. 807: ; 2) Call this routine. 808: ; 809: ; TO RESET THE TIMEOUT FLAG 810: ; 1) Set bit 7 of the accumulator to 1. 811: ; 2) Call this routine. 812: ; 813: ; EXAMPLE: 814: ; 815: ; ;DISABLE TIMEOUT 816: ; LDA #0 817: ; JSR SETTMO 818: ; 819: iSETTMO: 820: sta lTIMOUT 821: rts 822: 823: 824: ; B-17. Function Name: MEMTOP 825: ; 826: ; Purpose: Set the top of RAM 827: ; Call address: $FF99 (hex) 65433 (decimal) 828: ; Communication registers: X, Y 829: ; Preparatory routines: None 830: ; Error returns: None 831: ; Stack requirements: 2 832: ; Registers affected: X, Y 833: ; 834: ; Description: This routine is used to set the top of RAM. When this 835: ; routine is called with the carry bit of the accumulator set, the pointer 836: ; to the top of RAM will be loaded into the X and Y registers. When this 837: ; routine is called with the accumulator carry bit clear, the contents of 838: ; the X and Y registers are loaded in the top of memory pointer, changing 839: ; the top of memory. 840: ; 841: ; EXAMPLE: 842: ; ;DEALLOCATE THE RS-232 BUFFER 843: ; SEC 844: ; JSR MEMTOP ;READ TOP OF MEMORY 845: ; DEX 846: ; CLC 847: ; JSR MEMTOP ;SET NEW TOP OF MEMORY 848: ; 849: iMEMTOP: 850: bcc iMEMTOP_Set ; c = 0 --> set MEMTOP 851: iMEMTOP_Get: 852: ldx lMEMSIZ ; get MEMTOP to x/y 853: ldy lMEMSIZ + 1 854: iMEMTOP_Set: 855: stx lMEMSIZ ; set MEMTOP from x/y 856: sty lMEMSIZ + 1 857: rts 858: 859: ; B-16. Function Name: MEMBOT 860: ; 861: ; Purpose: Set bottom of memory 862: ; Call address: $FF9C (hex) 65436 (decimal) 863: ; Communication registers: X, Y 864: ; Preparatory routines: None 865: ; Error returns: None 866: ; Stack requirements: None 867: ; Registers affected: X, Y 868: ; 869: ; Description: This routine is used to set the bottom of the memory. If 870: ; the accumulator carry bit is set when this routine is called, a pointer 871: ; to the lowest byte of RAM is returned in the X and Y registers. On the 872: ; unexpanded Commodore 64 the initial value of this pointer is $0800 873: ; (2048 in decimal). If the accumulator carry bit is clear (-O) when this 874: ; routine is called, the values of the X and Y registers are transferred to 875: ; the low and high bytes, respectively, of the pointer to the beginning of 876: ; RAM. 877: ; 878: ; 879: ; 880: ; How to Use: 881: ; TO READ THE BOTTOM OF RAM 882: ; 1) Set the carry. 883: ; 2) Call this routine. 884: ; 885: ; TO SET THE BOTTOM OF MEMORY 886: ; 1) Clear the carry. 887: ; 2) Call this routine. 888: ; 889: ; EXAMPLE: 890: ; 891: ; ;MOVE BOTTOM OF MEMORY UP 1 PAGE 892: ; SEC ;READ MEMORY BOTTOM 893: ; JSR MEMBOT 894: ; INY 895: ; CLC ;SET MEMORY BOTTOM TO NEW VALUE 896: ; JSR MEMBOT 897: ; 898: iMEMBOT: 899: bcc @Set ; c = 0 --> set MEMBOT 900: 901: ldx lMEMSTR ; get MEMBOT to x/y 902: ldy lMEMSTR + 1 903: 904: @Set: stx lMEMSTR ; set MEMBOT from x/y 905: sty lMEMSTR + 1 906: rts 907: 908: 909: .if CompileComputer < C64_GENERAL 910: ; 911: ; Test if the memory location pointed to by (zSTAL),y is writable RAM. 912: ; For this, we write $55, then $AA into the location. After each write, 913: ; we test if the memory is $55 and $AA, respectively. 914: ; The memory location is left unchanged (that is, the old value is written 915: ; back to it), regardless of the outcome of the test. 916: ; 917: ; If the area is determined as RAM, return with c=1, else c=0. 918: ; 919: CheckWritability: 920: lda (zSTAL),y ; remember original value of the memory location 921: tax ; in X 922: 923: lda #$55 ; write $55 into memory location 924: sta (zSTAL),y 925: cmp (zSTAL),y ; still $55? 926: bne @NotEqual ; no, quit loop 927: 928: ror a ; test $AA pattern instead 929: sta (zSTAL),y 930: cmp (zSTAL),y ; still $AA? 931: bne @NotEqual ; no, quit loop 932: 933: .byte $A9 ; with next byte: "lda #$18". Make sure the CLC is not executed. 934: 935: @NotEqual: 936: clc ; return: There was a difference 937: 938: txa ; restore old value 939: sta (zSTAL),y 940: rts 941: .endif 942: 943: ; 6502 NMI routine 944: ; This routine is called whenever an NMI occurs. 945: ; 946: NMI: sei ; block IRQ 947: jmp (lNMINV) ; normally points to KNMI 948: 949: KNMI: pha ; save A, X and Y onto the stack 950: txa 951: pha 952: tya 953: pha 954: 955: .if CompileComputer >= C64_GENERAL 956: ; clear all bits in the interrupt control register to prevent further interrupts 957: lda #~CIA_ICR_BW_SET 958: sta CIA2 + CIA_O_ICR 959: 960: ; check if CIA2 generated this NMI 961: ldy CIA2 + CIA_O_ICR 962: bmi NMI_FROM_IO ; CIA2 generated the NMI, process it 963: .else 964: ; check if VIA1 generated this NMI 965: lda VIA1_IFR 966: bpl LFEFF 967: and VIA1_IEC 968: tax 969: and #$02 970: beq NMI_FROM_IO 971: .endif 972: 973: jsr CheckCartridge ; is there a cartridge (with magic) installed at $8000 (C64) / $A000 (VIC-20)? 974: bne @NoCartridge ; no, skip 975: jmp (CART_NMI) ; yes, let the cartridge process the NMI 976: 977: @NoCartridge: 978: .if CompileComputer >= C64_GENERAL 979: jsr iUDTIM_CheckRunStop 980: .else 981: bit VIA1_PA 982: jsr iUDTIM 983: .endif 984: jsr kSTOP 985: bne LFEFF 986: 987: RUNSTOP_RESTORE: 988: jsr iRESTOR 989: jsr iIOINIT 990: jsr iCINT 991: jmp (bRESTART + 2) 992: 993: NMI_FROM_IO: 994: 995: .if CompileComputer >= C64_GENERAL 996: LFEFF: 997: ; TODO combine more? 998: 999: ; TODO follow logic (currently, there is no description *why* these tests are done!) 1000: 1001: tya ; A := Y, which has contents of CIA2 + CIA_O_ICR here 1002: and lENABL ; only check bits that are set in lENABL 1003: tax 1004: 1005: and #CIA_ICR_B_TA ; check if TA of CIA2 generated the interrupt 1006: beq @NoTimerAUnderflow ; no -> branch, next test 1007: 1008: lda RS232_TXD_REG 1009: and #~CIA2_PA_B_RS232_TXD 1010: ora zNXTBIT 1011: sta RS232_TXD_REG 1012: 1013: ; clear all interrupt sources of CIA2 that are currently set 1014: lda lENABL ; get enabled interrupt sources 1015: sta CIA2 + CIA_O_ICR 1016: 1017: txa 1018: and #CIA_ICR_B_FLAG | CIA_ICR_B_TB ; check if timer B or FLAG generated the interrupt 1019: beq @Continue ; none -> branch 1020: 1021: and #CIA_ICR_B_TB ; check if timer B generated the interrupt 1022: beq @IntFromFlag ; no -> branch 1023: 1024: jsr LFED6 1025: jmp @Continue 1026: 1027: @IntFromFlag: 1028: jsr LFF07 1029: 1030: @Continue: 1031: jsr LEEBB 1032: jmp @ClearAllCIA2Interrupts 1033: 1034: @NoTimerAUnderflow: 1035: txa 1036: and #CIA_ICR_B_TB ; check if TB of CIA2 generated the interrupt 1037: beq @NoTimerBUnderflow ; no -> branch, next test 1038: jsr LFED6 1039: jmp @ClearAllCIA2Interrupts 1040: 1041: @NoTimerBUnderflow: 1042: txa 1043: and #CIA_ICR_B_FLAG ; check if FLAG of CIA2 generated the interrupt 1044: beq @ClearAllCIA2Interrupts ; no -> branch, next test 1045: jsr LFF07 1046: 1047: @ClearAllCIA2Interrupts: 1048: ; clear all interrupt sources of CIA2 that are currently set 1049: lda lENABL ; get enabled interrupt sources 1050: sta CIA2 + CIA_O_ICR 1051: 1052: .else 1053: 1054: lda VIA1_IEC 1055: ora #$80 1056: pha 1057: lda #$7F 1058: sta VIA1_IEC 1059: txa 1060: and #$40 1061: beq LFF02 1062: lda #$CE 1063: ora zNXTBIT 1064: sta VIA1_PCR 1065: lda VIA1_T1CL 1066: pla 1067: sta VIA1_IEC 1068: jsr LEEBB 1069: LFEFF: 1070: jmp NMI_End 1071: ; ----------------------- 1072: 1073: LFF02: txa 1074: and #$20 1075: beq @LFF2C 1076: lda VIA1_PB 1077: and #$01 1078: sta zINBIT 1079: lda VIA1_T2CL 1080: sbc #$16 1081: adc lBAUDOF 1082: sta VIA1_T2CL 1083: lda VIA1_T2CH 1084: adc lBAUDOF + 1 1085: sta VIA1_T2CH 1086: pla 1087: sta VIA1_IEC 1088: jsr LEF59 1089: jmp NMI_End 1090: @LFF2C: txa 1091: and #$10 1092: beq NMI_End 1093: lda lM51CTR 1094: and #$0F 1095: bne @LFF38 1096: @LFF38: asl a 1097: tax 1098: lda LFEC2 - 2,x 1099: sta VIA1_T2CL 1100: lda LFEC2 - 1,x 1101: sta VIA1_T2CH 1102: lda VIA1_PB 1103: pla 1104: ora #$20 1105: and #$EF 1106: sta VIA1_IEC 1107: ldx lBITNUM 1108: stx zBITC1 1109: .endif 1110: 1111: NMI_End: 1112: pla 1113: tay 1114: pla 1115: tax 1116: pla 1117: rti 1118: 1119: LFEC2: 1120: 1121: .if CompileComputer >= C64_GENERAL 1122: 1123: .if CompileComputer >= C64_02 1124: .word $27C1 1125: .word $1A3E 1126: .word $11C5 1127: .word $0E74 1128: .word $0CED 1129: .word $0645 1130: .word $02F0 1131: .word $0146 1132: .word $00B8 1133: .word $0071 1134: .else 1135: .word $26AC 1136: .word $19A7 1137: .word $115D 1138: .word $0E1F 1139: .word $0CA1 1140: .word $061F 1141: .word $02DD 1142: .word $013D 1143: .word $00B2 1144: .word $006C 1145: 1146: .endif 1147: 1148: .else 1149: 1150: .if CompileComputer >= VIC20_07 1151: 1152: .word $2AE6 1153: .word $1C78 1154: .word $1349 1155: .word $0FB1 1156: .word $0E0A 1157: .word $06D3 1158: .word $0338 1159: .word $016A 1160: .word $00D0 1161: .word $0083 1162: .word $0036 1163: 1164: .else 1165: 1166: .word $2792 1167: .word $1A40 1168: .word $11C6 1169: .word $0E74 1170: .word $0CEE 1171: .word $0645 1172: .word $02F1 1173: .word $0146 1174: .word $00B8 1175: .word $0071 1176: .word $002A 1177: 1178: .endif 1179: 1180: .endif 1181: 1182: 1183: .if CompileComputer >= C64_GENERAL 1184: LFED6: lda CIA2 + CIA_O_PB 1185: and #$01 1186: sta zINBIT 1187: lda CIA2 + CIA_O_TBLO 1188: sbc #$1C 1189: adc lBAUDOF 1190: sta CIA2 + CIA_O_TBLO 1191: lda CIA2 + CIA_O_TBHI 1192: adc lBAUDOF + 1 1193: sta CIA2 + CIA_O_TBHI 1194: lda #$11 1195: sta CIA2 + CIA_O_CRB 1196: 1197: ; clear all interrupt sources of CIA2 that are currently set 1198: lda lENABL ; get enabled interrupt sources 1199: sta CIA2 + CIA_O_ICR 1200: 1201: lda #$FF 1202: sta CIA2 + CIA_O_TBLO 1203: sta CIA2 + CIA_O_TBHI 1204: jmp LEF59 1205: LFF07: 1206: .if CompileComputer = C64_01 1207: lda lM51CTR 1208: and #$0F 1209: bne LFF1A 1210: .endif 1211: lda lM51AJB 1212: sta CIA2 + CIA_O_TBLO 1213: lda lM51AJB + 1 1214: .if CompileComputer = C64_01 1215: jmp LFF25 1216: LFF1A: asl a 1217: tax 1218: lda LFEC2 - 2,x 1219: sta CIA2 + CIA_O_TBLO 1220: lda LFEC2 - 1,x 1221: LFF25: 1222: .endif 1223: sta CIA2 + CIA_O_TBHI 1224: lda #$11 1225: sta CIA2 + CIA_O_CRB 1226: 1227: lda #CIA_ICR_B_FLAG | CIA_ICR_B_TB 1228: eor lENABL 1229: sta lENABL 1230: 1231: lda #$FF 1232: sta CIA2 + CIA_O_TBLO 1233: sta CIA2 + CIA_O_TBHI 1234: ldx lBITNUM 1235: stx zBITC1 1236: rts 1237: 1238: .if CompileComputer >= C64_02 1239: LFF2E: tax 1240: lda lM51AJB + 1 1241: rol a 1242: tay 1243: txa 1244: adc #<200 1245: sta lBAUDOF 1246: tya 1247: adc #>200 1248: sta lBAUDOF + 1 1249: rts 1250: .endif 1251: 1252: .segment "TapeFakeFiller" 1253: nop 1254: nop 1255: 1256: ; FillUntil KERNAL_START + $1F43, $EA 1257: .segment "TapeFakeIrq" 1258: 1259: ; This is a faked IRQ entry point. It is used by the tape routine to execute the IRQ routine, 1260: ; returning to a predefined address afterwards. 1261: ; 1262: ; When this address is called (JMPed to), the return address - 1 is already on the stack. 1263: ; This routine has to set a flag register on the stack, making sure that the B bit is unset 1264: ; forcing a processing of an IRQ (and not of a BRK instruction) 1265: ; 1266: FakeIRQ: 1267: php ; push flag register onto stack 1268: 1269: ; now, manipulate the flag register making sure B is unset 1270: 1271: pla ; get it back into the Accu 1272: and #~A6502_FLAGS_B ; make sure B is unset 1273: pha ; store the flag register back onto the stack 1274: 1275: 1276: .endif 1277: 1278: ; 6502 IRQ routine 1279: ; This routine is called whenever an IRQ occurs. 1280: ; 1281: IRQ: pha ; save A, X and Y onto stack 1282: txa 1283: pha 1284: tya 1285: pha 1286: 1287: tsx ; SP -> X 1288: lda lSTACK + 4,x ; Read status register from stack 1289: and #A6502_FLAGS_B ; check BRK flag 1290: beq @isIRQ ; BRK flag is 0 --> it was an IRQ 1291: 1292: jmp (lCNBINV) ; BRK flag was 1, process the BRK instruction 1293: 1294: @isIRQ: jmp (lCINV) ; process the IRQ. Normally, this points to KIRQ 1295: 1296: 1297: .if CompileComputer >= C64_GENERAL 1298: .if CompileComputer >= C64_02 1299: 1300: ; B-7. Function Name: CINT 1301: ; 1302: ; Purpose: Initialize screen editor & 6567 video chip 1303: ; Call address: $FF81 (hex) 65409 (decimal) 1304: ; Communication registers: None 1305: ; Preparatory routines: None 1306: ; Error returns: None 1307: ; Stack requirements: 4 1308: ; Registers affected: A, X, Y 1309: ; 1310: ; 1311: ; Description: This routine sets up the 6567 video controller chip in the 1312: ; Commodore 64 for normal operation. The KERNAL screen editor is also 1313: ; initialized. This routine should be called by a Commodore 64 program 1314: ; cartridge. 1315: ; 1316: ; How to Use: 1317: ; 1318: ; 1) Call this routine. 1319: ; 1320: ; EXAMPLE: 1321: ; 1322: ; JSR CINT 1323: ; JMP RUN ;BEGIN EXECUTION 1324: ; 1325: ; NOTE: iCINT_WITH_PAL_NTSC is an *extended* version. 1326: ; It determines if there is a 6567 (NTSC) or 6569 (PAL) VIC chip. 1327: ; It stores the result in lTVSFLG (TV Standard FLaG), with 1328: ; 0 = NTSC, 1 = PAL. 1329: ; Then, it reprograms the CIA timer for PAL or NTSC. 1330: ; 1331: iCINT_WITH_PAL_NTSC: 1332: jsr iCINT 1333: 1334: @WaitForRaster: 1335: lda VIC + VICII_O_Raster 1336: bne @WaitForRaster 1337: lda VIC + VICII_O_IRQFlags 1338: and #$01 1339: sta lTVSFLG 1340: jmp iIOINIT_TIMER 1341: 1342: ; Remainder of iIOINIT. As the code become too large because of the PAL/NTSC 1343: ; implementation, this patch is here now. 1344: ; 1345: Patch_IOINIT: 1346: IOINIT_PATCH 1347: .endif 1348: .endif 1349: 1350: .if CompileComputer >= C64_GENERAL 1351: 1352: ; FillUntil KERNAL_START + $1F80 1353: .segment "KernalJumpTable" 1354: 1355: .byte VERSION_FF80 ; a version number for the KERNAL 1356: 1357: ; here, the KERNAL jump table begins 1358: ; 1359: 1360: 1361: ; the VIC-20 does not know CINT, IOINIT and RAMTAS, as these were added with the C64: 1362: 1363: kCINT: 1364: .if CompileComputer >= C64_02 1365: ; on C64 >= -02 ROM, determine if this is a PAL or an NTSC machine, 1366: ; and set the IRQ timings accordingly. 1367: ; Afterwards, iCINT is called. 1368: jmp iCINT_WITH_PAL_NTSC 1369: .else 1370: ; for C64 with -01 ROM, iCINT is called directly. 1371: jmp iCINT 1372: .endif 1373: 1374: kIOINIT: jmp iIOINIT 1375: kRAMTAS: jmp iRAMTAS 1376: 1377: .else 1378: 1379: ; FillUntil $FF8A,FILL_FFXX 1380: 1381: .endif 1382: 1383: .segment "KernalJumpTable2" 1384: 1385: ; here, the KERNAL jump table common to VIC20 and C64 begins 1386: 1387: kRESTOR: jmp iRESTOR 1388: kVECTOR: jmp iVECTOR 1389: kSETMSG: jmp iSETMSG 1390: kSECOND: jmp iSECOND 1391: kTKSA: jmp iTKSA 1392: kMEMTOP: jmp iMEMTOP 1393: kMEMBOT: jmp iMEMBOT 1394: kSCNKEY: jmp iSCNKEY 1395: kSETTMO: jmp iSETTMO 1396: kACPTR: 1397: .ifdef JIFFY 1398: jmp JDLFBAA 1399: .else 1400: jmp iACPTR 1401: .endif 1402: kCIOUT: jmp iCIOUT 1403: kUNTLK: jmp iUNTLK 1404: kUNLSN: jmp iUNLSN 1405: kLISTEN: jmp iLISTEN 1406: kTALK: jmp iTALK 1407: kREADST: jmp iREADST 1408: kSETLFS: jmp iSETLFS 1409: kSETNAM: jmp iSETNAM 1410: kOPEN: jmp (lIOPEN) 1411: kCLOSE: jmp (lICLOSE) 1412: kCHKIN: jmp (lICHKIN) 1413: kCHKOUT: jmp (lICKOUT) 1414: kCLRCHN: jmp (lICLRCH) 1415: kCHRIN: jmp (lIBASIN) 1416: kCHROUT: jmp (lIBSOUT) 1417: kLOAD: jmp iLOAD 1418: kSAVE: jmp iSAVE 1419: kSETTIM: jmp iSETTIM 1420: kRDTIM: jmp iRDTIM 1421: kSTOP: jmp (lISTOP) 1422: kGETIN: jmp (lIGETIN) 1423: kCLALL: jmp (lICLALL) 1424: kUDTIM: jmp iUDTIM 1425: kSCREEN: jmp iSCREEN 1426: kPLOT: jmp iPLOT 1427: kIOBASE: jmp iIOBASE 1428: 1429: .if (CompileComputer >= C64_GENERAL) .AND (.NOT .defined(C64JAPAN)) 1430: .byte "RR" ; Robert Russell 1431: .if CompileComputer = C64_4064 1432: .byte 0,0 1433: .else 1434: .byte "BY" ; Bob Yannes 1435: .endif 1436: .endif 1437: 1438: ; FillUntil $FFFA,FILL_FFXXa 1439: .segment "Int6502" 1440: 1441: .addr NMI ; 6502 NMI vector 1442: .addr RESET ; 6502 RESET vector 1443: .addr IRQ ; 6502 IRQ vector