c64.a65.full

     1:          .setcpu "6502"
     2:  
     3:  ;       .include "../asm6502.inc"
     4:  ASM_JMP = $4C
     5:  ASM_BIT2 = $24
     6:  ASM_BIT3 = $2C
     7:  
     8:  ; Flags of the 6502
     9:  A6502_FLAGS_N = $80     ; Negative
    10:  A6502_FLAGS_V = $40     ; oVerflow
    11:  A6502_FLAGS_R = $20     ; Reserved
    12:  A6502_FLAGS_B = $10     ; Break (only valid on stack after BRK/IRQ, otherwise 0)
    13:  A6502_FLAGS_D = $08     ; Decimal
    14:  A6502_FLAGS_I = $04     ; Interrupt
    15:  A6502_FLAGS_Z = $02     ; Zero
    16:  A6502_FLAGS_C = $01     ; Carry
    17:  ;       .include "../petscii.inc"
    18:  ASC_LF          = $0A
    19:  ASC_CR          = $0D
    20:  ASC_RVS         = $12
    21:  ASC_HOME        = $13
    22:  ASC_INSDEL      = $14
    23:  
    24:  ASC_LOWERCASE   = $0E
    25:  ASC_UPPERCASE   = $8E
    26:  ASC_DISALLOW_LOWERCASE = $08
    27:  ASC_ALLOW_LOWERCASE    = $09
    28:  
    29:  ASC_CURSORLEFTRIGHT = $1D
    30:  ASC_CURSORUPDOWN    = $11
    31:  
    32:  .if .defined(C64JAPAN)
    33:  ASC_PI          = $B0
    34:  .else
    35:  ASC_PI          = $DE
    36:  .endif
    37:  
    38:  KEY_NONE        = $40
    39:  KEY_STOP        = $03
    40:  
    41:  PETSCII_CRSR_RIGHT = $1D
    42:  
    43:  ;       .include "../macros.inc"
    44:  ; htasc - set the hi bit on the last byte of a string for termination
    45:  ; (by Tom Greene)
    46:  .macro htasc str
    47:          .repeat .strlen(str)-1,I
    48:                  .byte   .strat(str,I)
    49:          .endrep
    50:          .byte   .strat(str,.strlen(str)-1) | $80
    51:  .endmacro
    52:  
    53:  .macro htasc_floppy_error str
    54:          .byte   .strat(str,0) | $80
    55:          .repeat .strlen(str)-2,I
    56:                  .byte   .strat(str,I + 1)
    57:          .endrep
    58:          .byte   .strat(str,.strlen(str)-1) | $80
    59:  .endmacro
    60:  
    61:  ; For every token, a byte gets put into segment "DUMMY".
    62:  ; This way, we count up with every token. The DUMMY segment
    63:  ; doesn't get linked into the binary.
    64:  .macro init_token_tables
    65:          .segment "VECTORS"
    66:  TOKEN_ADDRESS_TABLE:
    67:          .segment "KEYWORDS"
    68:  TOKEN_NAME_TABLE:
    69:                  .segment "DUMMY"
    70:  DUMMY_START:
    71:  .endmacro
    72:  
    73:  ; optionally define token symbol
    74:  ; count up token number
    75:  .macro define_token token
    76:          .segment "DUMMY"
    77:                  .ifnblank token
    78:  token := <(*-DUMMY_START)+$80
    79:                  .endif
    80:                  .res 1; count up in any case
    81:  .endmacro
    82:  
    83:  ; lay down a keyword, optionally define a token symbol
    84:  .macro keyword key, token
    85:                  .segment "KEYWORDS"
    86:                  htasc   key
    87:                  define_token token
    88:  .endmacro
    89:  
    90:  ; lay down a keyword and an address (RTS style),
    91:  ; optionally define a token symbol
    92:  .macro keyword_rts key, vec, token
    93:          .segment "VECTORS"
    94:                  .word   vec-1
    95:                  keyword key, token
    96:  .endmacro
    97:  
    98:  ; lay down a keyword and an address,
    99:  ; optionally define a token symbol
   100:  .macro keyword_addr key, vec, token
   101:          .segment "VECTORS"
   102:                  .addr   vec
   103:                  keyword key, token
   104:  .endmacro
   105:  
   106:  .macro count_tokens
   107:          .segment "DUMMY"
   108:  NUM_TOKENS := <(*-DUMMY_START)
   109:  .endmacro
   110:  
   111:  .macro init_error_table
   112:          .segment "DUMMY"
   113:  DUMMY_START_ERROR:
   114:  
   115:          .segment "ERROR"
   116:  ERROR_MESSAGES:
   117:  .endmacro
   118:  
   119:  .ifdef CBM2_EXT_FILE_ERRORS
   120:   .macro define_error_token token
   121:          .segment "DUMMY"
   122:                  .ifnblank token
   123:  token := <(*-DUMMY_START_ERROR + 1)
   124:                  .endif
   125:                  .res 1; count up in any case
   126:   .endmacro
   127:  
   128:   .macro define_error error, msg, addr
   129:          .segment "ERROR"
   130:  addr := *
   131:                  htasc msg
   132:                  define_error_token error
   133:   .endmacro
   134:  
   135:  .else
   136:   .macro define_error error, msg, addr
   137:          .segment "ERROR"
   138:  error := <(*-ERROR_MESSAGES)
   139:                  htasc msg
   140:   .endmacro
   141:  
   142:  .endif
   143:  
   144:  ;---------------------------------------------
   145:  ; set the MSB of every byte of a string
   146:  .macro asc80 str
   147:          .repeat .strlen(str),I
   148:                  .byte   .strat(str,I)+$80
   149:          .endrep
   150:  .endmacro
   151:  
   152:  
   153:  ;       .include "defines.inc"
   154:  ; .include "defines-c64vic20.inc"
   155:  
   156:  COMPUTER_UNKNOWN=0
   157:  
   158:  VIC20_GENERAL=COMPUTER_UNKNOWN + $10
   159:  VIC20_02=VIC20_GENERAL + 2
   160:  VIC20_06=VIC20_GENERAL + 6
   161:  VIC20_07=VIC20_GENERAL + 7
   162:  
   163:  C64_GENERAL=VIC20_GENERAL + $20
   164:  C64_01=C64_GENERAL + 1
   165:  C64_02=C64_GENERAL + 2
   166:  C64_03=C64_GENERAL + 3
   167:  C64_SX64=C64_GENERAL + 4
   168:  C64_4064=C64_GENERAL + 5
   169:  C64_GS=C64_GENERAL + 6
   170:  
   171:  .ifdef vic20
   172:  CompileComputer=VIC20_GENERAL + vic20
   173:  .elseif .defined(c64)
   174:          .if c64 = 4064
   175:  CompileComputer=C64_4064
   176:          .else
   177:  CompileComputer=C64_GENERAL + c64
   178:          .endif
   179:  .endif
   180:  
   181:  .ifdef sx64
   182:  CompileComputer=C64_SX64
   183:  c64 = sx64
   184:  .endif
   185:  
   186:  .ifdef c64gs
   187:  CompileComputer=C64_GS
   188:  c64 = c64gs
   189:  .endif
   190:  
   191:  .ifndef CompileComputer
   192:  CompileComputer=COMPUTER_UNKNOWN
   193:  .endif
   194:  
   195:  .macro FillCount count,filler
   196:          .repeat count
   197:                  .ifblank filler
   198:                          .byte DRIVEFILLER
   199:                  .else
   200:                          .byte filler
   201:                  .endif
   202:          .endrep
   203:  .endmacro
   204:  
   205:  .macro FillUntil address,filler
   206:          FillCount address-*,filler
   207:  .endmacro
   208:  
   209:  .macro FillNOP count
   210:          FillCount count,$EA
   211:  .endmacro
   212:  
   213:  IEEE_LISTEN    = $20    ; on ATN, with primary address
   214:  IEEE_TALK      = $40    ; on ATN, with primary address
   215:  IEEE_OPEN      = $60    ; on ATN, with secondary address
   216:  IEEE_CLOSE     = $E0    ; on ATN, with primary address
   217:  IEEE_SECONDARY = $F0    ; on ATN, with secondary address
   218:  
   219:  IEEE_LOAD      = IEEE_OPEN + 0
   220:  IEEE_SAVE      = IEEE_OPEN + 1
   221:  
   222:  IEEE_UNLISTEN = IEEE_LISTEN + $1F
   223:  IEEE_UNTALK   = IEEE_TALK   + $1F
   224:  
   225:  STATUS_IEC_DEVICE_NOT_PRESENT        = $80
   226:  STATUS_IEC_EOI                       = $40
   227:  STATUS_IEC_TIMEOUT_READ              = $02
   228:  STATUS_IEC_TIMEOUT_WRITE             = $01
   229:  
   230:  STATUS_VERIFY                        = $10
   231:  
   232:  STATUS_TAPE_EOT                      = $80
   233:  STATUS_TAPE_EOF                      = $40 ; not on LOAD and VERIFY
   234:  STATUS_TAPE_CHKSUM_ERR               = $20
   235:  STATUS_TAPE_UNRECOVERABLE_READ_ERROR = $10
   236:  STATUS_TAPE_LONG_BLOCK               = $08
   237:  STATUS_TAPE_SHORT_BLOCK              = $04
   238:  
   239:  
   240:  FREQUENCY_1MHZ = 1000000
   241:  FREQUENCY_NTSC = 1022700
   242:  FREQUENCY_PAL  =  985248
   243:  
   244:  DEFAULT_INIT_VALUE_CIA1_TA_1MHZ = ((FREQUENCY_1MHZ + 59) / 60) ; $411B
   245:  DEFAULT_INIT_VALUE_CIA1_TA_NTSC = ((FREQUENCY_NTSC + 59) / 60) ; $4295
   246:  DEFAULT_INIT_VALUE_CIA1_TA_PAL  = ((FREQUENCY_PAL  + 59) / 60) ; $4025
   247:  
   248:  .if CompileComputer=C64_01
   249:  DRIVEFILLER=$AA
   250:  VERSION_FF80=$AA
   251:  VERSION_E4AC=$2B
   252:  BASIC_END := $E3A2
   253:  SET_COLOR_FRAME := COL_LIGHTBLUE
   254:  SET_COLOR_BACKGROUND := COL_BLUE
   255:  TEXT_SHIFTRUNSTOP = TEXT_LOADRUN
   256:  END_TEXT_SHIFTRUNSTOP = END_TEXT_LOADRUN
   257:  
   258:  DEFAULT_COLOR := COL_LIGHTBLUE
   259:  
   260:  .elseif CompileComputer=C64_02
   261:  DRIVEFILLER=$AA
   262:  VERSION_FF80=0
   263:  BASIC_END := $E3A2
   264:  TEXT_SHIFTRUNSTOP = TEXT_LOADRUN
   265:  END_TEXT_SHIFTRUNSTOP = END_TEXT_LOADRUN
   266:    .if .defined(C64JAPAN)
   267:  VERSION_E4AC=$0
   268:  SET_COLOR_FRAME := COL_CYAN
   269:  SET_COLOR_BACKGROUND := COL_WHITE
   270:  DEFAULT_COLOR := COL_BLUE
   271:    .else
   272:  VERSION_E4AC=$5C
   273:  SET_COLOR_FRAME := COL_LIGHTBLUE
   274:  SET_COLOR_BACKGROUND := COL_BLUE
   275:  DEFAULT_COLOR := COL_LIGHTBLUE
   276:    .endif
   277:  
   278:  .elseif CompileComputer=C64_03
   279:  DRIVEFILLER=$AA
   280:  VERSION_FF80=3
   281:  VERSION_E4AC=$81
   282:  BASIC_END := $E3A2
   283:  SET_COLOR_FRAME := COL_LIGHTBLUE
   284:  SET_COLOR_BACKGROUND := COL_BLUE
   285:  TEXT_SHIFTRUNSTOP = TEXT_LOADRUN
   286:  END_TEXT_SHIFTRUNSTOP = END_TEXT_LOADRUN
   287:  
   288:  DEFAULT_COLOR := COL_LIGHTBLUE
   289:  
   290:  .elseif CompileComputer=C64_4064
   291:  DRIVEFILLER=$AA
   292:  VERSION_FF80=$64
   293:  VERSION_E4AC=$63
   294:  BASIC_END := $E3A2
   295:  SET_COLOR_FRAME := COL_BLACK
   296:  SET_COLOR_BACKGROUND := COL_BLACK
   297:  TEXT_SHIFTRUNSTOP = TEXT_LOADRUN
   298:  END_TEXT_SHIFTRUNSTOP = END_TEXT_LOADRUN
   299:  
   300:  DEFAULT_COLOR := COL_WHITE
   301:  
   302:  .elseif CompileComputer=C64_SX64
   303:  DRIVEFILLER=$AA
   304:  VERSION_FF80=$43
   305:  VERSION_E4AC=$B3
   306:  BASIC_END := $E3A2
   307:  SET_COLOR_FRAME := COL_CYAN
   308:  SET_COLOR_BACKGROUND := COL_WHITE
   309:  TEXT_SHIFTRUNSTOP = TEXT_LOAD_8_RUN
   310:  END_TEXT_SHIFTRUNSTOP = END_TEXT_LOAD_8_RUN
   311:  
   312:  DEFAULT_COLOR := COL_BLUE
   313:  
   314:  .elseif CompileComputer=C64_GS
   315:  DRIVEFILLER=$AA
   316:  VERSION_FF80=3
   317:  VERSION_E4AC=$81
   318:  BASIC_END := $E3A2
   319:  SET_COLOR_FRAME := COL_LIGHTBLUE
   320:  SET_COLOR_BACKGROUND := COL_BLUE
   321:  TEXT_SHIFTRUNSTOP = TEXT_LOADRUN
   322:  END_TEXT_SHIFTRUNSTOP = END_TEXT_LOADRUN
   323:  
   324:  DEFAULT_COLOR := COL_LIGHTBLUE
   325:  
   326:  .endif
   327:  
   328:  CHKSUM_BF52 = $EC
   329:  
   330:  EDITOR_TAB  = 10
   331:  EDITOR_COLS = 40
   332:  EDITOR_ROWS = 25
   333:  
   334:  EDITOR_MAX_COMBINED_ROWS = 2
   335:  ;       .include "memory.inc"
   336:  ; .include "../basic/basic-memory.inc"
   337:  .segment "MEM_BASIC_ZP": zeropage
   338:  
   339:  zADRAY1:        .res 2  ; $0003
   340:  zADRAY2:        .res 2  ; $0005
   341:  zCHARAC:        .res 1  ; $0007
   342:  zENDCHR:        .res 1  ; $0008
   343:  zTRMPOS:        .res 1  ; $0009
   344:  zVERCK:         .res 1  ; $000A
   345:  zCOUNT:         .res 1  ; $000B
   346:  zDIMFLG:        .res 1  ; $000C
   347:  zVALTYP:        .res 1  ; $000D
   348:  zINTFLG:        .res 1  ; $000E
   349:  zGARBFL:        .res 1  ; $000F
   350:  zINTALLOWED:    .res 1  ; $0010 ; TODO
   351:  zSUBFLG:        .res 1  ; $0011
   352:  zTANSGN:        .res 1  ; $0012
   353:  z13:            .res 1  ; $0013 ; TODO
   354:  zLINNUM:        .res 2  ; $0014
   355:  zTEMPPT:        .res 1  ; $0016
   356:  zLASTPT:        .res 2  ; $0017
   357:  zTEMPST:        .res 5  ; $0019
   358:  zCHANNL:        .res 4  ; $001E
   359:  zINDEX:         .res 2  ; $0022
   360:  zINDEX2:        .res 2  ; $0024
   361:  zRESHO:         .res 5  ; $0026
   362:  zTEMP_28        := zRESHO + 2   ; TODO
   363:  zTXTTAB:        .res 2  ; $002B
   364:  zVARTAB:        .res 2  ; $002D
   365:  zARYTAB:        .res 2  ; $002F
   366:  zSTREND:        .res 2  ; $0031
   367:  zFRETOP:        .res 2  ; $0033
   368:  zFRESPC:        .res 2  ; $0035
   369:  zMEMSIZ:        .res 2  ; $0037
   370:  zCURLIN:        .res 2  ; $0039
   371:  zOLDLIN:        .res 2  ; $003B
   372:  zOLDTXT:        .res 2  ; $003D
   373:  zDATLIN:        .res 2  ; $003F
   374:  zDATPTR:        .res 2  ; $0041
   375:  zINPPTR:        .res 2  ; $0043
   376:  zVARNAM:        .res 2  ; $0045
   377:  zVARPNT:        .res 2  ; $0047
   378:  zFORPNT:        .res 2  ; $0049
   379:  zVARTXT:        .res 2  ; $004B
   380:  zOPMASK:        .res 1  ; $004D
   381:  zTEMPF3:        .res 5  ; $004E
   382:  zTEMP_50        := zTEMPF3 + 2  ; TODO
   383:  zFOUR6:         .res 1  ; $0053
   384:  zJMPER:         .res 3  ; $0054
   385:  zTEMPF1:        .res 5  ; $0057
   386:  zTEMP_58        := zTEMPF1 + 1  ; TODO
   387:  zTEMP_5A        := zTEMPF1 + 3  ; TODO
   388:  zTEMPF2:        .res 5  ; $005C
   389:  zTEMP_5D        := zTEMPF2 + 1  ; TODO
   390:  zTEMP_5E        := zTEMPF2 + 2  ; TODO
   391:  zTEMP_5F        := zTEMPF2 + 3  ; TODO
   392:  zTEMP_60        := zTEMPF2 + 4  ; TODO
   393:  zFAC:           .res 7  ; $0061
   394:  zFACEXP         := zFAC ; $0061
   395:  zFACHO          := zFAC + 1     ; $0062
   396:  zFACSGN         := zFAC + 5     ; $0066
   397:  zSGNFLG         := zFAC + 6     ; $0067
   398:  zBITS:          .res 1  ; $0068
   399:  zARG:           .res 7  ; $0069
   400:  zARGEXP         := zARG ; $0069
   401:  zARGHO          := zARG + 1     ; $006A
   402:  zARGSGN         := zARG + 5     ; $006E
   403:  zARISGN         := zARG + 6     ; $006F
   404:  zFACOV:         .res 1  ; $0070
   405:  zFBUFPT:        .res 2  ; $0071
   406:  zCHRGET:        .res 6  ; $0073
   407:  zCHRGOT:        .res 7  ; $0079
   408:  zCHRGOT_SPACE:  .res 11 ; $0080
   409:  zTXTPTR         := zCHRGOT + 1  ; $007A
   410:  zRNDX:          .res 5  ; $008B
   411:  
   412:  .segment "MEM_BASIC_ZP2": zeropage
   413:  
   414:  zASCWRK:        .res 1  ; $00FF
   415:  
   416:          .segment "STACK"
   417:  
   418:  lSTACK:         .res 256
   419:  
   420:          .segment "MEM_BASIC_DATA_0200"
   421:  
   422:  lBUF:           .res 89
   423:  END_lBUF:
   424:  
   425:          .segment "MEM_BASIC_DATA_0300"
   426:  
   427:  lIERROR:        .res 2
   428:  lIMAIN:         .res 2
   429:  lICRNCH:        .res 2
   430:  lIQPLOP:        .res 2
   431:  lIGONE:         .res 2
   432:  lIEVAL:         .res 2
   433:  lSAREG:         .res 1
   434:  lSXREG:         .res 1
   435:  lSYREG:         .res 1
   436:  lSPREG:         .res 1
   437:  
   438:  .if CompileComputer >= C64_GENERAL
   439:          .segment "MEM_BASIC_USR"
   440:  .else
   441:          .segment "MEM_BASIC_USR": zeropage
   442:  .endif
   443:  
   444:  lUSRPOK:        .res 1
   445:  lUSRADD:        .res 2
   446:  
   447:          .segment "C6510_ZP": zeropage
   448:  
   449:  zD6510:         .res 1
   450:  zR6510:         .res 1
   451:  
   452:  lVICSCN         := $0400
   453:  lSPNTRN         := $07F8
   454:  
   455:  CARTRIDGE       := $8000
   456:  CART_RESET      := CARTRIDGE + 0
   457:  CART_NMI        := CARTRIDGE + 2
   458:  CART_MAGIC      := CARTRIDGE + 4
   459:  
   460:  ; .include "../vic-ii.inc"
   461:  VICII_O_Sprite0X                        := 0
   462:  VICII_O_Sprite0Y                        := 1
   463:  VICII_O_Sprite1X                        := 2
   464:  VICII_O_Sprite1Y                        := 3
   465:  VICII_O_Sprite2X                        := 4
   466:  VICII_O_Sprite2Y                        := 5
   467:  VICII_O_Sprite3X                        := 6
   468:  VICII_O_Sprite3Y                        := 7
   469:  VICII_O_Sprite4X                        := 8
   470:  VICII_O_Sprite4Y                        := 9
   471:  VICII_O_Sprite5X                        := 10
   472:  VICII_O_Sprite5Y                        := 11
   473:  VICII_O_Sprite6X                        := 12
   474:  VICII_O_Sprite6Y                        := 13
   475:  VICII_O_Sprite7X                        := 14
   476:  VICII_O_Sprite7Y                        := 15
   477:  VICII_O_SpriteXMSB                      := 16   ; MSBs of all Sprite X coordinates; bit i corresponds to sprite i
   478:  
   479:  VICII_O_ControlReg1                     := 17
   480:  VICII_B_ControlReg1_Raster8             := $80  ; bit 8 of VICII_O_Raster
   481:  VICII_B_ControlReg1_ECM                 := $40  ; extended color mode
   482:  VICII_B_ControlReg1_BMM                 := $20  ; bit map mode (HiRes)
   483:  VICII_B_ControlReg1_DEN                 := $10  ; display enable
   484:  VICII_B_ControlReg1_RSEL                := $08  ; 1 = 25 rows, 0 = 24 rows
   485:  VICII_B_ControlReg1_YSCROLL_MASK        := $07  ; offset from top in raster lines
   486:  
   487:  VICII_O_Raster                          := 18
   488:  VICII_O_LightPenX                       := 19
   489:  VICII_O_LightPenY                       := 20
   490:  VICII_O_SprEnable                       := 21   ; sprite enable: 1 = sprite is enabled. bit i corresponds to sprite i
   491:  
   492:  VICII_O_ControlReg2                     := 22
   493:  VICII_B_ControlReg2_Reserved1           := $80  ; unused
   494:  VICII_B_ControlReg2_Reserved2           := $40  ; unused
   495:  VICII_B_ControlReg2_RES                 := $20  ; RESET on 6566; unused on 6567/6569
   496:  VICII_B_ControlReg2_MCM                 := $10  ; multicolor bitmap
   497:  VICII_B_ControlReg2_CSEL                := $08  ; 1 = 40 colums, 0 = 38 columns
   498:  VICII_B_ControlReg2_XSCROLL_MASK        := $07  ; offset in pixels from left side
   499:  
   500:  VICII_O_SprExpandY                      := 23   ; sprite Y expansion: 1 = sprite is expanded. bit i corresponds to sprite i
   501:  
   502:  VICII_O_MemControl                      := 24
   503:  VICII_B_MemControl_Reserved             := $01
   504:  VICII_B_MemControl_CB_Mask              := $0E
   505:  VICII_B_MemControl_VM_Mask              := $F0
   506:  
   507:  VICII_O_IRQFlags                        := 25   ; interrupt register
   508:  VICII_B_IRQFlags_RST                    := $01
   509:  VICII_B_IRQFlags_MBC                    := $02
   510:  VICII_B_IRQFlags_MMC                    := $04
   511:  VICII_B_IRQFlags_LP                     := $08  ; lightpen
   512:  VICII_B_IRQFlags_Reserved               := $70
   513:  VICII_B_IRQFlags_Any                    := $80  ; any IRQ happened
   514:  
   515:  VICII_O_IRQMasks                        := 26
   516:  VICII_B_IRQMasks_RST                    := VICII_B_IRQFlags_RST
   517:  VICII_B_IRQMasks_MBC                    := VICII_B_IRQFlags_MBC
   518:  VICII_B_IRQMasks_MMC                    := VICII_B_IRQFlags_MMC
   519:  VICII_B_IRQMasks_LP                     := VICII_B_IRQFlags_LP
   520:  VICII_B_IRQMasks_Reserved               := $F0
   521:  
   522:  VICII_O_SprPriority                     := 27   ; sprite data priority: 1 = sprite is behind data, 0 = sprite is before. bit i corresponds to sprite i
   523:  VICII_O_SprMCM                          := 28   ; sprite multi color mode: 1 = sprite is multi-color. bit i corresponds to sprite i
   524:  VICII_O_SprExpandX                      := 29   ; sprite X expansion: 1 = sprite is expanded. bit i corresponds to sprite i
   525:  VICII_O_SprSprColl                      := 30   ; sprite-sprite collision: 1 = sprite has collided with another sprite. bit i corresponds to sprite i
   526:  VICII_O_SprBackColl                     := 31   ; sprite-background collision: 1 = sprite has collided with the background. bit i corresponds to sprite i
   527:  
   528:  VICII_O_BorderCol                       := 32   ; border color
   529:  VICII_O_BackgCol0                       := 33   ; background color 0
   530:  VICII_O_BackgCol1                       := 34   ; background color 1
   531:  VICII_O_BackgCol2                       := 35   ; background color 2
   532:  VICII_O_BackgCol3                       := 36   ; background color 3
   533:  
   534:  VICII_O_SprMCMCol0                      := 37   ; multi-color sprite: color 0
   535:  VICII_O_SprMCMCol1                      := 38   ; multi-color sprite: color 1
   536:  
   537:  VICII_O_Spr0Col                         := 39   ; sprite 0 color
   538:  VICII_O_Spr1Col                         := 40   ; sprite 1 color
   539:  VICII_O_Spr2Col                         := 41   ; sprite 2 color
   540:  VICII_O_Spr3Col                         := 42   ; sprite 3 color
   541:  VICII_O_Spr4Col                         := 43   ; sprite 4 color
   542:  VICII_O_Spr5Col                         := 44   ; sprite 5 color
   543:  VICII_O_Spr6Col                         := 45   ; sprite 6 color
   544:  VICII_O_Spr7Col                         := 46   ; sprite 7 color
   545:  
   546:  VICIIe_O_Keyboard                       := 47   ; bit 3..0: status of 4 additional keyboard pins (TODO: 3 or 4?)
   547:  VICIIe_B_Keyboard_Reserved_MASK         := $F0  ; unused
   548:  
   549:  VICIIe_O_ControlReg3                    := 48   ; TODO: Is there a test bit $02?
   550:  VICIIe_B_ControlReg3_2MHZ               := $01  ; 1 = 2 MHz mode, 0 = 1 MHz mode
   551:  VICIIe_B_ControlReg3_Reserved_MASK      := $FE  ; unused
   552:  
   553:  COL_BLACK      = 0
   554:  COL_WHITE      = 1
   555:  COL_RED        = 2
   556:  COL_CYAN       = 3
   557:  COL_VIOLET     = 4
   558:  COL_GREEN      = 5
   559:  COL_BLUE       = 6
   560:  COL_YELLOW     = 7
   561:  COL_ORANGE     = 8
   562:  COL_BROWN      = 9
   563:  COL_LIGHTRED   = 10
   564:  COL_GRAY1      = 11
   565:  COL_GRAY2      = 12
   566:  COL_LIGHTGREEN = 13
   567:  COL_LIGHTBLUE  = 14
   568:  COL_GRAY3      = 15
   569:  
   570:  VIC           := $D000
   571:  
   572:  ; .include "../sid.inc"
   573:  SID_O_Voc1FreqLo   := 0
   574:  SID_O_Voc1FreqHi   := 1
   575:  SID_O_Voc1PWidthLo := 2
   576:  SID_O_Voc1PWidthHi := 3
   577:  SID_O_Voc1Control  := 4
   578:  SID_O_Voc1AttDec   := 5
   579:  SID_O_Voc1SusRel   := 6
   580:  SID_O_Voc2FreqLo   := 7
   581:  SID_O_Voc2FreqHi   := 8
   582:  SID_O_Voc2PWidthLo := 9
   583:  SID_O_Voc2PWidthHi := 10
   584:  SID_O_Voc2Control  := 11
   585:  SID_O_Voc2AttDec   := 12
   586:  SID_O_Voc2SusRel   := 13
   587:  SID_O_Voc3FreqLo   := 14
   588:  SID_O_Voc3FreqHi   := 15
   589:  SID_O_Voc3PWidthLo := 16
   590:  SID_O_Voc3PWidthHi := 17
   591:  SID_O_Voc3Control  := 18
   592:  SID_O_Voc3AttDec   := 19
   593:  SID_O_Voc3SusRel   := 20
   594:  SID_O_FiltFreqLo   := 21
   595:  SID_O_FiltFreqHi   := 22
   596:  SID_O_FiltControl  := 23
   597:  SID_O_FiltMode     := 24
   598:  SID_O_ADC1              := 25
   599:  SID_O_ADC2              := 26
   600:  SID_O_Random            := 27
   601:  SID_O_Voc3Output        := 28
   602:  
   603:  SID           := $D400
   604:  
   605:  COLORRAM      := $D800
   606:  
   607:  ; .include "../cia.inc"
   608:  CIA_O_PA       :=  0
   609:  CIA_O_PB       :=  1
   610:  CIA_O_DDRA     :=  2
   611:  CIA_O_DDRB     :=  3
   612:  CIA_O_TALO     :=  4
   613:  CIA_O_TAHI     :=  5
   614:  CIA_O_TBLO     :=  6
   615:  CIA_O_TBHI     :=  7
   616:  CIA_O_TOD10THS :=  8
   617:  CIA_O_TODSEC   :=  9
   618:  CIA_O_TODMIN   := 10
   619:  CIA_O_TODHR    := 11
   620:  CIA_O_SDR      := 12
   621:  CIA_O_ICR      := 13
   622:  CIA_O_CRA      := 14
   623:  CIA_O_CRB      := 15
   624:  
   625:  CIA_ICR_B_TA            := $01  ; bit: timer A underflow
   626:  CIA_ICR_B_TB            := $02  ; bit: timer B underflow
   627:  CIA_ICR_B_TOD           := $04  ; bit: TOD alarm
   628:  CIA_ICR_B_SP            := $08  ; bit: Serial port full/empty
   629:  CIA_ICR_B_FLAG          := $10  ; bit: external -FLAG
   630:  CIA_ICR_B_UNUSED        := $60
   631:  CIA_ICR_BR_IR           := $80  ; bit: any interrupt occurred (read-only)
   632:  CIA_ICR_BW_SET          := $80  ; bit: set (=1) or clear (=0) bit (write-only)
   633:  CIA_ICR_BW_UNSET        := $00  ;
   634:  
   635:  CIA_CRA_B_START         := $01  ; 1 = start timer A, 0 = stop timer A
   636:  CIA_CRA_B_PBON          := $02  ; 1 = timer A output appears on PB6, 0 = PB6 is not affected by timer
   637:  CIA_CRA_B_TOGGLE        := $04  ; PB6 output mode: 1 = toggle, 0 = pulse
   638:  CIA_CRA_B_ONESHOT       := $08  ; 1 = one shot timer, 0 = continuous mode
   639:  CIA_CRA_B_FORCE_LOAD    := $10  ; 1 = force load (this is a strobe, that is, it will always be read as "0")
   640:  CIA_CRA_B_COUNT_CNT     := $20  ; 1 = timer A counts positive edges of CNT, 0 = timer A counts PHI2 pulses
   641:  CIA_CRA_B_SP_OUTPUT     := $40  ; 1 = serial port (SP) is output, 0 = it is input
   642:  CIA_CRA_B_50HZ          := $80  ; 1 = 50Hz clock at TOD, 0 = 60Hz clock
   643:  
   644:  CIA_CRB_B_START         := $01  ; 1 = start timer B, 0 = stop timer B
   645:  CIA_CRB_B_PBON          := $02  ; 1 = timer B output appears on PB7, 0 = PB7 is not affected by timer
   646:  CIA_CRB_B_TOGGLE        := $04  ; PB7 output mode: 1 = toggle, 0 = pulse
   647:  CIA_CRB_B_ONESHOT       := $08  ; 1 = one shot timer, 0 = continuous mode
   648:  CIA_CRB_B_FORCE_LOAD    := $10  ; 1 = force load (this is a strobe, that is, it will always be read as "0")
   649:  CIA_CRB_B_TOD_ALARM     := $80  ; 1 = writing to TOD registers sets ALARM, 0 = writing to TOD registers sets time-of-day
   650:  
   651:  CIA_CRB_B_MODE_MASK     := $60  ; mask bits for setting the timer B count mode
   652:  CIA_CRB_B_MODE_PHI2     := $00  ; timer B counts PHI2 pulses
   653:  CIA_CRB_B_MODE_CNT      := $20  ; timer B counts positive edges of CNT
   654:  CIA_CRB_B_MODE_TA_      := $40  ; timer B counts timer A underflows
   655:  CIA_CRB_B_MODE_TA_WITH_CNT      := $60  ; timer B counts timer A underflows which occur while CNT is high
   656:  
   657:  CIA1          := $DC00
   658:  
   659:  CIA2          := $DD00
   660:  
   661:  CIA2_PA_B_VA14          := $01
   662:  CIA2_PA_B_VA15          := $02
   663:  CIA2_PA_B_RS232_TXD     := $04
   664:  CIA2_PA_B_IEC_ATN_OUT   := $08
   665:  CIA2_PA_B_IEC_CLK_OUT   := $10
   666:  CIA2_PA_B_IEC_DATA_OUT  := $20
   667:  CIA2_PA_B_IEC_CLK_IN    := $40
   668:  CIA2_PA_B_IEC_DATA_IN   := $80
   669:  
   670:  CIA2_PB_B_RS232_RXD     := $01 ; also connected with -FLAG
   671:  CIA2_PB_B_RS232_RTS     := $02
   672:  CIA2_PB_B_RS232_DTR     := $04
   673:  CIA2_PB_B_RS232_RING    := $08
   674:  CIA2_PB_B_RS232_DCD     := $10
   675:  CIA2_PB_B_RS232_PB5     := $20 ; unused
   676:  CIA2_PB_B_RS232_CTS     := $40
   677:  CIA2_PB_B_RS232_DSR     := $80
   678:  
   679:  
   680:  P6510_B_LORAM           := $01
   681:  P6510_B_HIRAM           := $02
   682:  P6510_B_CHAREN          := $04
   683:  P6510_B_CASS_WRITE      := $08
   684:  P6510_B_CASS_SENSE      := $10
   685:  P6510_B_CASS_MOTOR      := $20
   686:  P6510_B_UNUSED          := $C0
   687:  
   688:  P6510_B_MASK            := ~ P6510_B_UNUSED
   689:  
   690:  IOBASE        := CIA1
   691:  
   692:  FILE_KEYBOARD := 0
   693:  FILE_TAPE     := 1
   694:  FILE_RS232    := 2
   695:  FILE_SCREEN   := 3
   696:  FILE_IEC      := 4
   697:  
   698:  KEY_SHIFTRUN  := $83
   699:  
   700:  IEC_REG       := CIA2 + CIA_O_PA
   701:  IEC_DDR       := CIA2 + CIA_O_DDRA
   702:  
   703:  IEC_B_ATN_OUT  := CIA2_PA_B_IEC_ATN_OUT
   704:  IEC_B_CLK_OUT  := CIA2_PA_B_IEC_CLK_OUT
   705:  IEC_B_DATA_OUT := CIA2_PA_B_IEC_DATA_OUT
   706:  IEC_B_CLK_IN   := CIA2_PA_B_IEC_CLK_IN
   707:  IEC_B_DATA_IN  := CIA2_PA_B_IEC_DATA_IN
   708:  
   709:  IEC_REG_ATN_OUT      := CIA2 + CIA_O_PA
   710:  IEC_REG_DATA_CLK_OUT := CIA2 + CIA_O_PA
   711:  IEC_REG_DATA_CLK_IN  := CIA2 + CIA_O_PA
   712:  
   713:  IEC_TIMER_LO            := CIA1 + CIA_O_TBLO
   714:  IEC_TIMER_HI            := CIA1 + CIA_O_TBHI
   715:  
   716:  IEC_TIMER_FLAG_REG      := CIA1 + CIA_O_ICR
   717:  IEC_TIMER_FLAG_B        := CIA_ICR_B_TB
   718:  
   719:  TAPE_REG                := zR6510
   720:  TAPE_DDR                := zD6510
   721:  TAPE_B_WRITE            := P6510_B_CASS_WRITE
   722:  TAPE_B_SENSE            := P6510_B_CASS_SENSE
   723:  TAPE_B_MOTOR_ON_ALL     := P6510_B_CASS_MOTOR
   724:  TAPE_B_MOTOR_ON         := P6510_B_CASS_MOTOR
   725:  TAPE_B_MOTOR_OFF_AND    := ~ P6510_B_CASS_MOTOR & P6510_B_MASK
   726:  
   727:  TAPE_REG_WRITE          := zR6510
   728:  TAPE_REG_SENSE          := zR6510
   729:  TAPE_REG_MOTOR          := zR6510
   730:  TAPE_REG_ICR            := CIA1 + CIA_O_ICR
   731:  TAPE_REG_ICR_B_CLEARALL := CIA_ICR_BW_UNSET | $7F
   732:  TAPE_REG_ICR_B_CASSREAD := CIA_ICR_BW_SET | CIA_ICR_B_FLAG
   733:  TAPE_REG_ICR_B_WR_TIMER := CIA_ICR_BW_SET | CIA_ICR_B_TB
   734:  TAPE_REG_ICR_B_SET_3    := CIA_ICR_BW_SET | CIA_ICR_B_TA
   735:  TAPE_REG_ICR_B_UNSET_3  := CIA_ICR_BW_UNSET | CIA_ICR_B_TA
   736:  
   737:  TAPE_TIMER1_LO          := CIA1 + CIA_O_TBLO
   738:  TAPE_TIMER1_HI          := CIA1 + CIA_O_TBHI
   739:  TAPE_TIMER2_LO          := CIA1 + CIA_O_TALO
   740:  TAPE_TIMER2_HI          := CIA1 + CIA_O_TAHI
   741:  TAPE_TIMER1_CONST       := $16
   742:  
   743:  KEYB_ROW                := CIA1 + CIA_O_PA
   744:  KEYB_COL                := CIA1 + CIA_O_PB
   745:  KEYB_COL_FOR_STOP       := KEYB_COL
   746:  
   747:  KEYB_ROW_CTRL           := $7F
   748:  KEYB_COL_CTRL           := $FB
   749:  KEYB_ROW_STOP           := $BD
   750:  KEYB_ROW_STANDARD       := $7F
   751:  KEYB_CHECK_STOP         := $7F
   752:  
   753:  RS232_TXD_REG           := CIA2 + CIA_O_PA
   754:  RS232_TXD_BIT           := CIA2_PA_B_RS232_TXD
   755:  
   756:  RS232_REG_1             := CIA2 + CIA_O_PB
   757:  RS232_REG_2             := CIA2 + CIA_O_PB
   758:  RS232_TIMER_LO          := CIA2 + CIA_O_TALO
   759:  RS232_TIMER_HI          := CIA2 + CIA_O_TAHI
   760:  
   761:  ;       .include "../basic/basic2.inc"
   762:  
   763:  .segment "HEADER"
   764:  
   765:  BASIC_START:
   766:  
   767:  bRESTART:
   768:          .addr   LE394
   769:          .addr   LE37B
   770:          .byte   "CBMBASIC"
   771:  
   772:  ; This is the table of the entry addresses of the various
   773:  ; BASIC commands. Every address is " - 1" as this table is
   774:  ; used in pushing the address onto the stack and perfoming
   775:  ; an RTS afterwards.
   776:  
   777:  .segment "VECTORS"
   778:  
   779:          .segment "KEYWORDS"
   780:  
   781:  CONFIG_FILE=1
   782:  CONFIG_CBM_ALL=1
   783:  CONFIG_2=1
   784:  
   785:  ;       .include "token.s"
   786:  
   787:  .segment "VECTORS"
   788:  
   789:  bSTMDSP = TOKEN_ADDRESS_TABLE
   790:  bFUNDSP = UNFNC
   791:  
   792:  
   793:  ; This is the table of the BASIC functions.
   794:  
   795:  ; This is the table of the operands. Every entry consists
   796:  ; of 3 consecutive bytes: A first byte (@?) and the address
   797:  ; of the processing function ( - 1).
   798:  
   799:  bOPTAB = MATHTBL
   800:  
   801:  ;.segment "KEYWORDS"
   802:  
   803:  bRESLST = TOKEN_NAME_TABLE
   804:  
   805:  ; This is the list of the reserved words. Every word ends
   806:  ; with the last byte having bit 7 set.
   807:  ; The list ends with the last byte being 0.
   808:  ; The complete list is not allowed to exceed 256 byte!
   809:  
   810:  TokPi      = $FF
   811:  
   812:  
   813:  .segment "ERROR"
   814:  
   815:  ; This is the table of error strings. Every entry ends with
   816:  ; bit 7 set.
   817:  
   818:  ErrTooManyFiles        =  1
   819:  ErrFileOpen            =  2
   820:  ErrFileNotOpen         =  3
   821:  ErrFileNotFound        =  4
   822:  ErrDeviceNotPresent    =  5
   823:  ErrNotInputFile        =  6
   824:  ErrNotOutputFile       =  7
   825:  ErrMissingFileName     =  8
   826:  ErrIllegalDeviceNumber =  9
   827:  ErrNextWithoutFor      = 10
   828:  ErrSyntax              = 11
   829:  ErrReturnWithoutGosub  = 12
   830:  ErrOutOfData           = 13
   831:  ErrIllegalQuantity     = 14
   832:  ErrOverflow            = 15
   833:  ErrOutOfMemory         = 16
   834:  ErrUndefinedStatement  = 17
   835:  ErrBadSubscript        = 18
   836:  ErrRedimdArray         = 19
   837:  ErrDivisionByZero      = 20
   838:  ErrIllegalDirect       = 21
   839:  ErrTypeMismatch        = 22
   840:  ErrStringTooLong       = 23
   841:  ErrFileData            = 24
   842:  ErrFormulaTooComplex   = 25
   843:  ErrCantContinue        = 26
   844:  ErrUndefdFunction      = 27
   845:  ErrVerify              = 28
   846:  ErrLoad                = 29
   847:  ErrBreak               = 30
   848:  
   849:  
   850:  bERRTAB:
   851:  StrTooManyFiles:
   852:          htasc   "TOO MANY FILES"
   853:  StrFileOpen:
   854:          htasc   "FILE OPEN"
   855:  StrFileNotOpen:
   856:          htasc   "FILE NOT OPEN"
   857:  StrFileNotFound:
   858:          htasc   "FILE NOT FOUND"
   859:  StrDeviceNotPresent:
   860:          htasc   "DEVICE NOT PRESENT"
   861:  StrNotInputFile:
   862:          htasc   "NOT INPUT FILE"
   863:  StrNotOutputFile:
   864:          htasc   "NOT OUTPUT FILE"
   865:  StrMissingFileName:
   866:          htasc   "MISSING FILE NAME"
   867:  StrIllegalDeviceNumber:
   868:          htasc   "ILLEGAL DEVICE NUMBER"
   869:  StrNextWithoutFor:
   870:          htasc   "NEXT WITHOUT FOR"
   871:  StrSyntax:
   872:          htasc   "SYNTAX"
   873:  StrReturnWithoutGosub:
   874:          htasc   "RETURN WITHOUT GOSUB"
   875:  StrOutOfData:
   876:          htasc   "OUT OF DATA"
   877:  StrIllegalQuantity:
   878:          htasc   "ILLEGAL QUANTITY"
   879:  StrOverflow:
   880:          htasc   "OVERFLOW"
   881:  StrOutOfMemory:
   882:          htasc   "OUT OF MEMORY"
   883:  StrUndefinedStatement:
   884:          htasc   "UNDEF'D STATEMENT"
   885:  StrBadSubscript:
   886:          htasc   "BAD SUBSCRIPT"
   887:  StrRedimdArray:
   888:          htasc   "REDIM'D ARRAY"
   889:  StrDivisionByZero:
   890:          htasc   "DIVISION BY ZERO"
   891:  StrIllegalDirect:
   892:          htasc   "ILLEGAL DIRECT"
   893:  StrTypeMismatch:
   894:          htasc   "TYPE MISMATCH"
   895:  StrStringTooLong:
   896:          htasc   "STRING TOO LONG"
   897:  StrFileData:
   898:          htasc   "FILE DATA"
   899:  StrFormulaTooComplex:
   900:          htasc   "FORMULA TOO COMPLEX"
   901:  StrCantContinue:
   902:          htasc   "CAN'T CONTINUE"
   903:  StrUndefdFunction:
   904:          htasc   "UNDEF'D FUNCTION"
   905:  StrVerify:
   906:          htasc   "VERIFY"
   907:  StrLoad:
   908:          htasc   "LOAD"
   909:  
   910:  ; This is the list of pointers into the error strings.
   911:  
   912:  bERRPTR:
   913:          .addr   StrTooManyFiles
   914:          .addr   StrFileOpen
   915:          .addr   StrFileNotOpen
   916:          .addr   StrFileNotFound
   917:          .addr   StrDeviceNotPresent
   918:          .addr   StrNotInputFile
   919:          .addr   StrNotOutputFile
   920:          .addr   StrMissingFileName
   921:          .addr   StrIllegalDeviceNumber
   922:          .addr   StrNextWithoutFor
   923:          .addr   StrSyntax
   924:          .addr   StrReturnWithoutGosub
   925:          .addr   StrOutOfData
   926:          .addr   StrIllegalQuantity
   927:          .addr   StrOverflow
   928:          .addr   StrOutOfMemory
   929:          .addr   StrUndefinedStatement
   930:          .addr   StrBadSubscript
   931:          .addr   StrRedimdArray
   932:          .addr   StrDivisionByZero
   933:          .addr   StrIllegalDirect
   934:          .addr   StrTypeMismatch
   935:          .addr   StrStringTooLong
   936:          .addr   StrFileData
   937:          .addr   StrFormulaTooComplex
   938:          .addr   StrCantContinue
   939:          .addr   StrUndefdFunction
   940:          .addr   StrVerify
   941:          .addr   StrLoad
   942:          .addr   StrBreak
   943:  
   944:  bOKK:   .byte   $0D,"OK",$0D,$00
   945:  
   946:  .segment "CODE"
   947:  
   948:  StrError:
   949:  .if CompileComputer >= C64_GENERAL
   950:          .byte   ' '
   951:  .else
   952:          .byte   $0D
   953:  .endif
   954:          .byte   " ERROR"
   955:          .byte   $00
   956:  
   957:  StrIn:
   958:          .byte   " IN "
   959:          .byte   $00
   960:  
   961:  StrReady:
   962:          .byte   $0D,$0A
   963:          .byte   "READY."
   964:          .byte   $0D,$0A,$00
   965:  
   966:  StrCrBreak:
   967:          .byte   $0D,$0A
   968:  StrBreak:
   969:          .byte   "BREAK"
   970:          .byte   $00
   971:  
   972:          .byte   $A0     ; @?
   973:  
   974:  ; This routine tries to find a stack entry for a
   975:  ; previous "FOR" statement.
   976:  ;
   977:  ; Input:
   978:  ;   zFORPNT/zFORPNT + 1:
   979:  ;     Contans the variable name of the variable given
   980:  ;     by the "NEXT" command.
   981:  ;     If ANY for has to be closed, zFORPNT + 1 is 0.
   982:  ;
   983:  ; Output:
   984:  ;   X:
   985:  ;      contains a pointer into the stack page
   986:  ;      where the "FOR entry" is located.
   987:  ;
   988:  ;   Z:
   989:  ;      Is set iff an entry has been found.
   990:  ;      OR the stack has been exhausted.
   991:  ;
   992:  ;   zFORPNT/zFORPNT + 1:
   993:  ;      contains the variable name of the variable
   994:  ;      being "NEXT"ed, even if no variable name
   995:  ;      was given on input.
   996:  ;
   997:  ; Remarks:
   998:  ;   This function is tricks as it also handles the
   999:  ;   FOR, GOSUB and RETURN statements. @
  1000:  
  1001:  bFNDFOR:
  1002:          tsx
  1003:          inx
  1004:          inx
  1005:          inx
  1006:          inx
  1007:  @Loop:
  1008:          ; first check if there is a "FOR entry"
  1009:          lda     lSTACK + 1,x
  1010:          cmp     #TokFor
  1011:          bne     @Ret        ; no FOR entry, return with error
  1012:  
  1013:          ; check if the user asked for a specific variable
  1014:          lda     zFORPNT + 1
  1015:          bne     @TestVar    ; yes, this, test this variable
  1016:  
  1017:          ; no variable name was given, just take the current
  1018:          ; one out of the stack entry
  1019:          lda     lSTACK + 2,x
  1020:          sta     zFORPNT
  1021:          lda     lSTACK + 3,x
  1022:          sta     zFORPNT + 1
  1023:  
  1024:          ; now, test if the variable in the stack entry
  1025:          ; is the right one.
  1026:          ; If no variable is given, it will be the right one
  1027:          ; as we just took that one out of the stack entry.
  1028:  @TestVar:
  1029:          cmp     lSTACK + 3,x
  1030:          bne     @UnWind     ; not the same, unwind the stack
  1031:          lda     zFORPNT
  1032:          cmp     lSTACK + 2,x
  1033:          beq     @Ret        ; ok, we found the variable, quit.
  1034:  
  1035:          ; we have not found the variable. Unwind the stack,
  1036:          ; that is, remove the current "FOR entry" and test
  1037:          ; if there is another one before that.
  1038:  @UnWind:
  1039:          ; add 18 to the stack pointer to skip to the next entry
  1040:          txa
  1041:          clc
  1042:          adc     #18
  1043:          tax
  1044:  
  1045:          ; if we did not reach the end of the stack, test the next entry
  1046:          ; This one is a bit tricky. It only works as expected because
  1047:          ; X has been incremented four times at the beginning of this
  1048:          ; function.
  1049:          bne     @Loop
  1050:  
  1051:  @Ret:   rts
  1052:  
  1053:  
  1054:  bBLTU:  jsr     bREASON
  1055:          sta     zSTREND
  1056:          sty     zSTREND + 1
  1057:  
  1058:          ; Move memory around
  1059:          ;
  1060:          ; Input:
  1061:          ;  zTEMP_5F: Old begin
  1062:          ;  zTEMP_5A: Old end ( + 1)
  1063:          ;  zTEMP_58: New end ( + 1)
  1064:          ;
  1065:          ; Remark:
  1066:          ;   If both areas overlap, the new area has to be "above" the old one.
  1067:          ;
  1068:  MoveMem:
  1069:  
  1070:  @OldBegin = zTEMP_5F
  1071:  @OldEndP1 = zTEMP_5A
  1072:  @NewEndP1 = zTEMP_58
  1073:  
  1074:          ; calculate length of block to transfer
  1075:          ; via subtracting Old begin from old end ( + 1).
  1076:          ;
  1077:          sec
  1078:          lda     @OldEndP1
  1079:          sbc     @OldBegin
  1080:          sta     zINDEX    ; low byte of length into zIndex
  1081:          tay               ; and remember it in Y, too.
  1082:          lda     @OldEndP1 + 1
  1083:          sbc     @OldBegin + 1
  1084:          tax               ; now, the high byte of length is in X
  1085:  
  1086:          inx
  1087:          tya               ; check low byte of length
  1088:          beq     @SkipPartialPage ; is 0, thus, we do net have a partial page to process
  1089:  
  1090:          ; now, subtract "page hangover" (low byte of length to move)
  1091:          ; from OldEndP1 and NewEndP1.
  1092:          ; This way, we process this "hangover" at first. Afterwards, only complete
  1093:          ; pages have to be processed.
  1094:  
  1095:          lda     @OldEndP1
  1096:          sec
  1097:          sbc     zINDEX
  1098:          sta     @OldEndP1
  1099:          bcs     @CalcNewEnd
  1100:          dec     @OldEndP1 + 1
  1101:          sec
  1102:  
  1103:  @CalcNewEnd:
  1104:          lda     @NewEndP1
  1105:          sbc     zINDEX
  1106:          sta     @NewEndP1
  1107:          bcs     @ProcessNextPage
  1108:          dec     @NewEndP1 + 1
  1109:          bcc     @ProcessNextPage    ; unconditional jump
  1110:          ; --------------------------
  1111:  
  1112:  @Loop:
  1113:          lda     (@OldEndP1),y       ; copy from old...
  1114:          sta     (@NewEndP1),y       ; ... to new location
  1115:  @ProcessNextPage:
  1116:          dey                         ; number of bytes to process in this page
  1117:          bne     @Loop               ; not zero? Then, copy memory.
  1118:  
  1119:          ; copy the "last" byte of each page separately
  1120:          lda     (@OldEndP1),y
  1121:          sta     (@NewEndP1),y
  1122:  
  1123:  @SkipPartialPage:
  1124:          ; decrement the page numbers of source and destination
  1125:          ; and check if we have more pages to process (x).
  1126:  
  1127:          dec     @OldEndP1 + 1
  1128:          dec     @NewEndP1 + 1
  1129:          dex
  1130:          bne     @ProcessNextPage
  1131:          rts
  1132:  
  1133:  
  1134:          ; check if there is enough memory on the stack
  1135:          ;
  1136:          ; Input:
  1137:          ;   A:
  1138:          ;     Half of the number of bytes to check for
  1139:          ;     (that is, the number of double bytes)
  1140:          ;
  1141:          ; Output:
  1142:          ;   If this function returns, there is enough memory
  1143:          ;   on the stack.
  1144:          ;
  1145:          ; Remark:
  1146:          ;   If there is not enough memory on the stack, this
  1147:          ;   function does not return, but outputs an "?OUT OF MEMORY ERROR"
  1148:          ;
  1149:  bGETSTK:
  1150:          ; first of all, calculate how much byte we would not
  1151:          asl     a        ; as we are checking for double-words, multiply with 2
  1152:          adc     #$3E     ; add a "security area" (@? Why $3E = 62)
  1153:          bcs     bOMERR   ; we overflowed, that is, it would not even fit into the 256 byte stack
  1154:          sta     zINDEX   ; remember the value
  1155:  
  1156:          ; now, check if the stack pointer is higher than what we just calculated
  1157:          tsx
  1158:          cpx     zINDEX
  1159:          bcc     bOMERR
  1160:          rts
  1161:  
  1162:  bREASON:
  1163:          cpy     zFRETOP + 1
  1164:          bcc     @Ret
  1165:          bne     @LA412
  1166:          cmp     zFRETOP
  1167:          bcc     @Ret
  1168:  
  1169:          ; save zTMPF1 and zTMPF2 area onto the stack
  1170:  
  1171:  @SAVE_AREA_SIZE = zFACEXP - zTEMPF1
  1172:  
  1173:  @LA412: pha
  1174:          ldx     #@SAVE_AREA_SIZE - 1
  1175:          tya
  1176:  @LA416: pha
  1177:          lda     zTEMPF1,x
  1178:          dex
  1179:          bpl     @LA416
  1180:  
  1181:          jsr     bGARBAG
  1182:  
  1183:          ; restore the zTMPF1 and zTMPF2 area from the stack
  1184:          ldx     #-(@SAVE_AREA_SIZE - 1)
  1185:  @LA421: pla
  1186:          sta     zTEMPF1 + @SAVE_AREA_SIZE,x
  1187:          inx
  1188:          bmi     @LA421
  1189:          pla
  1190:          tay
  1191:          pla
  1192:          cpy     zFRETOP + 1
  1193:          bcc     @Ret
  1194:          bne     bOMERR
  1195:          cmp     zFRETOP
  1196:          bcs     bOMERR
  1197:  @Ret:   rts
  1198:  
  1199:  bOMERR: ldx     #ErrOutOfMemory
  1200:  bERROR: jmp     (lIERROR)       ; for the VIC - 20, this is a no-op
  1201:                                  ; for the C64, only proceed if bit 7
  1202:                                  ; of the error code is not set
  1203:  
  1204:          ; output a specific error message
  1205:          ;
  1206:          ; Input:
  1207:          ;   X:
  1208:          ;     The number of the error message
  1209:          ;
  1210:          ; Remark:
  1211:          ;   After outputting the message, this function returns into
  1212:          ;   the main BASIC loop. It never returns to its caller.
  1213:          ;
  1214:  ErrorOut:
  1215:          txa                     ; multiply the error number with 2
  1216:          asl     a               ; (this gives a pointer into the error text table)
  1217:          tax
  1218:          lda     bERRPTR - 2,x     ; Get the low byte
  1219:          sta     zINDEX
  1220:          lda     bERRPTR - 1,x     ; and the high byte into zIndex/zIndex + 1
  1221:          sta     zINDEX + 1
  1222:  
  1223:          jsr     kCLRCHN         ; clear channel, that is, output to the screen
  1224:  
  1225:          lda     #0              ; make sure: we do not want to output LF after CR anymore
  1226:          sta     z13
  1227:          jsr     bCRDO           ; output a CR
  1228:  
  1229:          jsr     LAB45           ; output a question mark '?'
  1230:  
  1231:          ; now, output the text from the table
  1232:  
  1233:          ldy     #0              ; start at the first character of the text
  1234:  @Loop:  lda     (zINDEX),y      ; get the next character
  1235:          pha                     ; remember it
  1236:          and     #$7F            ; clear bit 7 (thus, make it printable)
  1237:          jsr     LAB47           ; output the character
  1238:          iny                     ; proceed to the next character
  1239:          pla                     ; get back the remembered character
  1240:          bpl     @Loop           ; if bit 7 was not set, proceed to the next character
  1241:  
  1242:          jsr     LA67A           ; initialize stack pointers (hardware stack and string stack)
  1243:  
  1244:          ; output the text "error"
  1245:  
  1246:          lda     #<StrError
  1247:          ldy     #>StrError
  1248:  
  1249:  bERRFIN:jsr     bSTROUT         ; output the text given in A/Y.a
  1250:  
  1251:          ldy     zCURLIN + 1     ; get high byte of current line (is $FF if in direct mode)
  1252:          iny
  1253:          beq     bREADY          ; it was $FF, thus, skip th next instruction
  1254:          jsr     bINPRT          ; output "in line XXX"
  1255:  
  1256:  bREADY: lda     #<StrReady
  1257:          ldy     #>StrReady
  1258:          jsr     bSTROUT
  1259:          lda     #$80            ; set the direct modus flag
  1260:          jsr     kSETMSG
  1261:  
  1262:  bMAIN:  jmp     (lIMAIN)        ; points to IMAIN normally
  1263:  IMAIN:  jsr     bINLIN
  1264:          stx     zTXTPTR
  1265:          sty     zTXTPTR + 1
  1266:          jsr     zCHRGET
  1267:          tax
  1268:          beq     bMAIN
  1269:          ldx     #$FF            ; set the line number to >= $FF00 = 65280 - as line numbers > 64999 are not allowed, this is a marker that no program is running currently
  1270:          stx     zCURLIN + 1
  1271:          bcc     bMAIN1
  1272:          jsr     bCRUNCH
  1273:          jmp     bGONE
  1274:  bMAIN1: jsr     bLINGET
  1275:          jsr     bCRUNCH
  1276:  bINSLIN:sty     zCOUNT
  1277:  
  1278:          @58 = zTEMPF1 + 1
  1279:          @5A = zTEMPF1 + 3
  1280:  
  1281:          @5F = zTEMPF2 + 3
  1282:  
  1283:          jsr     bFNDLIN
  1284:          bcc     @LA4ED
  1285:          ldy     #1
  1286:          lda     (@5F),y
  1287:          sta     zINDEX + 1
  1288:          lda     zVARTAB
  1289:          sta     zINDEX
  1290:          lda     @5F + 1
  1291:          sta     zINDEX2 + 1
  1292:          lda     @5F
  1293:          dey
  1294:          sbc     (@5F),y
  1295:          clc
  1296:          adc     zVARTAB
  1297:          sta     zVARTAB
  1298:          sta     zINDEX2
  1299:          lda     zVARTAB + 1
  1300:          adc     #-1
  1301:          sta     zVARTAB + 1
  1302:          sbc     @5F + 1
  1303:          tax
  1304:          sec
  1305:          lda     @5F
  1306:          sbc     zVARTAB
  1307:          tay
  1308:          bcs     @LA4D7
  1309:          inx
  1310:          dec     zINDEX2 + 1
  1311:  @LA4D7:
  1312:          clc
  1313:          adc     zINDEX
  1314:          bcc     @LA4DF
  1315:          dec     zINDEX + 1
  1316:          clc
  1317:  @LA4DF:
  1318:          lda     (zINDEX),y
  1319:          sta     (zINDEX2),y
  1320:          iny
  1321:          bne     @LA4DF
  1322:          inc     zINDEX + 1
  1323:          inc     zINDEX2 + 1
  1324:          dex
  1325:          bne     @LA4DF
  1326:  @LA4ED:
  1327:          jsr     LA659
  1328:          jsr     bLINKPRG
  1329:          lda     lBUF
  1330:          beq     bMAIN
  1331:          clc
  1332:          lda     zVARTAB
  1333:          sta     @5A
  1334:          adc     zCOUNT
  1335:          sta     @58
  1336:          ldy     zVARTAB + 1
  1337:          sty     @5A + 1
  1338:          bcc     @LA508
  1339:          iny
  1340:  @LA508:
  1341:          sty     @58 + 1
  1342:          jsr     bBLTU
  1343:          lda     zLINNUM
  1344:          ldy     zLINNUM + 1
  1345:          sta     lBUF - 2
  1346:          sty     lBUF - 1
  1347:          lda     zSTREND
  1348:          ldy     zSTREND + 1
  1349:          sta     zVARTAB
  1350:          sty     zVARTAB + 1
  1351:          ldy     zCOUNT
  1352:          dey
  1353:  @LA522:
  1354:          lda     lBUF - 4,y
  1355:          sta     (@5F),y
  1356:          dey
  1357:          bpl     @LA522
  1358:  LA52A:  jsr     LA659
  1359:          jsr     bLINKPRG
  1360:          jmp     bMAIN
  1361:  bLINKPRG:
  1362:          lda     zTXTTAB
  1363:          ldy     zTXTTAB + 1
  1364:          sta     zINDEX
  1365:          sty     zINDEX + 1
  1366:          clc
  1367:  @LA53C:
  1368:          ldy     #1
  1369:          lda     (zINDEX),y
  1370:          beq     @Ret
  1371:          ldy     #4
  1372:  @LA544:
  1373:          iny
  1374:          lda     (zINDEX),y
  1375:          bne     @LA544
  1376:          iny
  1377:          tya
  1378:          adc     zINDEX
  1379:          tax
  1380:          ldy     #0
  1381:          sta     (zINDEX),y
  1382:          lda     zINDEX + 1
  1383:          adc     #0
  1384:          iny
  1385:          sta     (zINDEX),y
  1386:          stx     zINDEX
  1387:          sta     zINDEX + 1
  1388:          bcc     @LA53C
  1389:  @Ret:   rts
  1390:  
  1391:  bINLIN: ldx     #0
  1392:  @LA562: jsr     bCHIN
  1393:          cmp     #ASC_CR
  1394:          beq     @LA576
  1395:          sta     lBUF,x
  1396:          inx
  1397:          cpx     #END_lBUF - lBUF
  1398:          bcc     @LA562
  1399:          ldx     #ErrStringTooLong
  1400:          jmp     bERROR
  1401:  
  1402:  @LA576: jmp     bSTREND
  1403:  
  1404:  bCRUNCH:jmp     (lICRNCH)
  1405:  LA57C:  ldx     zTXTPTR
  1406:          ldy     #$04
  1407:          sty     zGARBFL
  1408:  LA582:  lda     lBUF,x
  1409:          bpl     @LA58E
  1410:          cmp     #TokPi
  1411:          beq     LA5C9
  1412:          inx
  1413:          bne     LA582
  1414:  @LA58E:
  1415:          cmp     #' '
  1416:          beq     LA5C9
  1417:          sta     zENDCHR
  1418:          cmp     #'"'
  1419:          beq     LA5EE
  1420:          bit     zGARBFL
  1421:          bvs     LA5C9
  1422:          cmp     #'?'
  1423:          bne     @LA5A4
  1424:          lda     #TokPrint
  1425:          bne     LA5C9
  1426:  @LA5A4:
  1427:          cmp     #'0'
  1428:          bcc     @LA5AC
  1429:          cmp     #'<'
  1430:          bcc     LA5C9
  1431:  @LA5AC:
  1432:          sty     zFBUFPT
  1433:          ldy     #0
  1434:          sty     zCOUNT
  1435:          dey
  1436:          stx     zTXTPTR
  1437:          dex
  1438:  LA5B6:  iny
  1439:          inx
  1440:  LA5B8:  lda     lBUF,x
  1441:          sec
  1442:          sbc     bRESLST,y
  1443:          beq     LA5B6
  1444:          cmp     #$80
  1445:          bne     LA5F5
  1446:          ora     zCOUNT
  1447:  LA5C7:  ldy     zFBUFPT
  1448:  LA5C9:  inx
  1449:          iny
  1450:          sta     lBUF - 5,y
  1451:          lda     lBUF - 5,y
  1452:          beq     LA609
  1453:          sec
  1454:          sbc     #$3A            ; ':' @?
  1455:          beq     @LA5DC
  1456:          cmp     #$49            ; DATA @?
  1457:          bne     @LA5DE
  1458:  @LA5DC:
  1459:          sta     zGARBFL
  1460:  @LA5DE:
  1461:          sec
  1462:          sbc     #$55            ; REM @?
  1463:          bne     LA582
  1464:  JDLA5E3:
  1465:          sta     zENDCHR
  1466:  LA5E5:  lda     lBUF,x
  1467:          beq     LA5C9
  1468:          cmp     zENDCHR
  1469:          beq     LA5C9
  1470:  LA5EE:  iny
  1471:          sta     lBUF - 5,y
  1472:          inx
  1473:          bne     LA5E5
  1474:  LA5F5:  ldx     zTXTPTR
  1475:          inc     zCOUNT
  1476:  @LA5F9: iny
  1477:          lda     bRESLST - 1,y
  1478:          bpl     @LA5F9
  1479:          lda     bRESLST,y
  1480:          bne     LA5B8
  1481:          lda     lBUF,x
  1482:          bpl     LA5C7
  1483:  LA609:  sta     lBUF - 3,y
  1484:          dec     zTXTPTR + 1     ; = 1, this is (>(lBUF - 1))
  1485:          lda     #<lBUF - 1
  1486:          sta     zTXTPTR
  1487:          rts
  1488:  
  1489:  bFNDLIN:lda     zTXTTAB
  1490:          ldx     zTXTTAB + 1
  1491:  LA617:  ldy     #1
  1492:          sta     zTEMP_5F
  1493:          stx     zTEMP_5F + 1
  1494:          lda     (zTEMP_5F),y
  1495:          beq     @RetSuccess
  1496:          iny
  1497:          iny
  1498:          lda     zLINNUM + 1
  1499:          cmp     (zTEMP_5F),y
  1500:          bcc     @Ret
  1501:          beq     @LA62E
  1502:          dey
  1503:          bne     @LA637
  1504:  @LA62E:
  1505:          lda     zLINNUM
  1506:          dey
  1507:          cmp     (zTEMP_5F),y
  1508:          bcc     @Ret
  1509:          beq     @Ret
  1510:  @LA637:
  1511:          dey
  1512:          lda     (zTEMP_5F),y
  1513:          tax
  1514:          dey
  1515:          lda     (zTEMP_5F),y
  1516:          bcs     LA617
  1517:  @RetSuccess:
  1518:          clc
  1519:  @Ret:   rts
  1520:  
  1521:  RetA641 = @Ret
  1522:  
  1523:  bSCRTCH:bne     RetA641
  1524:  LA644:  lda     #0
  1525:          tay
  1526:          sta     (zTXTTAB),y
  1527:          iny
  1528:          sta     (zTXTTAB),y
  1529:          lda     zTXTTAB
  1530:          clc
  1531:          adc     #<2
  1532:          sta     zVARTAB
  1533:          lda     zTXTTAB + 1
  1534:          adc     #>2
  1535:          sta     zVARTAB + 1
  1536:  
  1537:  LA659:  jsr     bSTXPT
  1538:          lda     #0
  1539:  
  1540:  bCLEAR: bne     RetA68D
  1541:  LA660:  jsr     kCLALL
  1542:  LA663:  lda     zMEMSIZ
  1543:          ldy     zMEMSIZ + 1
  1544:          sta     zFRETOP
  1545:          sty     zFRETOP + 1
  1546:          lda     zVARTAB
  1547:          ldy     zVARTAB + 1
  1548:          sta     zARYTAB
  1549:          sty     zARYTAB + 1
  1550:          sta     zSTREND
  1551:          sty     zSTREND + 1
  1552:  LA677:  jsr     bRESTOR
  1553:  
  1554:  LA67A:  ldx     #zTEMPST
  1555:          stx     zTEMPPT
  1556:          pla
  1557:          tay
  1558:          pla
  1559:          ldx     #-6
  1560:          txs             ; Stackpointer to $01FA
  1561:          pha
  1562:          tya
  1563:          pha
  1564:          lda     #0
  1565:          sta     zOLDTXT + 1
  1566:          sta     zINTALLOWED
  1567:  RetA68D:
  1568:          rts
  1569:  
  1570:  bSTXPT: clc
  1571:          lda     zTXTTAB
  1572:          adc     #<-1
  1573:          sta     zTXTPTR
  1574:          lda     zTXTTAB + 1
  1575:          adc     #>-1
  1576:          sta     zTXTPTR + 1
  1577:          rts
  1578:  
  1579:  bLIST:  bcc     LA6A4
  1580:          beq     LA6A4
  1581:          cmp     #TokMinus
  1582:          bne     RetA68D
  1583:  LA6A4:
  1584:          jsr     bLINGET
  1585:          jsr     bFNDLIN
  1586:          jsr     zCHRGOT
  1587:          beq     @LA6BB
  1588:          cmp     #TokMinus
  1589:          bne     RetA641
  1590:          jsr     zCHRGET
  1591:          jsr     bLINGET
  1592:          bne     RetA641
  1593:  @LA6BB:
  1594:          pla
  1595:          pla
  1596:          lda     zLINNUM
  1597:          ora     zLINNUM + 1
  1598:          bne     LA6C9
  1599:  JDLA6C3:
  1600:          lda     #-1
  1601:          sta     zLINNUM
  1602:          sta     zLINNUM + 1
  1603:  LA6C9:  ldy     #1
  1604:          sty     zGARBFL
  1605:          lda     (zTEMP_5F),y
  1606:          beq     LA714
  1607:          jsr     bSTOP
  1608:  JDLA6D4:
  1609:          jsr     bCRDO
  1610:          iny
  1611:          lda     (zTEMP_5F),y
  1612:          tax
  1613:          iny
  1614:          lda     (zTEMP_5F),y
  1615:          cmp     zLINNUM + 1
  1616:          bne     @LA6E6
  1617:          cpx     zLINNUM
  1618:          beq     @LA6E8
  1619:  @LA6E6:  bcs     LA714
  1620:  @LA6E8:  sty     zFORPNT
  1621:          jsr     LBDCD
  1622:          lda     #' '
  1623:  LA6EF:  ldy     zFORPNT
  1624:          and     #$7F
  1625:  LA6F3:  jsr     LAB47
  1626:          cmp     #'"'
  1627:          bne     LA700
  1628:          lda     zGARBFL
  1629:          eor     #$FF
  1630:          sta     zGARBFL
  1631:  LA700:  iny
  1632:          beq     LA714
  1633:          lda     (zTEMP_5F),y
  1634:          bne     bQPLOP
  1635:          tay
  1636:          lda     (zTEMP_5F),y
  1637:          tax
  1638:          iny
  1639:          lda     (zTEMP_5F),y
  1640:          stx     zTEMP_5F
  1641:          sta     zTEMP_5F + 1
  1642:          bne     LA6C9
  1643:  LA714:
  1644:  .if CompileComputer >= C64_GENERAL
  1645:          jmp     ReadyVector
  1646:  .else
  1647:          jmp     bREADY
  1648:  .endif
  1649:  
  1650:  bQPLOP: jmp     (lIQPLOP)
  1651:  LA71A:  bpl     LA6F3
  1652:          cmp     #TokPi
  1653:          beq     LA6F3
  1654:          bit     zGARBFL
  1655:          bmi     LA6F3
  1656:          sec
  1657:          sbc     #$7F
  1658:          tax
  1659:          sty     zFORPNT
  1660:          ldy     #$FF
  1661:  @LA72C:
  1662:          dex
  1663:          beq     @LA737
  1664:  @LA72F:
  1665:          iny
  1666:          lda     bRESLST,y
  1667:          bpl     @LA72F
  1668:          bmi     @LA72C
  1669:  @LA737:
  1670:          iny
  1671:          lda     bRESLST,y
  1672:          bmi     LA6EF
  1673:          jsr     LAB47
  1674:          bne     @LA737
  1675:  
  1676:  bFOR:   lda     #$80
  1677:          sta     zINTALLOWED
  1678:          jsr     bLET
  1679:          jsr     bFNDFOR
  1680:          bne     @LA753
  1681:          txa
  1682:          adc     #$0F
  1683:          tax
  1684:          txs
  1685:  @LA753:
  1686:          pla
  1687:          pla
  1688:          lda     #$09
  1689:          jsr     bGETSTK
  1690:          jsr     bDATAN
  1691:          clc
  1692:          tya
  1693:          adc     zTXTPTR
  1694:          pha
  1695:          lda     zTXTPTR + 1
  1696:          adc     #0
  1697:          pha
  1698:          lda     zCURLIN + 1
  1699:          pha
  1700:          lda     zCURLIN
  1701:          pha
  1702:          lda     #TokTo
  1703:          jsr     LAEFF
  1704:          jsr     LAD8D
  1705:          jsr     bFRMNUM
  1706:          lda     zFACSGN
  1707:          ora     #$7F
  1708:          and     zFACHO
  1709:          sta     zFACHO
  1710:          lda     #<@LA78B
  1711:          ldy     #>@LA78B
  1712:          sta     zINDEX
  1713:          sty     zINDEX + 1
  1714:          jmp     LAE43
  1715:  
  1716:  @LA78B:
  1717:          lda     #<bFPTABL
  1718:          ldy     #>bFPTABL
  1719:          jsr     bMOVFM
  1720:          jsr     zCHRGOT
  1721:          cmp     #TokStep
  1722:          bne     @LA79F
  1723:          jsr     zCHRGET
  1724:          jsr     bFRMNUM
  1725:  @LA79F:
  1726:          jsr     bSIGN
  1727:          jsr     LAE38
  1728:          lda     zFORPNT + 1
  1729:          pha
  1730:          lda     zFORPNT
  1731:          pha
  1732:          lda     #TokFor
  1733:          pha
  1734:  bNEWSTT:jsr     bSTOP
  1735:          lda     zTXTPTR
  1736:          ldy     zTXTPTR + 1
  1737:          cpy     #>lBUF
  1738:          nop
  1739:          beq     @LA7BE
  1740:          sta     zOLDTXT
  1741:          sty     zOLDTXT + 1
  1742:  @LA7BE:
  1743:          ldy     #0
  1744:          lda     (zTXTPTR),y
  1745:          bne     LA807
  1746:  
  1747:  bCKEOL: ldy     #2
  1748:          lda     (zTXTPTR),y
  1749:          clc
  1750:          bne     @LA7CE
  1751:          jmp     LA84B
  1752:  @LA7CE:
  1753:          iny
  1754:          lda     (zTXTPTR),y
  1755:          sta     zCURLIN
  1756:          iny
  1757:          lda     (zTXTPTR),y
  1758:          sta     zCURLIN + 1
  1759:          tya
  1760:          adc     zTXTPTR
  1761:          sta     zTXTPTR
  1762:          bcc     bGONE
  1763:          inc     zTXTPTR + 1
  1764:  
  1765:  bGONE:  jmp     (lIGONE)
  1766:  LA7E4:  jsr     zCHRGET
  1767:          jsr     bGONE3
  1768:          jmp     bNEWSTT
  1769:  bGONE3: beq     RetA82B
  1770:  LA7EF:  sbc     #TokEnd
  1771:          bcc     @LA804
  1772:          cmp     #TokTab - TokEnd
  1773:          bcs     LA80E
  1774:          asl     a
  1775:          tay
  1776:          lda     bSTMDSP + 1,y
  1777:          pha
  1778:          lda     bSTMDSP,y
  1779:          pha
  1780:          jmp     zCHRGET
  1781:  @LA804:
  1782:          jmp     bLET
  1783:  
  1784:  LA807:  cmp     #':'
  1785:          beq     bGONE
  1786:  LA80B:  jmp     bSYNERR
  1787:  
  1788:  LA80E:  cmp     #TokGo - $80
  1789:          bne     LA80B
  1790:          jsr     zCHRGET
  1791:          lda     #TokTo
  1792:          jsr     LAEFF
  1793:          jmp     bGOTO
  1794:  bRESTOR:sec
  1795:          lda     zTXTTAB
  1796:          sbc     #1
  1797:          ldy     zTXTTAB + 1
  1798:          bcs     LA827
  1799:          dey
  1800:  LA827:  sta     zDATPTR
  1801:          sty     zDATPTR + 1
  1802:  RetA82B:
  1803:          rts
  1804:  
  1805:  bSTOP:  jsr     kSTOP
  1806:  bSTOP2: bcs     LA832
  1807:  bEND:   clc
  1808:  LA832:  bne     RetA870
  1809:          lda     zTXTPTR
  1810:          ldy     zTXTPTR + 1
  1811:          ldx     zCURLIN + 1
  1812:          inx
  1813:          beq     @LA849
  1814:          sta     zOLDTXT
  1815:          sty     zOLDTXT + 1
  1816:          lda     zCURLIN
  1817:          ldy     zCURLIN + 1
  1818:          sta     zOLDLIN
  1819:          sty     zOLDLIN + 1
  1820:  @LA849:
  1821:          pla
  1822:          pla
  1823:  
  1824:  LA84B:  lda     #<StrCrBreak
  1825:          ldy     #>StrCrBreak
  1826:          bcc     LA854
  1827:          jmp     bERRFIN
  1828:  
  1829:  LA854:
  1830:  .if CompileComputer >= C64_GENERAL
  1831:          jmp     ReadyVector
  1832:  .else
  1833:          jmp     bREADY
  1834:  .endif
  1835:  
  1836:  bCONT:  bne     RetA870
  1837:          ldx     #ErrCantContinue
  1838:          ldy     zOLDTXT + 1
  1839:          bne     @LA862
  1840:          jmp     bERROR
  1841:  
  1842:  @LA862:
  1843:          lda     zOLDTXT
  1844:          sta     zTXTPTR
  1845:          sty     zTXTPTR + 1
  1846:          lda     zOLDLIN
  1847:          ldy     zOLDLIN + 1
  1848:          sta     zCURLIN
  1849:          sty     zCURLIN + 1
  1850:  RetA870:
  1851:          rts
  1852:  
  1853:  bRUN:   php
  1854:          lda     #0
  1855:          jsr     kSETMSG
  1856:          plp
  1857:          bne     @LA87D
  1858:          jmp     LA659
  1859:  
  1860:  @LA87D:
  1861:          jsr     LA660
  1862:          jmp     LA897
  1863:  
  1864:  bGOSUB: lda     #3              ; we want to push 3 16 bit values on the stack
  1865:          jsr     bGETSTK         ; check for enough memory on stack
  1866:          lda     zTXTPTR + 1
  1867:          pha
  1868:          lda     zTXTPTR
  1869:          pha
  1870:          lda     zCURLIN + 1
  1871:          pha
  1872:          lda     zCURLIN
  1873:          pha
  1874:          lda     #TokGosub
  1875:          pha
  1876:  
  1877:  LA897:  jsr     zCHRGOT
  1878:          jsr     bGOTO
  1879:          jmp     bNEWSTT
  1880:  
  1881:  bGOTO:  jsr     bLINGET
  1882:          jsr     LA909
  1883:          sec
  1884:          lda     zCURLIN
  1885:          sbc     zLINNUM
  1886:          lda     zCURLIN + 1
  1887:          sbc     zLINNUM + 1
  1888:          bcs     @LA8BC
  1889:          tya
  1890:          sec
  1891:          adc     zTXTPTR
  1892:          ldx     zTXTPTR + 1
  1893:          bcc     @LA8C0
  1894:          inx
  1895:          bcs     @LA8C0
  1896:  @LA8BC:
  1897:          lda     zTXTTAB
  1898:          ldx     zTXTTAB + 1
  1899:  @LA8C0:
  1900:          jsr     LA617
  1901:          bcc     LA8E3
  1902:          lda     zTEMP_5F
  1903:          sbc     #<1
  1904:          sta     zTXTPTR
  1905:          lda     zTEMP_5F + 1
  1906:          sbc     #>0
  1907:          sta     zTXTPTR + 1
  1908:  RetA8D1:
  1909:          rts
  1910:  
  1911:  bRETURN:bne     RetA8D1
  1912:          lda     #-1
  1913:          sta     zFORPNT + 1
  1914:          jsr     bFNDFOR
  1915:          txs
  1916:          cmp     #TokGosub
  1917:          beq     LA8EB
  1918:          ldx     #ErrReturnWithoutGosub
  1919:          .byte   ASM_BIT3
  1920:  LA8E3:  ldx     #ErrUndefinedStatement
  1921:          jmp     bERROR
  1922:  LA8E8:  jmp     bSYNERR
  1923:  LA8EB:  pla
  1924:          pla
  1925:          sta     zCURLIN
  1926:          pla
  1927:          sta     zCURLIN + 1
  1928:          pla
  1929:          sta     zTXTPTR
  1930:          pla
  1931:          sta     zTXTPTR + 1
  1932:  
  1933:  bDATA:  jsr     bDATAN
  1934:  LA8FB:  tya
  1935:  
  1936:  JDLA8FC:
  1937:          clc
  1938:          adc     zTXTPTR
  1939:          sta     zTXTPTR
  1940:          bcc     RetA905
  1941:          inc     zTXTPTR + 1
  1942:  RetA905:
  1943:          rts
  1944:  
  1945:  bDATAN: ldx     #':'
  1946:          .byte   ASM_BIT3
  1947:  LA909:  ldx     #0              ; end of line
  1948:          stx     zCHARAC
  1949:          ldy     #0
  1950:          sty     zENDCHR
  1951:  LA911:
  1952:          lda     zENDCHR
  1953:          ldx     zCHARAC
  1954:          sta     zCHARAC
  1955:  JDLA917:
  1956:          stx     zENDCHR
  1957:  @LA919:
  1958:          lda     (zTXTPTR),y
  1959:          beq     RetA905
  1960:          cmp     zENDCHR
  1961:          beq     RetA905
  1962:          iny
  1963:          cmp     #'"'
  1964:          bne     @LA919
  1965:          beq     LA911
  1966:          ; ----------------
  1967:  
  1968:  bIF:    jsr     bFRMEVL
  1969:          jsr     zCHRGOT
  1970:          cmp     #TokGoto
  1971:          beq     @LA937
  1972:          lda     #TokThen
  1973:          jsr     LAEFF
  1974:  @LA937:
  1975:          lda     zFACEXP
  1976:          bne     LA940
  1977:  
  1978:  bREM:   jsr     LA909
  1979:          beq     LA8FB
  1980:  LA940:  jsr     zCHRGOT
  1981:          bcs     @LA948
  1982:          jmp     bGOTO
  1983:  
  1984:  @LA948:
  1985:          jmp     bGONE3
  1986:  
  1987:  bONGOTO:jsr     LB79E
  1988:          pha
  1989:          cmp     #TokGosub
  1990:          beq     LA957
  1991:  LA953:  cmp     #TokGoto
  1992:          bne     LA8E8
  1993:  LA957:  dec     zFACHO + 3
  1994:          bne     @LA95F
  1995:          pla
  1996:          jmp     LA7EF
  1997:  @LA95F:
  1998:          jsr     zCHRGET
  1999:          jsr     bLINGET
  2000:          cmp     #','
  2001:          beq     LA957
  2002:          pla
  2003:  RetA96A:
  2004:          rts
  2005:  
  2006:  bLINGET:ldx     #0
  2007:          stx     zLINNUM
  2008:          stx     zLINNUM + 1
  2009:  @LA971:
  2010:          bcs     RetA96A
  2011:          sbc     #'0' - 1
  2012:          sta     zCHARAC
  2013:          lda     zLINNUM + 1
  2014:          sta     zINDEX
  2015:          cmp     #>6400          ; interestingly, <6400 is 0.
  2016:          bcs     LA953
  2017:          lda     zLINNUM
  2018:          asl     a
  2019:          rol     zINDEX
  2020:          asl     a
  2021:          rol     zINDEX
  2022:          adc     zLINNUM
  2023:          sta     zLINNUM
  2024:          lda     zINDEX
  2025:          adc     zLINNUM + 1
  2026:          sta     zLINNUM + 1
  2027:          asl     zLINNUM
  2028:          rol     zLINNUM + 1
  2029:          lda     zLINNUM
  2030:          adc     zCHARAC
  2031:          sta     zLINNUM
  2032:          bcc     @LA99F
  2033:          inc     zLINNUM + 1
  2034:  @LA99F:
  2035:          jsr     zCHRGET
  2036:          jmp     @LA971
  2037:  
  2038:  bLET:   jsr     bPTRGET
  2039:          sta     zFORPNT
  2040:          sty     zFORPNT + 1
  2041:          lda     #TokEqual
  2042:          jsr     LAEFF
  2043:          lda     zINTFLG
  2044:          pha
  2045:          lda     zVALTYP
  2046:          pha
  2047:          jsr     bFRMEVL
  2048:          pla
  2049:          rol     a
  2050:          jsr     LAD90
  2051:          bne     bPUTSTR
  2052:          pla
  2053:  LA9C2:  bpl     bPTFLPT
  2054:  
  2055:  bPUTINT:jsr     bROUND
  2056:          jsr     bAYINT
  2057:          ldy     #0
  2058:          lda     zFACHO + 2
  2059:          sta     (zFORPNT),y
  2060:          iny
  2061:          lda     zFACHO + 3
  2062:          sta     (zFORPNT),y
  2063:          rts
  2064:  bPTFLPT:jmp     LBBD0
  2065:  
  2066:  bPUTSTR:pla
  2067:  LA9DA:  ldy     zFORPNT + 1
  2068:          cpy     #>bTI                   ; is the variable TI$?
  2069:          bne     bGETSPT
  2070:          jsr     LB6A6
  2071:  bPUTTIM:cmp     #6
  2072:          bne     @LAA24
  2073:          ldy     #0
  2074:          sty     zFACEXP
  2075:          sty     zFACSGN
  2076:  @LA9ED:
  2077:          sty     zFBUFPT
  2078:          jsr     @LAA1D
  2079:          jsr     bMUL10
  2080:          inc     zFBUFPT
  2081:          ldy     zFBUFPT
  2082:          jsr     @LAA1D
  2083:          jsr     bMOVAF
  2084:          tax
  2085:          beq     @LAA07
  2086:          inx
  2087:          txa
  2088:          jsr     LBAED
  2089:  @LAA07:
  2090:          ldy     zFBUFPT
  2091:          iny
  2092:          cpy     #6
  2093:          bne     @LA9ED
  2094:          jsr     bMUL10
  2095:          jsr     bQINT
  2096:          ldx     zFACHO + 2
  2097:          ldy     zFACHO + 1
  2098:          lda     zFACHO + 3
  2099:          jmp     kSETTIM
  2100:  
  2101:  @LAA1D:
  2102:          lda     (zINDEX),y
  2103:          jsr     zCHRGOT_SPACE
  2104:          bcc     @LAA27
  2105:  @LAA24:
  2106:          jmp     bIQERR
  2107:  
  2108:  @LAA27:
  2109:          sbc     #'0' - 1        ; carry is already set!
  2110:          jmp     LBD7E
  2111:  
  2112:  bGETSPT:ldy     #2
  2113:          lda     (zFACHO + 2),y
  2114:          cmp     zFRETOP + 1
  2115:          bcc     @LAA4B
  2116:          bne     @LAA3D
  2117:          dey
  2118:          lda     (zFACHO + 2),y
  2119:          cmp     zFRETOP
  2120:          bcc     @LAA4B
  2121:  @LAA3D:
  2122:          ldy     zFACHO + 3
  2123:          cpy     zVARTAB + 1
  2124:          bcc     @LAA4B
  2125:          bne     @LAA52
  2126:          lda     zFACHO + 2
  2127:          cmp     zVARTAB
  2128:          bcs     @LAA52
  2129:  @LAA4B:
  2130:          lda     zFACHO + 2
  2131:          ldy     zFACHO + 3
  2132:          jmp     @LAA68
  2133:  
  2134:  @LAA52:
  2135:          ldy     #0
  2136:          lda     (zFACHO + 2),y
  2137:          jsr     LB475
  2138:          lda     zTEMP_50
  2139:          ldy     zTEMP_50 + 1
  2140:          sta     zARISGN
  2141:          sty     zFACOV
  2142:          jsr     bMOVINS
  2143:          lda     #<zFAC
  2144:          ldy     #>zFAC
  2145:  @LAA68:
  2146:          sta     zTEMP_50
  2147:          sty     zTEMP_50 + 1
  2148:          jsr     bFREFAC
  2149:          ldy     #0
  2150:          lda     (zTEMP_50),y
  2151:          sta     (zFORPNT),y
  2152:          iny
  2153:          lda     (zTEMP_50),y
  2154:          sta     (zFORPNT),y
  2155:          iny
  2156:          lda     (zTEMP_50),y
  2157:          sta     (zFORPNT),y
  2158:          rts
  2159:  
  2160:  bPRINTN:jsr     bCMD
  2161:          jmp     LABB5
  2162:  
  2163:  bCMD:   jsr     LB79E
  2164:          beq     @LAA90
  2165:          lda     #','
  2166:          jsr     LAEFF
  2167:  @LAA90:
  2168:          php
  2169:          stx     z13
  2170:          jsr     bCKOUT
  2171:          plp
  2172:          jmp     bPRINT
  2173:  
  2174:  bSTRDON:jsr     LAB21
  2175:  
  2176:  LAA9D:  jsr     zCHRGOT
  2177:  
  2178:  bPRINT: beq     bCRDO
  2179:  LAAA2:  beq     RetAAE7
  2180:          cmp     #TokTab
  2181:          beq     LAAF8
  2182:          cmp     #TokSpc
  2183:          clc
  2184:          beq     LAAF8
  2185:          cmp     #','
  2186:          beq     bCOMPRT
  2187:          cmp     #';'
  2188:          beq     LAB13
  2189:          jsr     bFRMEVL
  2190:  bVAROP: bit     zVALTYP
  2191:          bmi     bSTRDON
  2192:          jsr     bFOUT
  2193:          jsr     bSTRLIT
  2194:          jsr     LAB21
  2195:          jsr     bOUTSPC
  2196:          bne     LAA9D
  2197:  bSTREND:lda     #0
  2198:          sta     lBUF,x
  2199:          ldx     #<(lBUF - 1)
  2200:          ldy     #>(lBUF - 1)
  2201:          lda     z13
  2202:          bne     RetAAE7
  2203:  
  2204:          ; output a CR and possibly a LF
  2205:          ;
  2206:          ; Input:
  2207:          ;   none
  2208:          ;
  2209:          ; Remark:
  2210:          ;   At first, this function outputs a CR ($0D). If z13 is negative,
  2211:          ;   it outputs a LF afterwards.
  2212:          ;
  2213:  bCRDO:  lda     #ASC_CR         ; output the CR
  2214:          jsr     LAB47
  2215:          bit     z13             ; check: Shall we output a LF?
  2216:          bpl     LAAE5
  2217:          lda     #ASC_LF         ; yes, output the LF
  2218:          jsr     LAB47
  2219:  LAAE5:  eor     #$FF
  2220:  RetAAE7:
  2221:          rts
  2222:  
  2223:  bCOMPRT:sec
  2224:          jsr     kPLOT
  2225:          tya
  2226:          sec
  2227:  @LAAEE:
  2228:          sbc     #EDITOR_TAB
  2229:          bcs     @LAAEE
  2230:          eor     #$FF
  2231:          adc     #$01
  2232:          bne     LAB0E
  2233:  LAAF8:  php
  2234:          sec
  2235:          jsr     kPLOT
  2236:          sty     zTRMPOS
  2237:          jsr     bGTBYTC
  2238:          cmp     #')'
  2239:          bne     LAB5F
  2240:          plp
  2241:          bcc     LAB0F
  2242:          txa
  2243:          sbc     zTRMPOS
  2244:          bcc     LAB13
  2245:  LAB0E:  tax
  2246:  LAB0F:  inx
  2247:  LAB10:  dex
  2248:          bne     LAB19
  2249:  LAB13:  jsr     zCHRGET
  2250:          jmp     LAAA2
  2251:  
  2252:  LAB19:  jsr     bOUTSPC
  2253:          bne     LAB10
  2254:  
  2255:  bSTROUT:jsr     bSTRLIT
  2256:  
  2257:  LAB21:  jsr     LB6A6
  2258:          tax
  2259:          ldy     #0
  2260:          inx
  2261:  @LAB28:
  2262:          dex
  2263:          beq     RetAAE7
  2264:          lda     (zINDEX),y
  2265:          jsr     LAB47
  2266:          iny
  2267:          cmp     #ASC_CR
  2268:          bne     @LAB28
  2269:          jsr     LAAE5
  2270:          jmp     @LAB28
  2271:  
  2272:  bOUTSPC:lda     z13
  2273:          beq     @LAB42
  2274:          lda     #' '
  2275:          .byte   ASM_BIT3
  2276:  @LAB42:
  2277:          lda     #ASC_CURSORLEFTRIGHT
  2278:          .byte   ASM_BIT3
  2279:  
  2280:  
  2281:  LAB45:  lda     #'?'
  2282:  
  2283:  LAB47:  jsr     bCHOUT
  2284:          and     #$FF
  2285:          rts
  2286:  
  2287:  bDOAGIN:lda     zSUBFLG
  2288:          beq     LAB62
  2289:          bmi     @LAB57
  2290:          ldy     #$FF
  2291:          bne     @LAB5B
  2292:          ; ---------------
  2293:  @LAB57:
  2294:          lda     zDATLIN
  2295:          ldy     zDATLIN + 1
  2296:  @LAB5B:
  2297:          sta     zCURLIN
  2298:          sty     zCURLIN + 1
  2299:  LAB5F:  jmp     bSYNERR
  2300:  LAB62:  lda     z13
  2301:          beq     @LAB6B
  2302:          ldx     #ErrFileData
  2303:          jmp     bERROR
  2304:  
  2305:  @LAB6B:
  2306:          lda     #<StrRedoFromStart
  2307:          ldy     #>StrRedoFromStart
  2308:          jsr     bSTROUT
  2309:          lda     zOLDTXT
  2310:          ldy     zOLDTXT + 1
  2311:          sta     zTXTPTR
  2312:          sty     zTXTPTR + 1
  2313:          rts
  2314:  
  2315:  bGET:   jsr     bERRDIR
  2316:          cmp     #'#'
  2317:          bne     @LAB92
  2318:          jsr     zCHRGET
  2319:          jsr     LB79E
  2320:          lda     #','
  2321:          jsr     LAEFF
  2322:          stx     z13
  2323:          jsr     bCKIN
  2324:  @LAB92:
  2325:          ldx     #<(lBUF + 1)
  2326:          ldy     #>(lBUF + 1)
  2327:          lda     #0
  2328:          sta     lBUF + 1
  2329:          lda     #$40
  2330:          jsr     LAC0F
  2331:          ldx     z13
  2332:          bne     LABB7
  2333:          rts
  2334:  
  2335:  bINPUTN:jsr     LB79E
  2336:          lda     #','
  2337:          jsr     LAEFF
  2338:          stx     z13
  2339:          jsr     bCKIN
  2340:          jsr     LABCE
  2341:  LABB5:  lda     z13
  2342:  LABB7:  jsr     kCLRCHN
  2343:          ldx     #0
  2344:          stx     z13
  2345:          rts
  2346:  bINPUT: cmp     #'"'
  2347:          bne     LABCE
  2348:          jsr     LAEBD
  2349:          lda     #';'
  2350:          jsr     LAEFF
  2351:          jsr     LAB21
  2352:  LABCE:  jsr     bERRDIR
  2353:          lda     #','
  2354:          sta     lBUF - 1
  2355:  LABD6:  jsr     bQINLIN
  2356:          lda     z13
  2357:          beq     bBUFFUL
  2358:          jsr     kREADST
  2359:          and     #$02
  2360:          beq     bBUFFUL
  2361:          jsr     LABB5
  2362:          jmp     bDATA
  2363:  
  2364:  bBUFFUL:lda     lBUF
  2365:          bne     LAC0D
  2366:          lda     z13
  2367:          bne     LABD6
  2368:          jsr     bDATAN
  2369:          jmp     LA8FB
  2370:  
  2371:  bQINLIN:lda     z13
  2372:          bne     @LAC03
  2373:          jsr     LAB45
  2374:          jsr     bOUTSPC
  2375:  @LAC03:
  2376:          jmp     bINLIN
  2377:  
  2378:  bREAD:  ldx     zDATPTR
  2379:          ldy     zDATPTR + 1
  2380:          lda     #$98
  2381:          .byte   ASM_BIT3
  2382:  LAC0D:  lda     #0
  2383:  LAC0F:  sta     zSUBFLG
  2384:          stx     zINPPTR
  2385:          sty     zINPPTR + 1
  2386:  LAC15:  jsr     bPTRGET
  2387:          sta     zFORPNT
  2388:          sty     zFORPNT + 1
  2389:          lda     zTXTPTR
  2390:          ldy     zTXTPTR + 1
  2391:          sta     zVARTXT
  2392:          sty     zVARTXT + 1
  2393:          ldx     zINPPTR
  2394:          ldy     zINPPTR + 1
  2395:          stx     zTXTPTR
  2396:          sty     zTXTPTR + 1
  2397:          jsr     zCHRGOT
  2398:          bne     LAC51
  2399:          bit     zSUBFLG
  2400:          bvc     LAC41
  2401:  
  2402:  bRGDET: jsr     bGETIN
  2403:          sta     lBUF
  2404:          ldx     #<(lBUF - 1)
  2405:          ldy     #>(lBUF - 1)
  2406:          bne     LAC4D
  2407:  LAC41:  bmi     LACB8
  2408:          lda     z13
  2409:          bne     @LAC4A
  2410:          jsr     LAB45
  2411:  @LAC4A:
  2412:          jsr     bQINLIN
  2413:  
  2414:  LAC4D:  stx     zTXTPTR
  2415:          sty     zTXTPTR + 1
  2416:  LAC51:  jsr     zCHRGET
  2417:          bit     zVALTYP
  2418:          bpl     @LAC89
  2419:          bit     zSUBFLG
  2420:          bvc     @LAC65
  2421:          inx
  2422:          stx     zTXTPTR
  2423:          lda     #0
  2424:          sta     zCHARAC
  2425:          beq     @LAC71
  2426:  @LAC65:
  2427:          sta     zCHARAC
  2428:          cmp     #'"'
  2429:          beq     @LAC72
  2430:          lda     #':'
  2431:          sta     zCHARAC
  2432:          lda     #','
  2433:  @LAC71:
  2434:          clc
  2435:  @LAC72:
  2436:          sta     zENDCHR
  2437:          lda     zTXTPTR
  2438:          ldy     zTXTPTR + 1
  2439:          adc     #0
  2440:          bcc     @LAC7D
  2441:          iny
  2442:  @LAC7D:
  2443:          jsr     LB48D
  2444:          jsr     LB7E2
  2445:          jsr     LA9DA
  2446:          jmp     @LAC91
  2447:  @LAC89:
  2448:          jsr     bFIN
  2449:          lda     zINTFLG
  2450:          jsr     LA9C2
  2451:  @LAC91:
  2452:          jsr     zCHRGOT
  2453:          beq     @LAC9D
  2454:          cmp     #','
  2455:          beq     @LAC9D
  2456:          jmp     bDOAGIN
  2457:  
  2458:  @LAC9D:
  2459:          lda     zTXTPTR
  2460:          ldy     zTXTPTR + 1
  2461:          sta     zINPPTR
  2462:          sty     zINPPTR + 1
  2463:          lda     zVARTXT
  2464:          ldy     zVARTXT + 1
  2465:          sta     zTXTPTR
  2466:          sty     zTXTPTR + 1
  2467:          jsr     zCHRGOT
  2468:          beq     LACDF
  2469:          jsr     bCHKCMA
  2470:          jmp     LAC15
  2471:  LACB8:  jsr     bDATAN
  2472:          iny
  2473:          tax
  2474:          bne     @LACD1
  2475:          ldx     #$0D
  2476:          iny
  2477:          lda     (zTXTPTR),y
  2478:          beq     LAD32
  2479:          iny
  2480:          lda     (zTXTPTR),y
  2481:          sta     zDATLIN
  2482:          iny
  2483:          lda     (zTXTPTR),y
  2484:          iny
  2485:          sta     zDATLIN + 1
  2486:  @LACD1:
  2487:          jsr     LA8FB
  2488:          jsr     zCHRGOT
  2489:          tax
  2490:          cpx     #$83
  2491:          bne     LACB8
  2492:          jmp     LAC51
  2493:  LACDF:  lda     zINPPTR
  2494:          ldy     zINPPTR + 1
  2495:          ldx     zSUBFLG
  2496:          bpl     @LACEA
  2497:          jmp     LA827
  2498:  @LACEA:
  2499:          ldy     #0
  2500:          lda     (zINPPTR),y
  2501:          beq     @Ret
  2502:          lda     z13
  2503:          bne     @Ret
  2504:          lda     #<bEXINT
  2505:          ldy     #>bEXINT
  2506:          jmp     bSTROUT
  2507:  @Ret:   rts
  2508:  
  2509:  bEXINT: .byte   "?EXTRA IGNORED",$0D,$00
  2510:  
  2511:  StrRedoFromStart:
  2512:          .byte   "?REDO FROM START",$0D,$00
  2513:  
  2514:  bNEXT:  bne     LAD24
  2515:          ldy     #0
  2516:          beq     LAD27
  2517:  LAD24:  jsr     bPTRGET
  2518:  LAD27:  sta     zFORPNT
  2519:          sty     zFORPNT + 1
  2520:          jsr     bFNDFOR
  2521:          beq     LAD35
  2522:          ldx     #ErrNextWithoutFor
  2523:  LAD32:  jmp     bERROR
  2524:  LAD35:  txs
  2525:          txa
  2526:          clc
  2527:          adc     #$04
  2528:          pha
  2529:          adc     #$06
  2530:          sta     zINDEX2
  2531:          pla
  2532:          ldy     #$01
  2533:          jsr     bMOVFM
  2534:          tsx
  2535:          lda     lSTACK + 9,x
  2536:          sta     zFACSGN
  2537:          lda     zFORPNT
  2538:          ldy     zFORPNT + 1
  2539:          jsr     bFADD
  2540:          jsr     LBBD0
  2541:          ldy     #$01
  2542:          jsr     LBC5D
  2543:          tsx
  2544:          sec
  2545:          sbc     lSTACK + 9,x
  2546:          beq     LAD78
  2547:  bDONEXT:lda     lSTACK + 15,x
  2548:          sta     zCURLIN
  2549:          lda     lSTACK + 16,x
  2550:          sta     zCURLIN + 1
  2551:          lda     lSTACK + 18,x
  2552:          sta     zTXTPTR
  2553:          lda     lSTACK + 17,x
  2554:          sta     zTXTPTR + 1
  2555:  LAD75:  jmp     bNEWSTT
  2556:  LAD78:  txa
  2557:          adc     #17
  2558:          tax
  2559:          txs
  2560:          jsr     zCHRGOT
  2561:          cmp     #','
  2562:          bne     LAD75
  2563:          jsr     zCHRGET
  2564:          jsr     LAD24
  2565:  bFRMNUM:jsr     bFRMEVL
  2566:  LAD8D:  clc
  2567:          .byte   ASM_BIT2
  2568:  LAD8F:  sec
  2569:  LAD90:  bit     zVALTYP
  2570:          bmi     LAD97
  2571:          bcs     LAD99
  2572:  LAD96:  rts
  2573:  LAD97:  bcs     LAD96
  2574:  LAD99:  ldx     #ErrTypeMismatch
  2575:          jmp     bERROR
  2576:  bFRMEVL:ldx     zTXTPTR
  2577:          bne     LADA4
  2578:          dec     zTXTPTR + 1
  2579:  LADA4:  dec     zTXTPTR
  2580:          ldx     #0
  2581:          .byte   ASM_BIT2
  2582:  LADA9:  pha
  2583:          txa
  2584:          pha
  2585:          lda     #1
  2586:          jsr     bGETSTK
  2587:          jsr     bEVAL
  2588:          lda     #$00
  2589:          sta     zOPMASK
  2590:  LADB8:  jsr     zCHRGOT
  2591:  LADBB:  sec
  2592:          sbc     #TokGreater
  2593:          bcc     LADD7
  2594:          cmp     #TokSgn - TokGreater
  2595:          bcs     LADD7
  2596:          cmp     #TokEqual - TokGreater
  2597:          rol     a
  2598:          eor     #$01
  2599:          eor     zOPMASK
  2600:          cmp     zOPMASK
  2601:          bcc     LAE30
  2602:          sta     zOPMASK
  2603:          jsr     zCHRGET
  2604:          jmp     LADBB
  2605:  LADD7:  ldx     zOPMASK
  2606:          bne     LAE07
  2607:          bcs     LAE58
  2608:          adc     #$07
  2609:          bcc     LAE58
  2610:          adc     zVALTYP
  2611:          bne     LADE8
  2612:          jmp     bCAT
  2613:  LADE8:  adc     #-1
  2614:          sta     zINDEX
  2615:          asl     a
  2616:          adc     zINDEX
  2617:          tay
  2618:  LADF0:  pla
  2619:          cmp     bOPTAB,y
  2620:          bcs     LAE5D
  2621:          jsr     LAD8D
  2622:  LADF9:  pha
  2623:  LADFA:  jsr     LAE20
  2624:          pla
  2625:          ldy     zVARTXT
  2626:          bpl     LAE19
  2627:          tax
  2628:          beq     LAE5B
  2629:          bne     LAE66
  2630:  LAE07:  lsr     zVALTYP
  2631:          txa
  2632:          rol     a
  2633:          ldx     zTXTPTR
  2634:          bne     LAE11
  2635:          dec     zTXTPTR + 1
  2636:  LAE11:  dec     zTXTPTR
  2637:          ldy     #$1B
  2638:          sta     zOPMASK
  2639:          bne     LADF0
  2640:  LAE19:  cmp     bOPTAB,y
  2641:          bcs     LAE66
  2642:          bcc     LADF9
  2643:  LAE20:  lda     bOPTAB + 2,y
  2644:          pha
  2645:          lda     bOPTAB + 1,y
  2646:          pha
  2647:          jsr     LAE33
  2648:          lda     zOPMASK
  2649:          jmp     LADA9
  2650:  LAE30:  jmp     bSYNERR
  2651:  LAE33:  lda     zFACSGN
  2652:          ldx     bOPTAB,y
  2653:  LAE38:  tay
  2654:          pla
  2655:          sta     zINDEX
  2656:          inc     zINDEX
  2657:          pla
  2658:          sta     zINDEX + 1
  2659:          tya
  2660:          pha
  2661:  LAE43:  jsr     bROUND
  2662:          lda     zFACHO + 3
  2663:          pha
  2664:          lda     zFACHO + 2
  2665:          pha
  2666:          lda     zFACHO + 1
  2667:          pha
  2668:          lda     zFACHO
  2669:          pha
  2670:          lda     zFACEXP
  2671:          pha
  2672:          jmp     (zINDEX)
  2673:  LAE58:  ldy     #$FF
  2674:          pla
  2675:  LAE5B:  beq     LAE80
  2676:  LAE5D:  cmp     #$64
  2677:          beq     LAE64
  2678:          jsr     LAD8D
  2679:  LAE64:  sty     zVARTXT
  2680:  LAE66:  pla
  2681:          lsr     a
  2682:          sta     zTANSGN
  2683:          pla
  2684:          sta     zARGEXP
  2685:          pla
  2686:          sta     zARGHO
  2687:          pla
  2688:          sta     zARGHO + 1
  2689:          pla
  2690:          sta     zARGHO + 2
  2691:          pla
  2692:          sta     zARGHO + 3
  2693:          pla
  2694:          sta     zARGSGN
  2695:          eor     zFACSGN
  2696:          sta     zARISGN
  2697:  LAE80:  lda     zFACEXP
  2698:          rts
  2699:  bEVAL:  jmp     (lIEVAL)
  2700:  LAE86:  lda     #$00
  2701:          sta     zVALTYP
  2702:  LAE8A:  jsr     zCHRGET
  2703:          bcs     LAE92
  2704:  LAE8F:  jmp     bFIN
  2705:  LAE92:  jsr     bISLETC
  2706:          bcc     LAE9A
  2707:          jmp     bISVAR
  2708:  LAE9A:  cmp     #$FF
  2709:          bne     bQDOT
  2710:          lda     #<bPIVAL
  2711:          ldy     #>bPIVAL
  2712:          jsr     bMOVFM
  2713:          jmp     zCHRGET
  2714:  
  2715:  bPIVAL: .byte   $82,$49,$0F,$DA,$A1
  2716:  
  2717:  bQDOT:  cmp     #'.'
  2718:          beq     LAE8F
  2719:          cmp     #TokMinus
  2720:          beq     bDOMIN
  2721:          cmp     #TokPlus
  2722:          beq     LAE8A
  2723:          cmp     #'"'
  2724:          bne     LAECC
  2725:  LAEBD:  lda     zTXTPTR
  2726:          ldy     zTXTPTR + 1
  2727:          adc     #0
  2728:          bcc     LAEC6
  2729:          iny
  2730:  LAEC6:  jsr     bSTRLIT
  2731:          jmp     LB7E2
  2732:  LAECC:  cmp     #TokNot
  2733:          bne     LAEE3
  2734:          ldy     #$18
  2735:          bne     LAF0F
  2736:  bEQUOP: jsr     bAYINT
  2737:          lda     zFACHO + 3
  2738:          eor     #$FF
  2739:          tay
  2740:          lda     zFACHO + 2
  2741:          eor     #$FF
  2742:          jmp     bGIVAYF
  2743:  LAEE3:  cmp     #TokFn
  2744:          bne     LAEEA
  2745:          jmp     bFNDOER
  2746:  LAEEA:  cmp     #TokSgn
  2747:          bcc     bOARCHK
  2748:          jmp     bISFUN
  2749:  bOARCHK:jsr     bCHKopen
  2750:          jsr     bFRMEVL
  2751:  bCHKclose:
  2752:          lda     #')'
  2753:          .byte   ASM_BIT3
  2754:  bCHKopen:
  2755:          lda     #'('
  2756:          .byte   ASM_BIT3
  2757:  bCHKCMA:lda     #','
  2758:  LAEFF:  ldy     #0
  2759:          cmp     (zTXTPTR),y
  2760:          bne     bSYNERR
  2761:          jmp     zCHRGET
  2762:  bSYNERR:ldx     #ErrSyntax
  2763:          jmp     bERROR
  2764:  bDOMIN: ldy     #$15
  2765:  LAF0F:  pla
  2766:          pla
  2767:          jmp     LADFA
  2768:  bRSVVAR:sec
  2769:          lda     zFACHO + 2
  2770:          sbc     #<BASIC_START
  2771:          lda     zFACHO + 3
  2772:          sbc     #>BASIC_START
  2773:          bcc     LAF27
  2774:          lda     #<BASIC_END
  2775:          sbc     zFACHO + 2
  2776:          lda     #>BASIC_END
  2777:          sbc     zFACHO + 3
  2778:  LAF27:  rts
  2779:  bISVAR: jsr     bPTRGET
  2780:          sta     zFACHO + 2
  2781:          sty     zFACHO + 3
  2782:          ldx     zVARNAM
  2783:          ldy     zVARNAM + 1
  2784:          lda     zVALTYP
  2785:          beq     LAF5D
  2786:          lda     #0
  2787:          sta     zFACOV
  2788:          jsr     bRSVVAR
  2789:          bcc     LAF5C
  2790:          cpx     #'T'            ; "T"
  2791:          bne     LAF5C
  2792:          cpy     #'I' + $80      ; "I$"
  2793:          bne     LAF5C
  2794:  bTISASC:jsr     LAF84
  2795:          sty     zTEMP_5E
  2796:          dey
  2797:          sty     zFBUFPT
  2798:          ldy     #6
  2799:          sty     zTEMP_5D
  2800:          ldy     #$24
  2801:          jsr     bFOUTIM
  2802:          jmp     LB46F
  2803:  LAF5C:  rts
  2804:  LAF5D:  bit     zINTFLG
  2805:          bpl     LAF6E
  2806:          ldy     #0
  2807:          lda     (zFACHO + 2),y
  2808:          tax
  2809:          iny
  2810:          lda     (zFACHO + 2),y
  2811:          tay
  2812:          txa
  2813:          jmp     bGIVAYF
  2814:  LAF6E:  jsr     bRSVVAR
  2815:          bcc     LAFA0
  2816:          cpx     #'T'
  2817:          bne     LAF92
  2818:          cpy     #'I'
  2819:          bne     LAFA0
  2820:          jsr     LAF84
  2821:          tya
  2822:          ldx     #$A0
  2823:          jmp     LBC4F
  2824:  LAF84:  jsr     kRDTIM
  2825:          stx     zFACHO + 2
  2826:          sty     zFACHO + 1
  2827:          sta     zFACHO + 3
  2828:          ldy     #0
  2829:          sty     zFACHO
  2830:          rts
  2831:  LAF92:  cpx     #'S'
  2832:          bne     LAFA0
  2833:          cpy     #'T'
  2834:          bne     LAFA0
  2835:          jsr     kREADST
  2836:          jmp     LBC3C
  2837:  LAFA0:  lda     zFACHO + 2
  2838:          ldy     zFACHO + 3
  2839:          jmp     bMOVFM
  2840:  bISFUN: asl     a
  2841:          pha
  2842:          tax
  2843:          jsr     zCHRGET
  2844:          cpx     #TokRem
  2845:          bcc     bNUMFUN
  2846:  bSTRFUN:jsr     bCHKopen
  2847:          jsr     bFRMEVL
  2848:          jsr     bCHKCMA
  2849:          jsr     LAD8F
  2850:          pla
  2851:          tax
  2852:          lda     zFACHO + 3
  2853:          pha
  2854:          lda     zFACHO + 2
  2855:          pha
  2856:          txa
  2857:          pha
  2858:          jsr     LB79E
  2859:          pla
  2860:          tay
  2861:          txa
  2862:          pha
  2863:          jmp     LAFD6
  2864:  bNUMFUN:jsr     bOARCHK
  2865:          pla
  2866:          tay
  2867:  LAFD6:  lda     bFUNDSP - 2*(TokSgn - $80),y
  2868:          sta     zJMPER + 1
  2869:          lda     bFUNDSP - 2*(TokSgn - $80) + 1,y
  2870:          sta     zJMPER + 2
  2871:          jsr     zJMPER
  2872:          jmp     LAD8D
  2873:  bOROP:  ldy     #$FF
  2874:          .byte   ASM_BIT3
  2875:  TAND:   ldy     #0
  2876:          sty     zCOUNT
  2877:          jsr     bAYINT
  2878:          lda     zFACHO + 2
  2879:          eor     zCOUNT
  2880:          sta     zCHARAC
  2881:          lda     zFACHO + 3
  2882:          eor     zCOUNT
  2883:          sta     zENDCHR
  2884:          jsr     bMOVFA
  2885:          jsr     bAYINT
  2886:          lda     zFACHO + 3
  2887:          eor     zCOUNT
  2888:          and     zENDCHR
  2889:          eor     zCOUNT
  2890:          tay
  2891:          lda     zFACHO + 2
  2892:          eor     zCOUNT
  2893:          and     zCHARAC
  2894:          eor     zCOUNT
  2895:          jmp     bGIVAYF
  2896:  bDOREL: jsr     LAD90
  2897:          bcs     bSTRREL
  2898:  bNUMREL:lda     zARGSGN
  2899:          ora     #$7F
  2900:          and     zARGHO
  2901:          sta     zARGHO
  2902:          lda     #<zARG
  2903:          ldy     #>zARG
  2904:          jsr     bFCOMP
  2905:          tax
  2906:          jmp     LB061
  2907:  bSTRREL:lda     #0
  2908:          sta     zVALTYP
  2909:          dec     zOPMASK
  2910:          jsr     LB6A6
  2911:          sta     zFACEXP
  2912:          stx     zFACHO
  2913:          sty     zFACHO + 1
  2914:          lda     zARGHO + 2
  2915:          ldy     zARGHO + 3
  2916:          jsr     LB6AA
  2917:          stx     zARGHO + 2
  2918:          sty     zARGHO + 3
  2919:          tax
  2920:          sec
  2921:          sbc     zFACEXP
  2922:          beq     LB056
  2923:          lda     #1
  2924:          bcc     LB056
  2925:          ldx     zFACEXP
  2926:          lda     #$FF
  2927:  LB056:  sta     zFACSGN
  2928:          ldy     #$FF
  2929:          inx
  2930:  LB05B:  iny
  2931:          dex
  2932:          bne     LB066
  2933:          ldx     zFACSGN
  2934:  LB061:  bmi     LB072
  2935:          clc
  2936:          bcc     LB072
  2937:  LB066:  lda     (zARGHO + 2),y
  2938:          cmp     (zFACHO),y
  2939:          beq     LB05B
  2940:          ldx     #$FF
  2941:          bcs     LB072
  2942:          ldx     #$01
  2943:  LB072:  inx
  2944:          txa
  2945:          rol     a
  2946:          and     zTANSGN
  2947:          beq     LB07B
  2948:          lda     #$FF
  2949:  LB07B:  jmp     LBC3C
  2950:  bDIM:   jsr     bCHKCMA
  2951:  bDIM2:  tax
  2952:          jsr     LB090
  2953:          jsr     zCHRGOT
  2954:          bne     bDIM
  2955:          rts
  2956:  bPTRGET:ldx     #$00
  2957:          jsr     zCHRGOT
  2958:  LB090:  stx     zDIMFLG
  2959:  LB092:  sta     zVARNAM
  2960:          jsr     zCHRGOT
  2961:          jsr     bISLETC
  2962:          bcs     LB09F
  2963:  LB09C:  jmp     bSYNERR
  2964:  LB09F:  ldx     #$00
  2965:          stx     zVALTYP
  2966:          stx     zINTFLG
  2967:          jsr     zCHRGET
  2968:          bcc     LB0AF
  2969:          jsr     bISLETC
  2970:          bcc     LB0BA
  2971:  LB0AF:  tax
  2972:  LB0B0:  jsr     zCHRGET
  2973:          bcc     LB0B0
  2974:          jsr     bISLETC
  2975:          bcs     LB0B0
  2976:  LB0BA:  cmp     #'$'
  2977:          bne     LB0C4
  2978:          lda     #$FF
  2979:          sta     zVALTYP
  2980:          bne     LB0D4
  2981:  LB0C4:  cmp     #'%'
  2982:          bne     LB0DB
  2983:          lda     zINTALLOWED
  2984:          bne     LB09C
  2985:          lda     #$80
  2986:          sta     zINTFLG
  2987:          ora     zVARNAM
  2988:          sta     zVARNAM
  2989:  LB0D4:  txa
  2990:          ora     #$80
  2991:          tax
  2992:          jsr     zCHRGET
  2993:  LB0DB:  stx     zVARNAM + 1
  2994:          sec
  2995:          ora     zINTALLOWED
  2996:          sbc     #'('
  2997:          bne     bORDVAR
  2998:          jmp     bISARY
  2999:  bORDVAR:ldy     #$00
  3000:          sty     zINTALLOWED
  3001:          lda     zVARTAB
  3002:          ldx     zVARTAB + 1
  3003:  LB0EF:  stx     zTEMP_5F + 1
  3004:  LB0F1:  sta     zTEMP_5F
  3005:          cpx     zARYTAB + 1
  3006:          bne     LB0FB
  3007:          cmp     zARYTAB
  3008:          beq     bNOTFNS
  3009:  LB0FB:  lda     zVARNAM
  3010:          cmp     (zTEMP_5F),y
  3011:          bne     LB109
  3012:          lda     zVARNAM + 1
  3013:          iny
  3014:          cmp     (zTEMP_5F),y
  3015:          beq     LB185
  3016:          dey
  3017:  LB109:  clc
  3018:          lda     zTEMP_5F
  3019:          adc     #7
  3020:          bcc     LB0F1
  3021:          inx
  3022:          bne     LB0EF
  3023:  bISLETC:cmp     #'A'
  3024:          bcc     LB11C
  3025:          sbc     #'Z' + 1
  3026:          sec
  3027:          sbc     #-('Z' + 1)
  3028:  LB11C:  rts
  3029:  bNOTFNS:pla
  3030:          pha
  3031:          cmp     #$2A            ; ?
  3032:          bne     bNOTEVL
  3033:  LB123:  lda     #<bTI           ; for TI$, store the special pointer
  3034:          ldy     #>bTI           ; so it can be recognized
  3035:          rts
  3036:  bNOTEVL:lda     zVARNAM
  3037:          ldy     zVARNAM + 1
  3038:          cmp     #'T'            ; "T"
  3039:          bne     LB13B
  3040:          cpy     #'I' + $80      ; "I$"
  3041:          beq     LB123
  3042:          cpy     #'I'
  3043:          bne     LB13B
  3044:  LB138:  jmp     bSYNERR
  3045:  LB13B:  cmp     #'S'
  3046:          bne     LB143
  3047:          cpy     #'T'
  3048:          beq     LB138
  3049:  LB143:  lda     zARYTAB
  3050:          ldy     zARYTAB + 1
  3051:          sta     zTEMP_5F
  3052:          sty     zTEMP_5F + 1
  3053:          lda     zSTREND
  3054:          ldy     zSTREND + 1
  3055:          sta     zTEMP_5A
  3056:          sty     zTEMP_5A + 1
  3057:          clc
  3058:          adc     #7
  3059:          bcc     LB159
  3060:          iny
  3061:  LB159:  sta     zTEMP_58
  3062:          sty     zTEMP_58 + 1
  3063:          jsr     bBLTU
  3064:          lda     zTEMP_58
  3065:          ldy     zTEMP_58 + 1
  3066:          iny
  3067:          sta     zARYTAB
  3068:          sty     zARYTAB + 1
  3069:          ldy     #0
  3070:          lda     zVARNAM
  3071:          sta     (zTEMP_5F),y
  3072:          iny
  3073:          lda     zVARNAM + 1
  3074:          sta     (zTEMP_5F),y
  3075:          lda     #0
  3076:          iny
  3077:          sta     (zTEMP_5F),y
  3078:          iny
  3079:          sta     (zTEMP_5F),y
  3080:          iny
  3081:          sta     (zTEMP_5F),y
  3082:          iny
  3083:          sta     (zTEMP_5F),y
  3084:          iny
  3085:          sta     (zTEMP_5F),y
  3086:  LB185:  lda     zTEMP_5F
  3087:          clc
  3088:          adc     #2
  3089:          ldy     zTEMP_5F + 1
  3090:          bcc     LB18F
  3091:          iny
  3092:  LB18F:  sta     zVARPNT
  3093:          sty     zVARPNT + 1
  3094:          rts
  3095:  bARYGET:lda     zCOUNT
  3096:          asl     a
  3097:          adc     #5
  3098:          adc     zTEMP_5F
  3099:          ldy     zTEMP_5F + 1
  3100:          bcc     LB1A0
  3101:          iny
  3102:  LB1A0:  sta     zTEMP_58
  3103:          sty     zTEMP_58 + 1
  3104:          rts
  3105:  
  3106:  bN32768:.byte   $90,$80,$00,$00,$00
  3107:  
  3108:  bFACINX:jsr     bAYINT
  3109:          lda     zFACHO + 2
  3110:          ldy     zFACHO + 3
  3111:          rts
  3112:  bINTIDX:jsr     zCHRGET
  3113:          jsr     bFRMEVL
  3114:  LB1B8:  jsr     LAD8D
  3115:          lda     zFACSGN
  3116:          bmi     LB1CC
  3117:  bAYINT: lda     zFACEXP
  3118:          cmp     #$90
  3119:          bcc     LB1CE
  3120:          lda     #<bN32768
  3121:          ldy     #>bN32768
  3122:          jsr     bFCOMP
  3123:  LB1CC:  bne     bIQERR
  3124:  LB1CE:  jmp     bQINT
  3125:  bISARY: lda     zDIMFLG
  3126:          ora     zINTFLG
  3127:          pha
  3128:          lda     zVALTYP
  3129:          pha
  3130:          ldy     #0
  3131:  LB1DB:  tya
  3132:          pha
  3133:          lda     zVARNAM + 1
  3134:          pha
  3135:          lda     zVARNAM
  3136:          pha
  3137:          jsr     bINTIDX
  3138:          pla
  3139:          sta     zVARNAM
  3140:          pla
  3141:          sta     zVARNAM + 1
  3142:          pla
  3143:          tay
  3144:          tsx
  3145:          lda     lSTACK + 2,x
  3146:          pha
  3147:          lda     lSTACK + 1,x
  3148:          pha
  3149:          lda     zFACHO + 2
  3150:          sta     lSTACK + 2,x
  3151:          lda     zFACHO + 3
  3152:          sta     lSTACK + 1,x
  3153:          iny
  3154:          jsr     zCHRGOT
  3155:          cmp     #','
  3156:          beq     LB1DB
  3157:          sty     zCOUNT
  3158:          jsr     bCHKclose
  3159:          pla
  3160:          sta     zVALTYP
  3161:          pla
  3162:          sta     zINTFLG
  3163:          and     #$7F
  3164:          sta     zDIMFLG
  3165:  bFNDARY:ldx     zARYTAB
  3166:          lda     zARYTAB + 1
  3167:  LB21C:  stx     zTEMP_5F
  3168:          sta     zTEMP_5F + 1
  3169:          cmp     zSTREND + 1
  3170:          bne     LB228
  3171:          cpx     zSTREND
  3172:          beq     bNOTFDD
  3173:  LB228:  ldy     #0
  3174:          lda     (zTEMP_5F),y
  3175:          iny
  3176:          cmp     zVARNAM
  3177:          bne     LB237
  3178:          lda     zVARNAM + 1
  3179:          cmp     (zTEMP_5F),y
  3180:          beq     bRAERR
  3181:  LB237:  iny
  3182:          lda     (zTEMP_5F),y
  3183:          clc
  3184:          adc     zTEMP_5F
  3185:          tax
  3186:          iny
  3187:          lda     (zTEMP_5F),y
  3188:          adc     zTEMP_5F + 1
  3189:          bcc     LB21C
  3190:  bBSERR: ldx     #ErrBadSubscript
  3191:          .byte   ASM_BIT3
  3192:  bIQERR: ldx     #ErrIllegalQuantity
  3193:  LB24A:  jmp     bERROR
  3194:  bRAERR: ldx     #ErrRedimdArray
  3195:          lda     zDIMFLG
  3196:          bne     LB24A
  3197:          jsr     bARYGET
  3198:          lda     zCOUNT
  3199:          ldy     #4
  3200:          cmp     (zTEMP_5F),y
  3201:          bne     bBSERR
  3202:          jmp     LB2EA
  3203:  bNOTFDD:jsr     bARYGET
  3204:          jsr     bREASON
  3205:          ldy     #0
  3206:          sty     zFBUFPT + 1
  3207:          ldx     #5
  3208:          lda     zVARNAM
  3209:          sta     (zTEMP_5F),y
  3210:          bpl     LB274
  3211:          dex
  3212:  LB274:  iny
  3213:          lda     zVARNAM + 1
  3214:          sta     (zTEMP_5F),y
  3215:          bpl     LB27D
  3216:          dex
  3217:          dex
  3218:  LB27D:  stx     zFBUFPT
  3219:          lda     zCOUNT
  3220:          iny
  3221:          iny
  3222:          iny
  3223:          sta     (zTEMP_5F),y
  3224:  LB286:  ldx     #11
  3225:          lda     #0
  3226:          bit     zDIMFLG
  3227:          bvc     LB296
  3228:          pla
  3229:          clc
  3230:          adc     #1
  3231:          tax
  3232:          pla
  3233:          adc     #0
  3234:  LB296:  iny
  3235:          sta     (zTEMP_5F),y
  3236:          iny
  3237:          txa
  3238:          sta     (zTEMP_5F),y
  3239:          jsr     bUMULT
  3240:          stx     zFBUFPT
  3241:          sta     zFBUFPT + 1
  3242:          ldy     zINDEX
  3243:          dec     zCOUNT
  3244:          bne     LB286
  3245:          adc     zTEMP_58 + 1
  3246:          bcs     LB30B
  3247:          sta     zTEMP_58 + 1
  3248:          tay
  3249:          txa
  3250:          adc     zTEMP_58
  3251:          bcc     LB2B9
  3252:          iny
  3253:          beq     LB30B
  3254:  LB2B9:  jsr     bREASON
  3255:          sta     zSTREND
  3256:          sty     zSTREND + 1
  3257:          lda     #0
  3258:          inc     zFBUFPT + 1
  3259:          ldy     zFBUFPT
  3260:          beq     LB2CD
  3261:  LB2C8:  dey
  3262:          sta     (zTEMP_58),y
  3263:          bne     LB2C8
  3264:  LB2CD:  dec     zTEMP_58 + 1
  3265:          dec     zFBUFPT + 1
  3266:          bne     LB2C8
  3267:          inc     zTEMP_58 + 1
  3268:          sec
  3269:          lda     zSTREND
  3270:          sbc     zTEMP_5F
  3271:          ldy     #2
  3272:          sta     (zTEMP_5F),y
  3273:          lda     zSTREND + 1
  3274:          iny
  3275:          sbc     zTEMP_5F + 1
  3276:          sta     (zTEMP_5F),y
  3277:          lda     zDIMFLG
  3278:          bne     LB34B
  3279:          iny
  3280:  LB2EA:  lda     (zTEMP_5F),y
  3281:          sta     zCOUNT
  3282:          lda     #0
  3283:          sta     zFBUFPT
  3284:  LB2F2:  sta     zFBUFPT + 1
  3285:          iny
  3286:          pla
  3287:          tax
  3288:          sta     zFACHO + 2
  3289:          pla
  3290:          sta     zFACHO + 3
  3291:          cmp     (zTEMP_5F),y
  3292:          bcc     bINLPN2
  3293:          bne     LB308
  3294:          iny
  3295:          txa
  3296:          cmp     (zTEMP_5F),y
  3297:          bcc     LB30F
  3298:  LB308:  jmp     bBSERR
  3299:  LB30B:  jmp     bOMERR
  3300:  
  3301:  bINLPN2:iny
  3302:  LB30F:  lda     zFBUFPT + 1
  3303:          ora     zFBUFPT
  3304:          clc
  3305:          beq     LB320
  3306:          jsr     bUMULT
  3307:          txa
  3308:          adc     zFACHO + 2
  3309:          tax
  3310:          tya
  3311:          ldy     zINDEX
  3312:  LB320:  adc     zFACHO + 3
  3313:          stx     zFBUFPT
  3314:          dec     zCOUNT
  3315:          bne     LB2F2
  3316:          sta     zFBUFPT + 1
  3317:          ldx     #5
  3318:          lda     zVARNAM
  3319:          bpl     LB331
  3320:          dex
  3321:  LB331:  lda     zVARNAM + 1
  3322:          bpl     LB337
  3323:          dex
  3324:          dex
  3325:  LB337:  stx     zTEMP_28
  3326:          lda     #0
  3327:          jsr     LB355
  3328:          txa
  3329:          adc     zTEMP_58
  3330:          sta     zVARPNT
  3331:          tya
  3332:          adc     zTEMP_58 + 1
  3333:          sta     zVARPNT + 1
  3334:          tay
  3335:          lda     zVARPNT
  3336:  LB34B:  rts
  3337:  bUMULT: sty     zINDEX
  3338:          lda     (zTEMP_5F),y
  3339:          sta     zTEMP_28
  3340:          dey
  3341:          lda     (zTEMP_5F),y
  3342:  LB355:  sta     zTEMP_28 + 1
  3343:          lda     #$10
  3344:          sta     zTEMP_5D
  3345:          ldx     #0
  3346:          ldy     #0
  3347:  LB35F:  txa
  3348:          asl     a
  3349:          tax
  3350:          tya
  3351:          rol     a
  3352:          tay
  3353:          bcs     LB30B
  3354:          asl     zFBUFPT
  3355:          rol     zFBUFPT + 1
  3356:          bcc     LB378
  3357:          clc
  3358:          txa
  3359:          adc     zTEMP_28
  3360:          tax
  3361:          tya
  3362:          adc     zTEMP_28 + 1
  3363:          tay
  3364:          bcs     LB30B
  3365:  LB378:  dec     zTEMP_5D
  3366:          bne     LB35F
  3367:          rts
  3368:  bFRE:   lda     zVALTYP
  3369:          beq     LB384
  3370:          jsr     LB6A6
  3371:  LB384:  jsr     bGARBAG
  3372:          sec
  3373:          lda     zFRETOP
  3374:          sbc     zSTREND
  3375:          tay
  3376:          lda     zFRETOP + 1
  3377:          sbc     zSTREND + 1
  3378:  bGIVAYF:ldx     #0
  3379:          stx     zVALTYP
  3380:          sta     zFACHO
  3381:          sty     zFACHO + 1
  3382:          ldx     #$90
  3383:          jmp     LBC44
  3384:  bPOS:   sec
  3385:          jsr     kPLOT
  3386:  LB3A2:  lda     #0
  3387:          beq     bGIVAYF
  3388:  bERRDIR:ldx     zCURLIN + 1
  3389:          inx
  3390:          bne     LB34B
  3391:          ldx     #ErrIllegalDirect
  3392:          .byte   ASM_BIT3
  3393:  bUFERR: ldx     #ErrUndefdFunction
  3394:          jmp     bERROR
  3395:  
  3396:  bDEF:   jsr     bGETFNM
  3397:          jsr     bERRDIR
  3398:          jsr     bCHKopen
  3399:          lda     #$80
  3400:          sta     zINTALLOWED
  3401:          jsr     bPTRGET
  3402:          jsr     LAD8D
  3403:          jsr     bCHKclose
  3404:          lda     #TokEqual
  3405:          jsr     LAEFF
  3406:          pha
  3407:          lda     zVARPNT + 1
  3408:          pha
  3409:          lda     zVARPNT
  3410:          pha
  3411:          lda     zTXTPTR + 1
  3412:          pha
  3413:          lda     zTXTPTR
  3414:          pha
  3415:          jsr     bDATA
  3416:          jmp     LB44F
  3417:  bGETFNM:lda     #TokFn
  3418:          jsr     LAEFF
  3419:          ora     #$80
  3420:          sta     zINTALLOWED
  3421:          jsr     LB092
  3422:          sta     zTEMPF3
  3423:          sty     zTEMPF3 + 1
  3424:          jmp     LAD8D
  3425:  bFNDOER:jsr     bGETFNM
  3426:          lda     zTEMPF3 + 1
  3427:          pha
  3428:          lda     zTEMPF3
  3429:          pha
  3430:          jsr     bOARCHK
  3431:          jsr     LAD8D
  3432:          pla
  3433:          sta     zTEMPF3
  3434:          pla
  3435:          sta     zTEMPF3 + 1
  3436:          ldy     #2
  3437:          lda     (zTEMPF3),y
  3438:          sta     zVARPNT
  3439:          tax
  3440:          iny
  3441:          lda     (zTEMPF3),y
  3442:          beq     bUFERR
  3443:          sta     zVARPNT + 1
  3444:          iny
  3445:  LB418:  lda     (zVARPNT),y
  3446:          pha
  3447:          dey
  3448:          bpl     LB418
  3449:          ldy     zVARPNT + 1
  3450:          jsr     LBBD4
  3451:          lda     zTXTPTR + 1
  3452:          pha
  3453:          lda     zTXTPTR
  3454:          pha
  3455:          lda     (zTEMPF3),y
  3456:          sta     zTXTPTR
  3457:          iny
  3458:          lda     (zTEMPF3),y
  3459:          sta     zTXTPTR + 1
  3460:          lda     zVARPNT + 1
  3461:          pha
  3462:          lda     zVARPNT
  3463:          pha
  3464:          jsr     bFRMNUM
  3465:          pla
  3466:          sta     zTEMPF3
  3467:          pla
  3468:          sta     zTEMPF3 + 1
  3469:          jsr     zCHRGOT
  3470:          beq     LB449
  3471:          jmp     bSYNERR
  3472:  LB449:  pla
  3473:          sta     zTXTPTR
  3474:          pla
  3475:          sta     zTXTPTR + 1
  3476:  LB44F:  ldy     #0
  3477:          pla
  3478:          sta     (zTEMPF3),y
  3479:          pla
  3480:          iny
  3481:          sta     (zTEMPF3),y
  3482:          pla
  3483:          iny
  3484:          sta     (zTEMPF3),y
  3485:          pla
  3486:          iny
  3487:          sta     (zTEMPF3),y
  3488:          pla
  3489:          iny
  3490:          sta     (zTEMPF3),y
  3491:          rts
  3492:  bSTRD:  jsr     LAD8D
  3493:          ldy     #0
  3494:          jsr     LBDDF
  3495:          pla
  3496:          pla
  3497:  LB46F:  lda     #<(zASCWRK)
  3498:          ldy     #>(zASCWRK)
  3499:          beq     bSTRLIT
  3500:          ; -------------
  3501:  
  3502:  LB475:  ldx     zFACHO + 2
  3503:          ldy     zFACHO + 3
  3504:          stx     zTEMP_50
  3505:          sty     zTEMP_50 + 1
  3506:  LB47D:  jsr     bGETSPA
  3507:          stx     zFACHO
  3508:          sty     zFACHO + 1
  3509:          sta     zFACEXP
  3510:          rts
  3511:  bSTRLIT:ldx     #'"'
  3512:          stx     zCHARAC
  3513:          stx     zENDCHR
  3514:  LB48D:  sta     zARISGN
  3515:          sty     zFACOV
  3516:          sta     zFACHO
  3517:          sty     zFACHO + 1
  3518:          ldy     #-1
  3519:  LB497:  iny
  3520:          lda     (zARISGN),y
  3521:          beq     LB4A8
  3522:          cmp     zCHARAC
  3523:          beq     LB4A4
  3524:          cmp     zENDCHR
  3525:          bne     LB497
  3526:  LB4A4:  cmp     #'"'
  3527:          beq     LB4A9
  3528:  LB4A8:  clc
  3529:  LB4A9:  sty     zFACEXP
  3530:          tya
  3531:          adc     zARISGN
  3532:          sta     zFBUFPT
  3533:          ldx     zFACOV
  3534:          bcc     LB4B5
  3535:          inx
  3536:  LB4B5:  stx     zFBUFPT + 1
  3537:          lda     zFACOV
  3538:          beq     LB4BF
  3539:          cmp     #2
  3540:          bne     LB4CA
  3541:  LB4BF:  tya
  3542:          jsr     LB475
  3543:          ldx     zARISGN
  3544:          ldy     zFACOV
  3545:  JDLB4C7:
  3546:          jsr     LB688
  3547:  LB4CA:  ldx     zTEMPPT
  3548:          cpx     #zTEMPST + 9
  3549:          bne     bPUTNW1
  3550:          ldx     #ErrFormulaTooComplex
  3551:  LB4D2:  jmp     bERROR
  3552:  bPUTNW1:lda     zFACEXP
  3553:          sta     0,x
  3554:          lda     zFACHO
  3555:          sta     1,x
  3556:          lda     zFACHO + 1
  3557:          sta     2,x
  3558:          ldy     #>zTEMPST
  3559:          stx     zFACHO + 2
  3560:          sty     zFACHO + 3
  3561:          sty     zFACOV
  3562:          dey
  3563:          sty     zVALTYP
  3564:          stx     zLASTPT
  3565:          inx
  3566:          inx
  3567:          inx
  3568:          stx     zTEMPPT
  3569:          rts
  3570:  bGETSPA:lsr     zGARBFL
  3571:  LB4F6:  pha
  3572:          eor     #$FF
  3573:          sec
  3574:          adc     zFRETOP
  3575:          ldy     zFRETOP + 1
  3576:          bcs     LB501
  3577:          dey
  3578:  LB501:  cpy     zSTREND + 1
  3579:          bcc     LB516
  3580:          bne     LB50B
  3581:          cmp     zSTREND
  3582:          bcc     LB516
  3583:  LB50B:  sta     zFRETOP
  3584:          sty     zFRETOP + 1
  3585:          sta     zFRESPC
  3586:          sty     zFRESPC + 1
  3587:          tax
  3588:          pla
  3589:          rts
  3590:  LB516:  ldx     #$10
  3591:          lda     zGARBFL
  3592:          bmi     LB4D2
  3593:          jsr     bGARBAG
  3594:          lda     #$80
  3595:          sta     zGARBFL
  3596:          pla
  3597:          bne     LB4F6
  3598:  bGARBAG:ldx     zMEMSIZ
  3599:          lda     zMEMSIZ + 1
  3600:  LB52A:  stx     zFRETOP
  3601:          sta     zFRETOP + 1
  3602:          ldy     #0
  3603:          sty     zTEMPF3 + 1
  3604:          sty     zTEMPF3
  3605:          lda     zSTREND
  3606:          ldx     zSTREND + 1
  3607:          sta     zTEMP_5F
  3608:          stx     zTEMP_5F + 1
  3609:          lda     #<zTEMPST
  3610:          ldx     #>zTEMPST
  3611:          sta     zINDEX
  3612:          stx     zINDEX + 1
  3613:  LB544:  cmp     zTEMPPT
  3614:          beq     LB54D
  3615:          jsr     LB5C7
  3616:          beq     LB544
  3617:  LB54D:  lda     #$07
  3618:          sta     zFOUR6
  3619:          lda     zVARTAB
  3620:          ldx     zVARTAB + 1
  3621:          sta     zINDEX
  3622:          stx     zINDEX + 1
  3623:  LB559:  cpx     zARYTAB + 1
  3624:          bne     LB561
  3625:          cmp     zARYTAB
  3626:          beq     LB566
  3627:  LB561:  jsr     bDVARS
  3628:          beq     LB559
  3629:  LB566:  sta     zTEMP_58
  3630:          stx     zTEMP_58 + 1
  3631:          lda     #3
  3632:          sta     zFOUR6
  3633:  LB56E:  lda     zTEMP_58
  3634:          ldx     zTEMP_58 + 1
  3635:  LB572:  cpx     zSTREND + 1
  3636:          bne     LB57D
  3637:          cmp     zSTREND
  3638:          bne     LB57D
  3639:          jmp     bGRBPAS
  3640:  LB57D:  sta     zINDEX
  3641:          stx     zINDEX + 1
  3642:          ldy     #0
  3643:          lda     (zINDEX),y
  3644:          tax
  3645:          iny
  3646:          lda     (zINDEX),y
  3647:          php
  3648:          iny
  3649:          lda     (zINDEX),y
  3650:          adc     zTEMP_58
  3651:          sta     zTEMP_58
  3652:          iny
  3653:          lda     (zINDEX),y
  3654:          adc     zTEMP_58 + 1
  3655:          sta     zTEMP_58 + 1
  3656:          plp
  3657:          bpl     LB56E
  3658:          txa
  3659:          bmi     LB56E
  3660:          iny
  3661:          lda     (zINDEX),y
  3662:          ldy     #0
  3663:          asl     a
  3664:          adc     #5
  3665:          adc     zINDEX
  3666:          sta     zINDEX
  3667:          bcc     LB5AE
  3668:          inc     zINDEX + 1
  3669:  LB5AE:  ldx     zINDEX + 1
  3670:  LB5B0:  cpx     zTEMP_58 + 1
  3671:          bne     LB5B8
  3672:          cmp     zTEMP_58
  3673:          beq     LB572
  3674:  LB5B8:  jsr     LB5C7
  3675:          beq     LB5B0
  3676:  bDVARS: lda     (zINDEX),y
  3677:          bmi     LB5F6
  3678:          iny
  3679:          lda     (zINDEX),y
  3680:          bpl     LB5F6
  3681:          iny
  3682:  LB5C7:  lda     (zINDEX),y
  3683:          beq     LB5F6
  3684:          iny
  3685:          lda     (zINDEX),y
  3686:          tax
  3687:          iny
  3688:          lda     (zINDEX),y
  3689:          cmp     zFRETOP + 1
  3690:          bcc     LB5DC
  3691:          bne     LB5F6
  3692:          cpx     zFRETOP
  3693:          bcs     LB5F6
  3694:  LB5DC:  cmp     zTEMP_5F + 1
  3695:          bcc     LB5F6
  3696:          bne     LB5E6
  3697:          cpx     zTEMP_5F
  3698:          bcc     LB5F6
  3699:  LB5E6:  stx     zTEMP_5F
  3700:          sta     zTEMP_5F + 1
  3701:          lda     zINDEX
  3702:          ldx     zINDEX + 1
  3703:          sta     zTEMPF3
  3704:          stx     zTEMPF3 + 1
  3705:          lda     zFOUR6
  3706:          sta     zJMPER + 1
  3707:  LB5F6:  lda     zFOUR6
  3708:          clc
  3709:          adc     zINDEX
  3710:          sta     zINDEX
  3711:          bcc     LB601
  3712:          inc     zINDEX + 1
  3713:  LB601:  ldx     zINDEX + 1
  3714:          ldy     #0
  3715:          rts
  3716:  bGRBPAS:lda     zTEMPF3 + 1
  3717:          ora     zTEMPF3
  3718:          beq     LB601
  3719:          lda     zJMPER + 1
  3720:          and     #$04
  3721:          lsr     a
  3722:          tay
  3723:          sta     zJMPER + 1
  3724:          lda     (zTEMPF3),y
  3725:          adc     zTEMP_5F
  3726:          sta     zTEMP_5A
  3727:          lda     zTEMP_5F + 1
  3728:          adc     #0
  3729:          sta     zTEMP_5A + 1
  3730:          lda     zFRETOP
  3731:          ldx     zFRETOP + 1
  3732:          sta     zTEMP_58
  3733:          stx     zTEMP_58 + 1
  3734:          jsr     MoveMem
  3735:          ldy     zJMPER + 1
  3736:          iny
  3737:          lda     zTEMP_58
  3738:          sta     (zTEMPF3),y
  3739:          tax
  3740:          inc     zTEMP_58 + 1
  3741:          lda     zTEMP_58 + 1
  3742:          iny
  3743:          sta     (zTEMPF3),y
  3744:          jmp     LB52A
  3745:  bCAT:   lda     zFACHO + 3
  3746:          pha
  3747:          lda     zFACHO + 2
  3748:          pha
  3749:          jsr     bEVAL
  3750:          jsr     LAD8F
  3751:          pla
  3752:          sta     zARISGN
  3753:          pla
  3754:          sta     zFACOV
  3755:          ldy     #0
  3756:          lda     (zARISGN),y
  3757:          clc
  3758:          adc     (zFACHO + 2),y
  3759:          bcc     LB65D
  3760:          ldx     #ErrStringTooLong
  3761:          jmp     bERROR
  3762:  LB65D:  jsr     LB475
  3763:          jsr     bMOVINS
  3764:          lda     zTEMP_50
  3765:          ldy     zTEMP_50 + 1
  3766:          jsr     LB6AA
  3767:          jsr     LB68C
  3768:          lda     zARISGN
  3769:          ldy     zFACOV
  3770:          jsr     LB6AA
  3771:          jsr     LB4CA
  3772:          jmp     LADB8
  3773:  bMOVINS:ldy     #0
  3774:          lda     (zARISGN),y
  3775:          pha
  3776:          iny
  3777:          lda     (zARISGN),y
  3778:          tax
  3779:          iny
  3780:          lda     (zARISGN),y
  3781:          tay
  3782:          pla
  3783:  LB688:  stx     zINDEX
  3784:          sty     zINDEX + 1
  3785:  LB68C:  tay
  3786:          beq     LB699
  3787:          pha
  3788:  LB690:  dey
  3789:          lda     (zINDEX),y
  3790:          sta     (zFRESPC),y
  3791:          tya
  3792:          bne     LB690
  3793:          pla
  3794:  LB699:  clc
  3795:          adc     zFRESPC
  3796:          sta     zFRESPC
  3797:          bcc     LB6A2
  3798:          inc     zFRESPC + 1
  3799:  LB6A2:  rts
  3800:  bFRESTR:jsr     LAD8F
  3801:  LB6A6:  lda     zFACHO + 2
  3802:          ldy     zFACHO + 3
  3803:  LB6AA:  sta     zINDEX
  3804:          sty     zINDEX + 1
  3805:          jsr     bFREFAC
  3806:          php
  3807:          ldy     #0
  3808:          lda     (zINDEX),y
  3809:          pha
  3810:          iny
  3811:          lda     (zINDEX),y
  3812:          tax
  3813:          iny
  3814:          lda     (zINDEX),y
  3815:          tay
  3816:          pla
  3817:          plp
  3818:          bne     LB6D6
  3819:          cpy     zFRETOP + 1
  3820:          bne     LB6D6
  3821:          cpx     zFRETOP
  3822:          bne     LB6D6
  3823:          pha
  3824:          clc
  3825:          adc     zFRETOP
  3826:          sta     zFRETOP
  3827:          bcc     LB6D5
  3828:          inc     zFRETOP + 1
  3829:  LB6D5:  pla
  3830:  LB6D6:  stx     zINDEX
  3831:          sty     zINDEX + 1
  3832:          rts
  3833:  bFREFAC:cpy     zLASTPT + 1
  3834:          bne     LB6EB
  3835:          cmp     zLASTPT
  3836:          bne     LB6EB
  3837:          sta     zTEMPPT
  3838:          sbc     #3
  3839:          sta     zLASTPT
  3840:          ldy     #0
  3841:  LB6EB:  rts
  3842:  bCHRD:  jsr     LB7A1
  3843:          txa
  3844:          pha
  3845:          lda     #1
  3846:          jsr     LB47D
  3847:          pla
  3848:          ldy     #0
  3849:          sta     (zFACHO),y
  3850:          pla
  3851:          pla
  3852:          jmp     LB4CA
  3853:  bLEFTD: jsr     bPREAM
  3854:          cmp     (zTEMP_50),y
  3855:          tya
  3856:  LB706:  bcc     LB70C
  3857:          lda     (zTEMP_50),y
  3858:          tax
  3859:          tya
  3860:  LB70C:  pha
  3861:  LB70D:  txa
  3862:  LB70E:  pha
  3863:          jsr     LB47D
  3864:          lda     zTEMP_50
  3865:          ldy     zTEMP_50 + 1
  3866:          jsr     LB6AA
  3867:          pla
  3868:          tay
  3869:          pla
  3870:          clc
  3871:          adc     zINDEX
  3872:          sta     zINDEX
  3873:          bcc     LB725
  3874:          inc     zINDEX + 1
  3875:  LB725:  tya
  3876:          jsr     LB68C
  3877:          jmp     LB4CA
  3878:  bRIGHTD:jsr     bPREAM
  3879:          clc
  3880:          sbc     (zTEMP_50),y
  3881:          eor     #$FF
  3882:          jmp     LB706
  3883:  bMIDD:  lda     #$FF
  3884:          sta     zFACHO + 3
  3885:          jsr     zCHRGOT
  3886:          cmp     #')'
  3887:          beq     LB748
  3888:          jsr     bCHKCMA
  3889:          jsr     LB79E
  3890:  LB748:  jsr     bPREAM
  3891:          beq     LB798
  3892:          dex
  3893:          txa
  3894:          pha
  3895:          clc
  3896:          ldx     #0
  3897:          sbc     (zTEMP_50),y
  3898:          bcs     LB70D
  3899:          eor     #$FF
  3900:          cmp     zFACHO + 3
  3901:          bcc     LB70E
  3902:          lda     zFACHO + 3
  3903:          bcs     LB70E
  3904:  bPREAM: jsr     bCHKclose
  3905:          pla
  3906:          tay
  3907:          pla
  3908:          sta     zJMPER + 1
  3909:          pla
  3910:          pla
  3911:          pla
  3912:          tax
  3913:          pla
  3914:          sta     zTEMP_50
  3915:          pla
  3916:          sta     zTEMP_50 + 1
  3917:          lda     zJMPER + 1
  3918:          pha
  3919:          tya
  3920:          pha
  3921:          ldy     #0
  3922:          txa
  3923:          rts
  3924:  bLEN:   jsr     bLEN1
  3925:          jmp     LB3A2
  3926:  bLEN1:  jsr     bFRESTR
  3927:          ldx     #0
  3928:          stx     zVALTYP
  3929:          tay
  3930:          rts
  3931:  bASC:   jsr     bLEN1
  3932:          beq     LB798
  3933:          ldy     #0
  3934:          lda     (zINDEX),y
  3935:          tay
  3936:          jmp     LB3A2
  3937:  LB798:  jmp     bIQERR
  3938:  bGTBYTC:jsr     zCHRGET
  3939:  LB79E:  jsr     bFRMNUM
  3940:  LB7A1:  jsr     LB1B8
  3941:          ldx     zFACHO + 2
  3942:          bne     LB798
  3943:          ldx     zFACHO + 3
  3944:          jmp     zCHRGOT
  3945:  bVAL:   jsr     bLEN1
  3946:          bne     bSTRVAL
  3947:          jmp     LB8F7
  3948:  bSTRVAL:ldx     zTXTPTR
  3949:          ldy     zTXTPTR + 1
  3950:          stx     zFBUFPT
  3951:          sty     zFBUFPT + 1
  3952:          ldx     zINDEX
  3953:          stx     zTXTPTR
  3954:          clc
  3955:          adc     zINDEX
  3956:          sta     zINDEX2
  3957:          ldx     zINDEX + 1
  3958:          stx     zTXTPTR + 1
  3959:          bcc     LB7CD
  3960:          inx
  3961:  LB7CD:  stx     zINDEX2 + 1
  3962:          ldy     #0
  3963:          lda     (zINDEX2),y
  3964:          pha
  3965:          tya
  3966:          sta     (zINDEX2),y
  3967:          jsr     zCHRGOT
  3968:          jsr     bFIN
  3969:          pla
  3970:          ldy     #0
  3971:          sta     (zINDEX2),y
  3972:  LB7E2:  ldx     zFBUFPT
  3973:          ldy     zFBUFPT + 1
  3974:          stx     zTXTPTR
  3975:          sty     zTXTPTR + 1
  3976:          rts
  3977:  bGETNUM:jsr     bFRMNUM
  3978:          jsr     bGETADR
  3979:  LB7F1:  jsr     bCHKCMA
  3980:          jmp     LB79E
  3981:  bGETADR:lda     zFACSGN
  3982:          bmi     LB798
  3983:          lda     zFACEXP
  3984:          cmp     #$91            ; exponent for 65536
  3985:          bcs     LB798
  3986:          jsr     bQINT
  3987:          lda     zFACHO + 2
  3988:          ldy     zFACHO + 3
  3989:          sty     zLINNUM
  3990:          sta     zLINNUM + 1
  3991:          rts
  3992:  bPEEK:  lda     zLINNUM + 1
  3993:          pha
  3994:          lda     zLINNUM
  3995:          pha
  3996:          jsr     bGETADR
  3997:          ldy     #0
  3998:          lda     (zLINNUM),y
  3999:          tay
  4000:          pla
  4001:          sta     zLINNUM
  4002:          pla
  4003:          sta     zLINNUM + 1
  4004:          jmp     LB3A2
  4005:  bPOKE:  jsr     bGETNUM
  4006:          txa
  4007:          ldy     #0
  4008:          sta     (zLINNUM),y
  4009:          rts
  4010:  bWAIT:  jsr     bGETNUM
  4011:          stx     zFORPNT
  4012:          ldx     #0
  4013:          jsr     zCHRGOT
  4014:          beq     LB83C
  4015:          jsr     LB7F1
  4016:  LB83C:  stx     zFORPNT + 1
  4017:          ldy     #0
  4018:  LB840:  lda     (zLINNUM),y
  4019:          eor     zFORPNT + 1
  4020:          and     zFORPNT
  4021:          beq     LB840
  4022:  LB848:  rts
  4023:  bFADDH: lda     #<bFHALF
  4024:          ldy     #>bFHALF
  4025:          jmp     bFADD
  4026:  bFSUB:  jsr     bCONUPK
  4027:  FSUBT:  lda     zFACSGN
  4028:          eor     #$FF
  4029:          sta     zFACSGN
  4030:          eor     zARGSGN
  4031:          sta     zARISGN
  4032:          lda     zFACEXP
  4033:          jmp     FADDT
  4034:  bFADD5: jsr     LB999
  4035:          bcc     LB8A3
  4036:  bFADD:  jsr     bCONUPK
  4037:  FADDT:  bne     LB86F
  4038:          jmp     bMOVFA
  4039:  LB86F:  ldx     zFACOV
  4040:          stx     zJMPER + 2
  4041:          ldx     #zARGEXP
  4042:          lda     zARGEXP
  4043:  LB877:  tay
  4044:          beq     LB848
  4045:          sec
  4046:          sbc     zFACEXP
  4047:          beq     LB8A3
  4048:          bcc     LB893
  4049:          sty     zFACEXP
  4050:          ldy     zARGSGN
  4051:          sty     zFACSGN
  4052:          eor     #$FF
  4053:          adc     #0
  4054:          ldy     #0
  4055:          sty     zJMPER + 2
  4056:          ldx     #zFACEXP
  4057:          bne     LB897
  4058:  LB893:  ldy     #0
  4059:          sty     zFACOV
  4060:  LB897:  cmp     #$F9
  4061:          bmi     bFADD5
  4062:          tay
  4063:          lda     zFACOV
  4064:          lsr     1,x
  4065:          jsr     LB9B0
  4066:  LB8A3:  bit     zARISGN
  4067:          bpl     LB8FE
  4068:          ldy     #zFACEXP
  4069:          cpx     #zARGEXP
  4070:          beq     LB8AF
  4071:          ldy     #zARGEXP
  4072:  LB8AF:  sec
  4073:          eor     #$FF
  4074:          adc     zJMPER + 2
  4075:          sta     zFACOV
  4076:          lda     4,y
  4077:          sbc     4,x
  4078:          sta     zFACHO + 3
  4079:          lda     zADRAY1,y
  4080:          sbc     zADRAY1,x
  4081:          sta     zFACHO + 2
  4082:          lda     2,y
  4083:          sbc     2,x
  4084:          sta     zFACHO + 1
  4085:          lda     1,y
  4086:          sbc     1,x
  4087:          sta     zFACHO
  4088:  LB8D2:  bcs     LB8D7
  4089:          jsr     bNEGFAC
  4090:  LB8D7:  ldy     #0
  4091:          tya
  4092:          clc
  4093:  LB8DB:  ldx     zFACHO
  4094:          bne     LB929
  4095:          ldx     zFACHO + 1
  4096:          stx     zFACHO
  4097:          ldx     zFACHO + 2
  4098:          stx     zFACHO + 1
  4099:          ldx     zFACHO + 3
  4100:          stx     zFACHO + 2
  4101:          ldx     zFACOV
  4102:          stx     zFACHO + 3
  4103:          sty     zFACOV
  4104:          adc     #8
  4105:          cmp     #$20
  4106:          bne     LB8DB
  4107:  LB8F7:  lda     #0
  4108:  LB8F9:  sta     zFACEXP
  4109:  LB8FB:  sta     zFACSGN
  4110:          rts
  4111:  LB8FE:  adc     zJMPER + 2
  4112:          sta     zFACOV
  4113:          lda     zFACHO + 3
  4114:          adc     zARGHO + 3
  4115:          sta     zFACHO + 3
  4116:          lda     zFACHO + 2
  4117:          adc     zARGHO + 2
  4118:          sta     zFACHO + 2
  4119:          lda     zFACHO + 1
  4120:          adc     zARGHO + 1
  4121:          sta     zFACHO + 1
  4122:          lda     zFACHO
  4123:          adc     zARGHO
  4124:          sta     zFACHO
  4125:          jmp     LB936
  4126:  LB91D:  adc     #1
  4127:          asl     zFACOV
  4128:          rol     zFACHO + 3
  4129:          rol     zFACHO + 2
  4130:          rol     zFACHO + 1
  4131:          rol     zFACHO
  4132:  LB929:  bpl     LB91D
  4133:          sec
  4134:          sbc     zFACEXP
  4135:          bcs     LB8F7
  4136:          eor     #$FF
  4137:          adc     #1
  4138:          sta     zFACEXP
  4139:  LB936:  bcc     LB946
  4140:  LB938:  inc     zFACEXP
  4141:          beq     bOVERR
  4142:          ror     zFACHO
  4143:          ror     zFACHO + 1
  4144:          ror     zFACHO + 2
  4145:          ror     zFACHO + 3
  4146:          ror     zFACOV
  4147:  LB946:  rts
  4148:  bNEGFAC:lda     zFACSGN
  4149:          eor     #$FF
  4150:          sta     zFACSGN
  4151:  LB94D:  lda     zFACHO
  4152:          eor     #$FF
  4153:          sta     zFACHO
  4154:          lda     zFACHO + 1
  4155:          eor     #$FF
  4156:          sta     zFACHO + 1
  4157:          lda     zFACHO + 2
  4158:          eor     #$FF
  4159:          sta     zFACHO + 2
  4160:          lda     zFACHO + 3
  4161:          eor     #$FF
  4162:          sta     zFACHO + 3
  4163:          lda     zFACOV
  4164:          eor     #$FF
  4165:          sta     zFACOV
  4166:          inc     zFACOV
  4167:          bne     LB97D
  4168:  LB96F:  inc     zFACHO + 3
  4169:          bne     LB97D
  4170:          inc     zFACHO + 2
  4171:          bne     LB97D
  4172:          inc     zFACHO + 1
  4173:          bne     LB97D
  4174:          inc     zFACHO
  4175:  LB97D:  rts
  4176:  bOVERR: ldx     #ErrOverflow
  4177:          jmp     bERROR
  4178:  bMULSHF:ldx     #zRESHO - 1
  4179:  LB985:  ldy     4,x
  4180:          sty     zFACOV
  4181:          ldy     3,x
  4182:          sty     4,x
  4183:          ldy     2,x
  4184:          sty     3,x
  4185:          ldy     1,x
  4186:          sty     2,x
  4187:          ldy     zBITS
  4188:          sty     1,x
  4189:  LB999:  adc     #8
  4190:          bmi     LB985
  4191:          beq     LB985
  4192:          sbc     #8
  4193:          tay
  4194:          lda     zFACOV
  4195:          bcs     LB9BA
  4196:  LB9A6:  asl     1,x
  4197:          bcc     LB9AC
  4198:          inc     1,x
  4199:  LB9AC:  ror     1,x
  4200:          ror     1,x
  4201:  LB9B0:  ror     2,x
  4202:          ror     3,x
  4203:          ror     4,x
  4204:          ror     a
  4205:          iny
  4206:          bne     LB9A6
  4207:  LB9BA:  clc
  4208:          rts
  4209:  
  4210:  bFPTABL:.byte   $81,$00,$00,$00,$00 ; FP 1
  4211:  LB9C1:  .byte   $03                 ; Grade of polynomial
  4212:          .byte   $7F,$5E,$56,$CB,$79 ; .434255942
  4213:          .byte   $80,$13,$9B,$0B,$64 ; .576584541
  4214:          .byte   $80,$76,$38,$93,$16 ; .961800759
  4215:          .byte   $82,$38,$AA,$3B,$20 ; 2.88539007
  4216:  LB9D6:  .byte   $80,$35,$04,$F3,$34 ; 1 / SQR(2)
  4217:  LB9DB:  .byte   $81,$35,$04,$F3,$34 ; SQR(2)
  4218:  LB9E0:  .byte   $80,$80,$00,$00,$00 ; - 0.5
  4219:  LB9E5:  .byte   $80,$31,$72,$17,$F8 ; LOG(2)
  4220:  
  4221:  bLOG:   jsr     bSIGN
  4222:          beq     LB9F1
  4223:          bpl     LB9F4
  4224:  LB9F1:  jmp     bIQERR
  4225:  LB9F4:  lda     zFACEXP
  4226:          sbc     #$7F
  4227:          pha
  4228:          lda     #$80
  4229:          sta     zFACEXP
  4230:          lda     #<LB9D6
  4231:          ldy     #>LB9D6
  4232:          jsr     bFADD
  4233:          lda     #<LB9DB
  4234:          ldy     #>LB9DB
  4235:          jsr     bFDIVT
  4236:          lda     #<bFPTABL
  4237:          ldy     #>bFPTABL
  4238:          jsr     bFSUB
  4239:          lda     #<LB9C1
  4240:          ldy     #>LB9C1
  4241:          jsr     bPOLYX
  4242:          lda     #<LB9E0
  4243:          ldy     #>LB9E0
  4244:          jsr     bFADD
  4245:          pla
  4246:          jsr     LBD7E
  4247:          lda     #<LB9E5
  4248:          ldy     #>LB9E5
  4249:  bFMULT: jsr     bCONUPK
  4250:  FMULTT: bne     LBA30
  4251:          jmp     LBA8B
  4252:  LBA30:  jsr     bMULDIV
  4253:          lda     #$00
  4254:          sta     zRESHO
  4255:          sta     zRESHO + 1
  4256:          sta     zRESHO + 2
  4257:          sta     zRESHO + 3
  4258:          lda     zFACOV
  4259:          jsr     bMULPLY
  4260:          lda     zFACHO + 3
  4261:          jsr     bMULPLY
  4262:          lda     zFACHO + 2
  4263:          jsr     bMULPLY
  4264:          lda     zFACHO + 1
  4265:          jsr     bMULPLY
  4266:          lda     zFACHO
  4267:          jsr     LBA5E
  4268:          jmp     LBB8F
  4269:  bMULPLY:bne     LBA5E
  4270:          jmp     bMULSHF
  4271:  LBA5E:  lsr     a
  4272:          ora     #$80
  4273:  LBA61:  tay
  4274:          bcc     LBA7D
  4275:          clc
  4276:          lda     zRESHO + 3
  4277:          adc     zARGHO + 3
  4278:          sta     zRESHO + 3
  4279:          lda     zRESHO + 2
  4280:          adc     zARGHO + 2
  4281:          sta     zRESHO + 2
  4282:          lda     zRESHO + 1
  4283:          adc     zARGHO + 1
  4284:          sta     zRESHO + 1
  4285:          lda     zRESHO
  4286:          adc     zARGHO
  4287:          sta     zRESHO
  4288:  LBA7D:  ror     zRESHO
  4289:          ror     zRESHO + 1
  4290:          ror     zRESHO + 2
  4291:          ror     zRESHO + 3
  4292:          ror     zFACOV
  4293:          tya
  4294:          lsr     a
  4295:          bne     LBA61
  4296:  LBA8B:  rts
  4297:  bCONUPK:sta     zINDEX
  4298:          sty     zINDEX + 1
  4299:          ldy     #4
  4300:          lda     (zINDEX),y
  4301:          sta     zARGHO + 3
  4302:          dey
  4303:          lda     (zINDEX),y
  4304:          sta     zARGHO + 2
  4305:          dey
  4306:          lda     (zINDEX),y
  4307:          sta     zARGHO + 1
  4308:          dey
  4309:          lda     (zINDEX),y
  4310:          sta     zARGSGN
  4311:          eor     zFACSGN
  4312:          sta     zARISGN
  4313:          lda     zARGSGN
  4314:          ora     #$80
  4315:          sta     zARGHO
  4316:          dey
  4317:          lda     (zINDEX),y
  4318:          sta     zARGEXP
  4319:          lda     zFACEXP
  4320:          rts
  4321:  bMULDIV:lda     zARGEXP
  4322:  LBAB9:  beq     LBADA
  4323:          clc
  4324:          adc     zFACEXP
  4325:          bcc     LBAC4
  4326:          bmi     LBADF
  4327:          clc
  4328:          .byte   ASM_BIT3
  4329:  LBAC4:  bpl     LBADA
  4330:          adc     #$80
  4331:          sta     zFACEXP
  4332:          bne     LBACF
  4333:          jmp     LB8FB
  4334:  LBACF:  lda     zARISGN
  4335:          sta     zFACSGN
  4336:          rts
  4337:  bMLDVEX:lda     zFACSGN
  4338:          eor     #$FF
  4339:          bmi     LBADF
  4340:  LBADA:  pla
  4341:          pla
  4342:          jmp     LB8F7
  4343:  LBADF:  jmp     bOVERR
  4344:  bMUL10: jsr     bMOVAF
  4345:          tax
  4346:          beq     LBAF8
  4347:          clc
  4348:          adc     #2              ; exponent + 2, thus, X * 4
  4349:          bcs     LBADF
  4350:  LBAED:  ldx     #0
  4351:          stx     zARISGN
  4352:          jsr     LB877
  4353:          inc     zFACEXP         ; exponent + 2, thus, ((X * 4) + X) * 2 = X * 10
  4354:          beq     LBADF
  4355:  LBAF8:  rts
  4356:  
  4357:  bTENC:  .byte   $84,$20,$00,$00,$00
  4358:  
  4359:  bDIV10: jsr     bMOVAF
  4360:          lda     #<bTENC
  4361:          ldy     #>bTENC
  4362:          ldx     #0
  4363:  bFDIV:  stx     zARISGN
  4364:          jsr     bMOVFM
  4365:          jmp     FDIVT
  4366:  bFDIVT: jsr     bCONUPK
  4367:  FDIVT:  beq     LBB8A
  4368:          jsr     bROUND
  4369:          lda     #0
  4370:          sec
  4371:          sbc     zFACEXP
  4372:          sta     zFACEXP
  4373:          jsr     bMULDIV
  4374:          inc     zFACEXP
  4375:          beq     LBADF
  4376:          ldx     #-4
  4377:          lda     #1
  4378:  LBB29:  ldy     zARGHO
  4379:          cpy     zFACHO
  4380:          bne     LBB3F
  4381:          ldy     zARGHO + 1
  4382:          cpy     zFACHO + 1
  4383:          bne     LBB3F
  4384:          ldy     zARGHO + 2
  4385:          cpy     zFACHO + 2
  4386:          bne     LBB3F
  4387:          ldy     zARGHO + 3
  4388:          cpy     zFACHO + 3
  4389:  LBB3F:  php
  4390:          rol     a
  4391:          bcc     LBB4C
  4392:          inx
  4393:          sta     zRESHO + 3,x
  4394:          beq     LBB7A
  4395:          bpl     LBB7E
  4396:          lda     #1
  4397:  LBB4C:  plp
  4398:          bcs     LBB5D
  4399:  LBB4F:  asl     zARGHO + 3
  4400:          rol     zARGHO + 2
  4401:          rol     zARGHO + 1
  4402:          rol     zARGHO
  4403:          bcs     LBB3F
  4404:          bmi     LBB29
  4405:          bpl     LBB3F
  4406:  
  4407:  LBB5D:  tay
  4408:          lda     zARGHO + 3
  4409:          sbc     zFACHO + 3
  4410:          sta     zARGHO + 3
  4411:          lda     zARGHO + 2
  4412:          sbc     zFACHO + 2
  4413:          sta     zARGHO + 2
  4414:          lda     zARGHO + 1
  4415:          sbc     zFACHO + 1
  4416:          sta     zARGHO + 1
  4417:          lda     zARGHO
  4418:          sbc     zFACHO
  4419:          sta     zARGHO
  4420:          tya
  4421:          jmp     LBB4F
  4422:  LBB7A:  lda     #$40
  4423:          bne     LBB4C
  4424:          ; -----------
  4425:  LBB7E:  asl     a
  4426:          asl     a
  4427:          asl     a
  4428:          asl     a
  4429:          asl     a
  4430:          asl     a
  4431:          sta     zFACOV
  4432:          plp
  4433:          jmp     LBB8F
  4434:  LBB8A:  ldx     #ErrDivisionByZero
  4435:          jmp     bERROR
  4436:  LBB8F:  lda     zRESHO
  4437:          sta     zFACHO
  4438:          lda     zRESHO + 1
  4439:          sta     zFACHO + 1
  4440:          lda     zRESHO + 2
  4441:          sta     zFACHO + 2
  4442:          lda     zRESHO + 3
  4443:          sta     zFACHO + 3
  4444:          jmp     LB8D7
  4445:  bMOVFM: sta     zINDEX
  4446:          sty     zINDEX + 1
  4447:          ldy     #4
  4448:          lda     (zINDEX),y
  4449:          sta     zFACHO + 3
  4450:          dey
  4451:          lda     (zINDEX),y
  4452:          sta     zFACHO + 2
  4453:          dey
  4454:          lda     (zINDEX),y
  4455:          sta     zFACHO + 1
  4456:          dey
  4457:          lda     (zINDEX),y
  4458:          sta     zFACSGN
  4459:          ora     #$80
  4460:          sta     zFACHO
  4461:          dey
  4462:          lda     (zINDEX),y
  4463:          sta     zFACEXP
  4464:          sty     zFACOV
  4465:          rts
  4466:  bMOV2F: ldx     #zTEMPF2
  4467:          .byte   ASM_BIT3
  4468:  LBBCA:  ldx     #zTEMPF1
  4469:          ldy     #0
  4470:          beq     LBBD4
  4471:  LBBD0:  ldx     zFORPNT
  4472:          ldy     zFORPNT + 1
  4473:  LBBD4:  jsr     bROUND
  4474:          stx     zINDEX
  4475:          sty     zINDEX + 1
  4476:          ldy     #4
  4477:          lda     zFACHO + 3
  4478:          sta     (zINDEX),y
  4479:          dey
  4480:          lda     zFACHO + 2
  4481:          sta     (zINDEX),y
  4482:          dey
  4483:          lda     zFACHO + 1
  4484:          sta     (zINDEX),y
  4485:          dey
  4486:          lda     zFACSGN
  4487:          ora     #$7F
  4488:          and     zFACHO
  4489:          sta     (zINDEX),y
  4490:          dey
  4491:          lda     zFACEXP
  4492:          sta     (zINDEX),y
  4493:          sty     zFACOV
  4494:          rts
  4495:  bMOVFA: lda     zARGSGN
  4496:  LBBFE:  sta     zFACSGN
  4497:          ldx     #5              ; why 5, but 6 in LBC0F?
  4498:  LBC02:  lda     zARG - 1,x
  4499:          sta     zFAC - 1,x
  4500:          dex
  4501:          bne     LBC02
  4502:          stx     zFACOV
  4503:          rts
  4504:  bMOVAF: jsr     bROUND
  4505:  LBC0F:  ldx     #6              ; why 6, but 5 in LBBFE + 2?
  4506:  LBC11:  lda     zFAC - 1,x
  4507:          sta     zARG - 1,x
  4508:          dex
  4509:          bne     LBC11
  4510:          stx     zFACOV
  4511:  LBC1A:  rts
  4512:  bROUND: lda     zFACEXP
  4513:          beq     LBC1A
  4514:          asl     zFACOV
  4515:          bcc     LBC1A
  4516:  LBC23:  jsr     LB96F
  4517:          bne     LBC1A
  4518:          jmp     LB938
  4519:  bSIGN:  lda     zFACEXP
  4520:          beq     LBC38
  4521:  LBC2F:  lda     zFACSGN
  4522:  LBC31:  rol     a
  4523:          lda     #$FF
  4524:          bcs     LBC38
  4525:          lda     #1
  4526:  LBC38:  rts
  4527:  bSGN:   jsr     bSIGN
  4528:  LBC3C:  sta     zFACHO
  4529:          lda     #$00
  4530:          sta     zFACHO + 1
  4531:          ldx     #$88
  4532:  LBC44:  lda     zFACHO
  4533:          eor     #$FF
  4534:          rol     a
  4535:  LBC49:  lda     #$00
  4536:          sta     zFACHO + 3
  4537:          sta     zFACHO + 2
  4538:  LBC4F:  stx     zFACEXP
  4539:          sta     zFACOV
  4540:          sta     zFACSGN
  4541:          jmp     LB8D2
  4542:  bABS:   lsr     zFACSGN
  4543:          rts
  4544:  bFCOMP: sta     zINDEX2
  4545:  LBC5D:  sty     zINDEX2 + 1
  4546:          ldy     #0
  4547:          lda     (zINDEX2),y
  4548:          iny
  4549:          tax
  4550:          beq     bSIGN
  4551:          lda     (zINDEX2),y
  4552:          eor     zFACSGN
  4553:          bmi     LBC2F
  4554:          cpx     zFACEXP
  4555:          bne     LBC92
  4556:          lda     (zINDEX2),y
  4557:          ora     #$80
  4558:          cmp     zFACHO
  4559:          bne     LBC92
  4560:          iny
  4561:          lda     (zINDEX2),y
  4562:          cmp     zFACHO + 1
  4563:          bne     LBC92
  4564:          iny
  4565:          lda     (zINDEX2),y
  4566:          cmp     zFACHO + 2
  4567:          bne     LBC92
  4568:          iny
  4569:          lda     #$7F
  4570:          cmp     zFACOV
  4571:          lda     (zINDEX2),y
  4572:          sbc     zFACHO + 3
  4573:          beq     LBCBA
  4574:  LBC92:  lda     zFACSGN
  4575:          bcc     LBC98
  4576:          eor     #$FF
  4577:  LBC98:  jmp     LBC31
  4578:  bQINT:  lda     zFACEXP
  4579:          beq     LBCE9
  4580:          sec
  4581:          sbc     #$A0
  4582:          bit     zFACSGN
  4583:          bpl     LBCAF
  4584:          tax
  4585:          lda     #$FF
  4586:          sta     zBITS
  4587:          jsr     LB94D
  4588:          txa
  4589:  LBCAF:  ldx     #$61
  4590:          cmp     #$F9
  4591:          bpl     LBCBB
  4592:          jsr     LB999
  4593:          sty     zBITS
  4594:  LBCBA:  rts
  4595:  LBCBB:  tay
  4596:          lda     zFACSGN
  4597:          and     #$80
  4598:          lsr     zFACHO
  4599:          ora     zFACHO
  4600:          sta     zFACHO
  4601:          jsr     LB9B0
  4602:          sty     zBITS
  4603:          rts
  4604:  bINT:   lda     zFACEXP
  4605:          cmp     #$A0
  4606:          bcs     LBCF2
  4607:          jsr     bQINT
  4608:          sty     zFACOV
  4609:          lda     zFACSGN
  4610:          sty     zFACSGN
  4611:          eor     #$80
  4612:          rol     a
  4613:          lda     #$A0
  4614:          sta     zFACEXP
  4615:          lda     zFACHO + 3
  4616:          sta     zCHARAC
  4617:          jmp     LB8D2
  4618:  LBCE9:  sta     zFACHO
  4619:          sta     zFACHO + 1
  4620:          sta     zFACHO + 2
  4621:          sta     zFACHO + 3
  4622:          tay
  4623:  LBCF2:  rts
  4624:  bFIN:   ldy     #0
  4625:          ldx     #zFACSGN - zTEMPF2
  4626:  LBCF7:  sty     zTEMPF2 + 1,x
  4627:          dex
  4628:          bpl     LBCF7
  4629:          bcc     LBD0D
  4630:          cmp     #'-'
  4631:          bne     LBD06
  4632:          stx     zSGNFLG
  4633:          beq     LBD0A
  4634:  LBD06:  cmp     #'+'
  4635:          bne     LBD0F
  4636:  LBD0A:  jsr     zCHRGET
  4637:  LBD0D:  bcc     LBD6A
  4638:  LBD0F:  cmp     #'.'
  4639:          beq     LBD41
  4640:          cmp     #'E'
  4641:          bne     LBD47
  4642:          jsr     zCHRGET
  4643:          bcc     LBD33
  4644:          cmp     #TokMinus
  4645:          beq     LBD2E
  4646:          cmp     #'-'
  4647:          beq     LBD2E
  4648:          cmp     #TokPlus
  4649:          beq     LBD30
  4650:          cmp     #'+'
  4651:          beq     LBD30
  4652:          bne     LBD35
  4653:  LBD2E:  ror     zTEMP_60
  4654:  LBD30:  jsr     zCHRGET
  4655:  LBD33:  bcc     LBD91
  4656:  LBD35:  bit     zTEMP_60
  4657:          bpl     LBD47
  4658:          lda     #0
  4659:          sec
  4660:          sbc     zTEMP_5E
  4661:          jmp     LBD49
  4662:  LBD41:  ror     zTEMP_5F
  4663:          bit     zTEMP_5F
  4664:          bvc     LBD0A
  4665:  LBD47:  lda     zTEMP_5E
  4666:  LBD49:  sec
  4667:          sbc     zTEMP_5D
  4668:          sta     zTEMP_5E
  4669:          beq     LBD62
  4670:          bpl     LBD5B
  4671:  LBD52:  jsr     bDIV10
  4672:          inc     zTEMP_5E
  4673:          bne     LBD52
  4674:          beq     LBD62
  4675:  LBD5B:  jsr     bMUL10
  4676:          dec     zTEMP_5E
  4677:          bne     LBD5B
  4678:  LBD62:  lda     zSGNFLG
  4679:          bmi     LBD67
  4680:          rts
  4681:  LBD67:  jmp     bNEGOP
  4682:  LBD6A:  pha
  4683:          bit     zTEMP_5F
  4684:          bpl     LBD71
  4685:          inc     zTEMP_5D
  4686:  LBD71:  jsr     bMUL10
  4687:          pla
  4688:          sec
  4689:          sbc     #'0'
  4690:          jsr     LBD7E
  4691:          jmp     LBD0A
  4692:  LBD7E:  pha
  4693:          jsr     bMOVAF
  4694:          pla
  4695:          jsr     LBC3C
  4696:          lda     zARGSGN
  4697:          eor     zFACSGN
  4698:          sta     zARISGN
  4699:          ldx     zFACEXP
  4700:          jmp     FADDT
  4701:  LBD91:  lda     zTEMP_5E
  4702:          cmp     #10             ; $0A
  4703:          bcc     LBDA0
  4704:          lda     #100            ; $64
  4705:          bit     zTEMP_60
  4706:          bmi     LBDAE
  4707:          jmp     bOVERR
  4708:  LBDA0:  asl     a
  4709:          asl     a
  4710:          clc
  4711:          adc     zTEMP_5E
  4712:          asl     a
  4713:          clc
  4714:          ldy     #0
  4715:          adc     (zTXTPTR),y
  4716:          sec
  4717:          sbc     #'0'
  4718:  LBDAE:  sta     zTEMP_5E
  4719:          jmp     LBD30
  4720:  
  4721:  bN0999: .byte   $9B,$3E,$BC,$1F,$FD     ; FP: 99999999.9
  4722:  LBDB8:  .byte   $9E,$6E,$6B,$27,$FD     ; FP: 999999999
  4723:  LBDBD:  .byte   $9E,$6E,$6B,$28,$00     ; FP: 1E9
  4724:  
  4725:  bINPRT: lda     #<StrIn         ; output string " IN "
  4726:          ldy     #>StrIn
  4727:          jsr     LBDDA
  4728:  
  4729:          lda     zCURLIN + 1     ; output the current line number
  4730:          ldx     zCURLIN
  4731:  LBDCD:  sta     zFACHO
  4732:          stx     zFACHO + 1
  4733:          ldx     #$90
  4734:          sec
  4735:          jsr     LBC49
  4736:          jsr     LBDDF
  4737:  LBDDA:  jmp     bSTROUT
  4738:  
  4739:  bFOUT:  ldy     #1
  4740:  LBDDF:  lda     #' '
  4741:          bit     zFACSGN
  4742:          bpl     LBDE7
  4743:          lda     #'-'
  4744:  LBDE7:  sta     zASCWRK,y
  4745:          sta     zFACSGN
  4746:          sty     zFBUFPT
  4747:          iny
  4748:          lda     #'0'
  4749:          ldx     zFACEXP
  4750:          bne     LBDF8
  4751:          jmp     LBF04
  4752:  LBDF8:  lda     #$00
  4753:          cpx     #$80
  4754:          beq     LBE00
  4755:          bcs     LBE09
  4756:  LBE00:  lda     #<LBDBD
  4757:          ldy     #>LBDBD
  4758:          jsr     bFMULT
  4759:          lda     #$F7
  4760:  LBE09:  sta     zTEMP_5D
  4761:  LBE0B:  lda     #<LBDB8
  4762:          ldy     #>LBDB8
  4763:          jsr     bFCOMP
  4764:          beq     LBE32
  4765:          bpl     LBE28
  4766:  LBE16:  lda     #<bN0999
  4767:          ldy     #>bN0999
  4768:          jsr     bFCOMP
  4769:          beq     LBE21
  4770:          bpl     LBE2F
  4771:  LBE21:  jsr     bMUL10
  4772:          dec     zTEMP_5D
  4773:          bne     LBE16
  4774:  LBE28:  jsr     bDIV10
  4775:          inc     zTEMP_5D
  4776:          bne     LBE0B
  4777:  LBE2F:  jsr     bFADDH
  4778:  LBE32:  jsr     bQINT
  4779:          ldx     #$01
  4780:          lda     zTEMP_5D
  4781:          clc
  4782:          adc     #$0A
  4783:          bmi     LBE47
  4784:          cmp     #$0B
  4785:          bcs     LBE48
  4786:          adc     #$FF
  4787:          tax
  4788:          lda     #$02
  4789:  LBE47:  sec
  4790:  LBE48:  sbc     #$02
  4791:          sta     zTEMP_5E
  4792:          stx     zTEMP_5D
  4793:          txa
  4794:          beq     LBE53
  4795:          bpl     LBE66
  4796:  LBE53:  ldy     zFBUFPT
  4797:          lda     #'.'
  4798:          iny
  4799:          sta     zASCWRK,y
  4800:          txa
  4801:          beq     LBE64
  4802:          lda     #'0'
  4803:          iny
  4804:          sta     zASCWRK,y
  4805:  LBE64:  sty     zFBUFPT
  4806:  LBE66:  ldy     #$00
  4807:  bFOUTIM:ldx     #$80
  4808:  LBE6A:  lda     zFACHO + 3
  4809:          clc
  4810:          adc     LBF16 + 3,y
  4811:          sta     zFACHO + 3
  4812:          lda     zFACHO + 2
  4813:          adc     LBF16 + 2,y
  4814:          sta     zFACHO + 2
  4815:          lda     zFACHO + 1
  4816:          adc     LBF16 + 1,y
  4817:          sta     zFACHO + 1
  4818:          lda     zFACHO
  4819:          adc     LBF16,y
  4820:          sta     zFACHO
  4821:          inx
  4822:          bcs     LBE8E
  4823:          bpl     LBE6A
  4824:          bmi     LBE90
  4825:  LBE8E:  bmi     LBE6A
  4826:  LBE90:  txa
  4827:          bcc     LBE97
  4828:          eor     #$FF
  4829:          adc     #10
  4830:  LBE97:  adc     #'0' - 1
  4831:          iny
  4832:          iny
  4833:          iny
  4834:          iny
  4835:          sty     zVARPNT
  4836:          ldy     zFBUFPT
  4837:          iny
  4838:          tax
  4839:          and     #$7F
  4840:          sta     zASCWRK,y
  4841:          dec     zTEMP_5D
  4842:          bne     LBEB2
  4843:          lda     #'.'
  4844:          iny
  4845:          sta     zASCWRK,y
  4846:  LBEB2:  sty     zFBUFPT
  4847:          ldy     zVARPNT
  4848:          txa
  4849:          eor     #$FF
  4850:          and     #$80
  4851:          tax
  4852:          cpy     #$24            ; @?
  4853:          beq     LBEC4
  4854:          cpy     #$3C            ; @?
  4855:          bne     LBE6A
  4856:  LBEC4:  ldy     zFBUFPT
  4857:  LBEC6:  lda     zASCWRK,y
  4858:          dey
  4859:          cmp     #'0'
  4860:          beq     LBEC6
  4861:          cmp     #'.'
  4862:          beq     LBED3
  4863:          iny
  4864:  LBED3:  lda     #'+'
  4865:          ldx     zTEMP_5E
  4866:          beq     LBF07
  4867:          bpl     LBEE3
  4868:          lda     #0
  4869:          sec
  4870:          sbc     zTEMP_5E
  4871:          tax
  4872:          lda     #'-'
  4873:  LBEE3:  sta     lSTACK + 1,y
  4874:          lda     #'E'
  4875:          sta     lSTACK,y
  4876:          txa
  4877:          ldx     #'0' - 1
  4878:          sec
  4879:  LBEEF:  inx
  4880:          sbc     #10
  4881:          bcs     LBEEF
  4882:          adc     #'9' + 1
  4883:          sta     lSTACK + 3,y
  4884:          txa
  4885:          sta     lSTACK + 2,y
  4886:          lda     #0
  4887:          sta     lSTACK + 4,y
  4888:          beq     LBF0C
  4889:  LBF04:  sta     zASCWRK,y
  4890:  LBF07:  lda     #0
  4891:          sta     lSTACK,y
  4892:  LBF0C:  lda     #<lSTACK
  4893:          ldy     #>lSTACK
  4894:          rts
  4895:  bFHALF: .byte   $80,$00,$00,$00,$00
  4896:  
  4897:  bFNULL = bFHALF + 2
  4898:  bTI    = bFNULL
  4899:  
  4900:  LBF16:  .byte   $FA,$0A,$1F,$00
  4901:  
  4902:          .byte   $00,$98,$96,$80
  4903:          .byte   $FF,$F0,$BD,$C0
  4904:          .byte   $00,$01,$86,$A0
  4905:          .byte   $FF,$FF,$D8,$F0
  4906:          .byte   $00,$00,$03,$E8
  4907:          .byte   $FF,$FF,$FF,$9C
  4908:          .byte   $00,$00,$00,$0A
  4909:          .byte   $FF,$FF,$FF,$FF
  4910:  
  4911:          .byte   $FF,$DF,$0A,$80
  4912:          .byte   $00,$03,$4B,$C0
  4913:          .byte   $FF,$FF,$73,$60
  4914:          .byte   $00,$00,$0E,$10
  4915:          .byte   $FF,$FF,$FD,$A8
  4916:          .byte   $00,$00,$00,$3C
  4917:  
  4918:          ; This seems to be something like a checksum for the BASIC-ROM.
  4919:  
  4920:          .byte   CHKSUM_BF52
  4921:  
  4922:  ;       FillUntil BASIC_START + $1F71,BASIC_FILLER
  4923:  
  4924:  .segment "BASICSQR"
  4925:  
  4926:  bSQR:   jsr     bMOVAF
  4927:          lda     #<bFHALF
  4928:          ldy     #>bFHALF
  4929:          jsr     bMOVFM
  4930:  bFPWRT: beq     bEXP
  4931:          lda     zARGEXP
  4932:          bne     LBF84
  4933:          jmp     LB8F9
  4934:  LBF84:  ldx     #<zTEMPF3
  4935:          ldy     #>zTEMPF3
  4936:          jsr     LBBD4
  4937:          lda     zARGSGN
  4938:          bpl     LBF9E
  4939:          jsr     bINT
  4940:          lda     #<zTEMPF3
  4941:          ldy     #>zTEMPF3
  4942:          jsr     bFCOMP
  4943:          bne     LBF9E
  4944:          tya
  4945:          ldy     zCHARAC
  4946:  LBF9E:  jsr     LBBFE
  4947:          tya
  4948:          pha
  4949:          jsr     bLOG
  4950:          lda     #<zTEMPF3
  4951:          ldy     #>zTEMPF3
  4952:          jsr     bFMULT
  4953:          jsr     bEXP
  4954:          pla
  4955:          lsr     a
  4956:          bcc     LBFBE
  4957:  bNEGOP: lda     zFACEXP
  4958:          beq     LBFBE
  4959:          lda     zFACSGN
  4960:          eor     #$FF
  4961:          sta     zFACSGN
  4962:  LBFBE:  rts
  4963:  
  4964:  bLOGEB2:
  4965:          .byte $81,$38,$AA,$3B,$29
  4966:  LBFC4:
  4967:          .byte $07
  4968:          .byte $71,$34,$58,$3E,$56
  4969:          .byte $74,$16,$7E,$B3,$1B
  4970:          .byte $77,$2F,$EE,$E3,$85
  4971:          .byte $7A,$1D,$84,$1C,$2A
  4972:          .byte $7C,$63,$59,$58,$0A
  4973:          .byte $7E,$75,$FD,$E7,$C6
  4974:          .byte $80,$31,$72,$18,$10
  4975:          .byte $81,$00,$00,$00,$00
  4976:  
  4977:  bEXP:   lda     #<bLOGEB2
  4978:          ldy     #>bLOGEB2
  4979:          jsr     bFMULT
  4980:          lda     zFACOV
  4981:          adc     #$50
  4982:          bcc     LBFFD
  4983:          jsr     LBC23
  4984:  
  4985:  LBFFD:
  4986:  
  4987:          .segment "BASICSQRJMP"
  4988:  
  4989:          jmp     LE000
  4990:  
  4991:          .segment "BASICSQR2"
  4992:  
  4993:  LE000:
  4994:          sta     zJMPER + 2
  4995:  
  4996:          .segment "BASICSQR3"
  4997:          jsr     LBC0F
  4998:          lda     zFACEXP
  4999:          cmp     #$88
  5000:          bcc     LE00E
  5001:  LE00B:  jsr     bMLDVEX
  5002:  LE00E:  jsr     bINT
  5003:          lda     zCHARAC
  5004:          clc
  5005:          adc     #$81
  5006:          beq     LE00B
  5007:          sec
  5008:          sbc     #1
  5009:          pha
  5010:          ldx     #5
  5011:  LE01E:  lda     zARGEXP,x
  5012:          ldy     zFACEXP,x
  5013:          sta     zFACEXP,x
  5014:          sty     zARGEXP,x
  5015:          dex
  5016:          bpl     LE01E
  5017:          lda     zJMPER + 2
  5018:          sta     zFACOV
  5019:          jsr     FSUBT
  5020:          jsr     bNEGOP
  5021:          lda     #<LBFC4
  5022:          ldy     #>LBFC4
  5023:          jsr     LE059
  5024:          lda     #0
  5025:          sta     zARISGN
  5026:          pla
  5027:          jsr     LBAB9
  5028:          rts
  5029:  bPOLYX: sta     zFBUFPT
  5030:          sty     zFBUFPT + 1
  5031:          jsr     LBBCA
  5032:          lda     #zTEMPF1
  5033:          jsr     bFMULT
  5034:          jsr     LE05D
  5035:          lda     #<zTEMPF1
  5036:          ldy     #>zTEMPF1
  5037:          jmp     bFMULT
  5038:  LE059:  sta     zFBUFPT
  5039:          sty     zFBUFPT + 1
  5040:  LE05D:  jsr     bMOV2F
  5041:          lda     (zFBUFPT),y
  5042:          sta     zSGNFLG
  5043:          ldy     zFBUFPT
  5044:          iny
  5045:          tya
  5046:          bne     LE06C
  5047:          inc     zFBUFPT + 1
  5048:  LE06C:  sta     zFBUFPT
  5049:          ldy     zFBUFPT + 1
  5050:  LE070:  jsr     bFMULT
  5051:          lda     zFBUFPT
  5052:          ldy     zFBUFPT + 1
  5053:          clc
  5054:          adc     #5
  5055:          bcc     LE07D
  5056:          iny
  5057:  LE07D:  sta     zFBUFPT
  5058:          sty     zFBUFPT + 1
  5059:          jsr     bFADD
  5060:          lda     #<zTEMPF2
  5061:          ldy     #>zTEMPF2
  5062:          dec     zSGNFLG
  5063:          bne     LE070
  5064:          rts
  5065:  bRMULC: .byte   $98,$35,$44,$7A,$00
  5066:  LE092:  .byte   $68,$28,$B1,$46,$00
  5067:  
  5068:  bRND:   jsr     bSIGN
  5069:          bmi     LE0D3
  5070:          bne     LE0BE
  5071:          jsr     kIOBASE
  5072:          stx     zINDEX
  5073:          sty     zINDEX + 1
  5074:          ldy     #4
  5075:          lda     (zINDEX),y
  5076:          sta     zFACHO
  5077:          iny
  5078:          lda     (zINDEX),y
  5079:          sta     zFACHO + 2
  5080:          ldy     #8
  5081:          lda     (zINDEX),y
  5082:          sta     zFACHO + 1
  5083:          iny
  5084:          lda     (zINDEX),y
  5085:          sta     zFACHO + 3
  5086:          jmp     LE0E3
  5087:  LE0BE:  lda     #<zRNDX
  5088:          ldy     #>zRNDX
  5089:          jsr     bMOVFM
  5090:          lda     #<bRMULC
  5091:          ldy     #>bRMULC
  5092:          jsr     bFMULT
  5093:          lda     #<LE092
  5094:          ldy     #>LE092
  5095:          jsr     bFADD
  5096:  LE0D3:  ldx     zFACHO + 3
  5097:          lda     zFACHO
  5098:          sta     zFACHO + 3
  5099:          stx     zFACHO
  5100:          ldx     zFACHO + 1
  5101:          lda     zFACHO + 2
  5102:          sta     zFACHO + 1
  5103:          stx     zFACHO + 2
  5104:  LE0E3:  lda     #0
  5105:          sta     zFACSGN
  5106:          lda     zFACEXP
  5107:          sta     zFACOV
  5108:          lda     #$80
  5109:          sta     zFACEXP
  5110:          jsr     LB8D7
  5111:          ldx     #<zRNDX
  5112:          ldy     #>zRNDX
  5113:  LE0F6:  jmp     LBBD4
  5114:  bBIOERR:cmp     #$F0
  5115:          bne     LE104
  5116:          sty     zMEMSIZ + 1
  5117:          stx     zMEMSIZ
  5118:          jmp     LA663
  5119:  LE104:  tax
  5120:          bne     LE109
  5121:          ldx     #ErrBreak
  5122:  LE109:  jmp     bERROR
  5123:  bCHOUT: jsr     kCHROUT
  5124:          bcs     bBIOERR
  5125:          rts
  5126:  bCHIN:  jsr     kCHRIN
  5127:          bcs     bBIOERR
  5128:          rts
  5129:  bCKOUT:
  5130:  .if CompileComputer >= C64_02
  5131:          jsr     LE4AD
  5132:  .else
  5133:          jsr     kCHKOUT
  5134:  .endif
  5135:          bcs     bBIOERR
  5136:          rts
  5137:  bCKIN:  jsr     kCHKIN
  5138:          bcs     bBIOERR
  5139:          rts
  5140:  bGETIN: jsr     kGETIN
  5141:          bcs     bBIOERR
  5142:          rts
  5143:  bSYS:   jsr     bFRMNUM
  5144:          jsr     bGETADR
  5145:          lda     #>(LE147 - 1)
  5146:          pha
  5147:          lda     #<(LE147 - 1)
  5148:          pha
  5149:          lda     lSPREG
  5150:          pha
  5151:          lda     lSAREG
  5152:          ldx     lSXREG
  5153:          ldy     lSYREG
  5154:          plp
  5155:          jmp     (zLINNUM)
  5156:  LE147:  php
  5157:          sta     lSAREG
  5158:          stx     lSXREG
  5159:          sty     lSYREG
  5160:          pla
  5161:          sta     lSPREG
  5162:          rts
  5163:  bSAVET: jsr     bSLPARA
  5164:          ldx     zVARTAB
  5165:          ldy     zVARTAB + 1
  5166:          lda     #zTXTTAB
  5167:          jsr     kSAVE
  5168:          bcs     bBIOERR
  5169:          rts
  5170:  bVERFYT:lda     #1
  5171:          .byte   ASM_BIT3
  5172:  
  5173:  bLOADT: lda     #0
  5174:          sta     zVERCK
  5175:          jsr     bSLPARA
  5176:          lda     zVERCK
  5177:          ldx     zTXTTAB
  5178:          ldy     zTXTTAB + 1
  5179:          jsr     kLOAD
  5180:          bcs     LE1D1
  5181:          lda     zVERCK
  5182:          beq     ChkStatus
  5183:  JDLE17E:
  5184:          ldx     #ErrVerify
  5185:          jsr     kREADST
  5186:          and     #$10
  5187:  
  5188:  .if CompileComputer >= C64_GENERAL
  5189:          bne     LE19E
  5190:  .else
  5191:  
  5192:          beq     @E187
  5193:          jmp     bERROR
  5194:  .endif
  5195:  
  5196:  @E187:  lda     zTXTPTR
  5197:  
  5198:          cmp     #>lBUF
  5199:          beq     LE194
  5200:          lda     #<bOKK
  5201:          ldy     #>bOKK
  5202:  
  5203:          jmp     bSTROUT
  5204:  LE194:  rts
  5205:  
  5206:  ChkStatus:
  5207:          jsr     kREADST
  5208:          and     #$BF
  5209:          beq     LE1A1
  5210:          ldx     #ErrLoad
  5211:  LE19E:  jmp     bERROR
  5212:  LE1A1:  lda     zTXTPTR + 1
  5213:          cmp     #>lBUF
  5214:          bne     LE1B5
  5215:  JDLE1A7:
  5216:          stx     zVARTAB
  5217:          sty     zVARTAB + 1
  5218:          lda     #<StrReady
  5219:          ldy     #>StrReady
  5220:          jsr     bSTROUT
  5221:          jmp     LA52A
  5222:  LE1B5:  jsr     bSTXPT
  5223:  
  5224:  .if CompileComputer >= C64_GENERAL
  5225:          jsr     bLINKPRG
  5226:          jmp     LA677
  5227:  .elseif CompileComputer >= VIC20_06
  5228:          JMP     LE476
  5229:  .else
  5230:          JMP     LA677
  5231:  .endif
  5232:  
  5233:  ;       FillUntil BASIC_START_2 + $01BE
  5234:  .segment "BASICOPEN"
  5235:  
  5236:  bOPENT: jsr     bOCPARA
  5237:          jsr     kOPEN
  5238:          bcs     LE1D1
  5239:          rts
  5240:  bCLOSET:jsr     bOCPARA
  5241:          lda     zFORPNT
  5242:          jsr     kCLOSE
  5243:          bcc     LE194
  5244:  LE1D1:  jmp     bBIOERR
  5245:  bSLPARA:lda     #0
  5246:          jsr     kSETNAM
  5247:          ldx     #1
  5248:          ldy     #0
  5249:  .ifdef JIFFY
  5250:          jsr     JDLF73A
  5251:  .else
  5252:          jsr     kSETLFS
  5253:  .endif
  5254:          jsr     bDEFLT
  5255:          jsr     LE257
  5256:          jsr     bDEFLT
  5257:          jsr     bCOMBYT
  5258:          ldy     #0
  5259:          stx     zFORPNT
  5260:          jsr     kSETLFS
  5261:          jsr     bDEFLT
  5262:          jsr     bCOMBYT
  5263:          txa
  5264:          tay
  5265:          ldx     zFORPNT
  5266:          jmp     kSETLFS
  5267:  bCOMBYT:jsr     bCMMERR
  5268:          jmp     LB79E
  5269:  bDEFLT: jsr     zCHRGOT
  5270:          bne     LE20D
  5271:          pla
  5272:          pla
  5273:  LE20D:  rts
  5274:  bCMMERR:jsr     bCHKCMA
  5275:  LE211:  jsr     zCHRGOT
  5276:          bne     LE20D
  5277:          jmp     bSYNERR
  5278:  bOCPARA:lda     #0
  5279:          jsr     kSETNAM
  5280:          jsr     LE211
  5281:          jsr     LB79E
  5282:          stx     zFORPNT
  5283:          txa
  5284:          ldx     #1
  5285:  JDLE229:
  5286:          ldy     #0
  5287:          jsr     kSETLFS
  5288:          jsr     bDEFLT
  5289:          jsr     bCOMBYT
  5290:          stx     zFORPNT + 1
  5291:          ldy     #0
  5292:          lda     zFORPNT
  5293:          cpx     #3
  5294:          bcc     LE23F
  5295:          dey
  5296:  LE23F:  jsr     kSETLFS
  5297:          jsr     bDEFLT
  5298:          jsr     bCOMBYT
  5299:          txa
  5300:          tay
  5301:          ldx     zFORPNT + 1
  5302:          lda     zFORPNT
  5303:          jsr     kSETLFS
  5304:          jsr     bDEFLT
  5305:          jsr     bCMMERR
  5306:  LE257:  jsr     bFRMEVL
  5307:  JDLE25A:
  5308:          jsr     bFRESTR
  5309:          ldx     zINDEX
  5310:          ldy     zINDEX + 1
  5311:          jmp     kSETNAM
  5312:  bCOS:   lda     #<bPI2
  5313:          ldy     #>bPI2
  5314:          jsr     bFADD
  5315:  bSIN:   jsr     bMOVAF
  5316:          lda     #<LE2E5
  5317:          ldy     #>LE2E5
  5318:          ldx     zARGSGN
  5319:          jsr     bFDIV
  5320:          jsr     bMOVAF
  5321:          jsr     bINT
  5322:          lda     #0
  5323:          sta     zARISGN
  5324:          jsr     FSUBT
  5325:          lda     #<LE2EA
  5326:          ldy     #>LE2EA
  5327:          jsr     bFSUB
  5328:          lda     zFACSGN
  5329:          pha
  5330:          bpl     LE29D
  5331:          jsr     bFADDH
  5332:          lda     zFACSGN
  5333:          bmi     LE2A0
  5334:          lda     zTANSGN
  5335:          eor     #$FF
  5336:          sta     zTANSGN
  5337:  LE29D:  jsr     bNEGOP
  5338:  LE2A0:  lda     #<LE2EA
  5339:          ldy     #>LE2EA
  5340:          jsr     bFADD
  5341:          pla
  5342:          bpl     LE2AD
  5343:          jsr     bNEGOP
  5344:  LE2AD:  lda     #<LE2EF
  5345:          ldy     #>LE2EF
  5346:          jmp     bPOLYX
  5347:  bTAN:   jsr     LBBCA
  5348:          lda     #$00
  5349:          sta     zTANSGN
  5350:          jsr     bSIN
  5351:          ldx     #<zTEMPF3
  5352:          ldy     #>zTEMPF3
  5353:          jsr     LE0F6
  5354:          lda     #<zTEMPF1
  5355:          ldy     #>zTEMPF1
  5356:          jsr     bMOVFM
  5357:          lda     #$00
  5358:          sta     zFACSGN
  5359:          lda     zTANSGN
  5360:          jsr     LE2DC
  5361:          lda     #<zTEMPF3
  5362:          ldy     #>zTEMPF3
  5363:          jmp     bFDIVT
  5364:  LE2DC:  pha
  5365:          jmp     LE29D
  5366:  
  5367:  bPI2:   .byte   $81,$49,$0F,$DA,$A2
  5368:  LE2E5:  .byte   $83,$49,$0F,$DA,$A2
  5369:  LE2EA:  .byte   $7F,$00,$00,$00,$00
  5370:  LE2EF:  .byte   $05
  5371:          .byte   $84,$E6,$1A,$2D,$1B
  5372:          .byte   $86,$28,$07,$FB,$F8
  5373:          .byte   $87,$99,$68,$89,$01
  5374:          .byte   $87,$23,$35,$DF,$E1
  5375:          .byte   $86,$A5,$5D,$E7,$28
  5376:          .byte   $83,$49,$0F,$DA,$A2
  5377:  
  5378:  bATN:   lda     zFACSGN
  5379:          pha
  5380:          bpl     LE316
  5381:          jsr     bNEGOP
  5382:  LE316:  lda     zFACEXP
  5383:          pha
  5384:          cmp     #$81
  5385:          bcc     LE324
  5386:          lda     #<bFPTABL
  5387:          ldy     #>bFPTABL
  5388:          jsr     bFDIVT
  5389:  LE324:  lda     #<bATNCON
  5390:          ldy     #>bATNCON
  5391:          jsr     bPOLYX
  5392:          pla
  5393:          cmp     #$81
  5394:          bcc     LE337
  5395:          lda     #<bPI2
  5396:          ldy     #>bPI2
  5397:          jsr     bFSUB
  5398:  LE337:  pla
  5399:          bpl     LE33D
  5400:          jmp     bNEGOP
  5401:  LE33D:  rts
  5402:  
  5403:  bATNCON:.byte   $0B
  5404:          .byte   $76,$B3,$83,$BD,$D3
  5405:          .byte   $79,$1E,$F4,$A6,$F5
  5406:          .byte   $7B,$83,$FC,$B0,$10
  5407:          .byte   $7C,$0C,$1F,$67,$CA
  5408:          .byte   $7C,$DE,$53,$CB,$C1
  5409:          .byte   $7D,$14,$64,$70,$4C
  5410:          .byte   $7D,$B7,$EA,$51,$7A
  5411:          .byte   $7D,$63,$30,$88,$7E
  5412:          .byte   $7E,$92,$44,$99,$3A
  5413:          .byte   $7E,$4C,$CC,$91,$C7
  5414:          .byte   $7F,$AA,$AA,$AA,$13
  5415:          .byte   $81,$00,$00,$00,$00
  5416:  
  5417:  .if CompileComputer >= C64_GENERAL
  5418:  LE37B:  jsr     kCLRCHN
  5419:          lda     #0
  5420:          sta     z13
  5421:          jsr     LA67A
  5422:          cli
  5423:  
  5424:          ; Patch: Output READY, but respect the (lIERROR) vector
  5425:  ReadyVector:
  5426:          ldx     #$80         ; errorcode = bit 7 set, that is, no error occurred
  5427:          jmp     (lIERROR)    ;  by default, this is a no-op
  5428:  
  5429:  PatchErrorOut:
  5430:          txa                  ; check the error code
  5431:          bmi     @LE391       ; bit 7 set? Then no error occurred, jump to "ready"
  5432:          jmp     ErrorOut     ; output the error
  5433:  @LE391:
  5434:          jmp     bREADY
  5435:  .endif
  5436:  
  5437:  LE394:
  5438:  .ifdef JIFFY
  5439:          jsr     JDLE4B7
  5440:  .else
  5441:          jsr     LE453
  5442:  .endif
  5443:          jsr     LE3BF
  5444:          jsr     LE422
  5445:          ldx     #-5             ; stack pointer to $01FB
  5446:          txs
  5447:  
  5448:  .if CompileComputer >= C64_GENERAL
  5449:          bne     ReadyVector
  5450:  .else
  5451:          jmp     bREADY
  5452:  .endif
  5453:  
  5454:  .segment "CHRGET"
  5455:  
  5456:  COPY_OF_CHRGET:
  5457:          inc     zTXTPTR
  5458:          bne     COPY_OF_CHRGOT
  5459:          inc     zTXTPTR + 1
  5460:  
  5461:  COPY_OF_CHRGOT:
  5462:          lda     $EA60           ; this is just a dummy address
  5463:          cmp     #'9' + 1
  5464:          bcs     COPY_OF_CHRGOT_RTS
  5465:  
  5466:  COPY_OF_CHRGOT_SPACE:
  5467:          cmp     #' '
  5468:          beq     COPY_OF_CHRGET
  5469:          sec
  5470:          sbc     #'0'
  5471:          sec
  5472:          sbc     #-'0'
  5473:  COPY_OF_CHRGOT_RTS:
  5474:          rts
  5475:  
  5476:          .byte   $80,$4F,$C7,$52,$58
  5477:  
  5478:  END_COPY_OF_CHRGET:
  5479:  
  5480:  .segment "INIT"
  5481:  
  5482:  LE3BF:  lda     #ASM_JMP
  5483:          sta     zJMPER
  5484:          sta     lUSRPOK
  5485:          lda     #<bIQERR
  5486:          ldy     #>bIQERR
  5487:          sta     lUSRADD
  5488:          sty     lUSRADD + 1
  5489:          lda     #<bGIVAYF
  5490:          ldy     #>bGIVAYF
  5491:          sta     zADRAY2
  5492:          sty     zADRAY2 + 1
  5493:          lda     #<bFACINX
  5494:          ldy     #>bFACINX
  5495:          sta     zADRAY1
  5496:          sty     zADRAY1 + 1
  5497:          ldx     #END_COPY_OF_CHRGET - COPY_OF_CHRGET - 1
  5498:  LE3E2:  lda     COPY_OF_CHRGET,x
  5499:          sta     zCHRGET,x
  5500:          dex
  5501:          bpl     LE3E2
  5502:          lda     #$03
  5503:          sta     zFOUR6
  5504:          lda     #0
  5505:          sta     zBITS
  5506:          sta     z13
  5507:          sta     zLASTPT + 1
  5508:          ldx     #1
  5509:          stx     lBUF - 3
  5510:          stx     lBUF - 4
  5511:          ldx     #zTEMPST
  5512:          stx     zTEMPPT
  5513:          sec
  5514:          jsr     kMEMBOT
  5515:          stx     zTXTTAB
  5516:          sty     zTXTTAB + 1
  5517:          sec
  5518:          jsr     kMEMTOP
  5519:          stx     zMEMSIZ
  5520:          sty     zMEMSIZ + 1
  5521:          stx     zFRETOP
  5522:          sty     zFRETOP + 1
  5523:          ldy     #0
  5524:          tya
  5525:          sta     (zTXTTAB),y
  5526:          inc     zTXTTAB
  5527:          bne     LE421
  5528:          inc     zTXTTAB + 1
  5529:  LE421:  rts
  5530:  LE422:  lda     zTXTTAB
  5531:          ldy     zTXTTAB + 1
  5532:          jsr     bREASON
  5533:          lda     #<LE473
  5534:          ldy     #>LE473
  5535:  .if CompileComputer = C64_4064
  5536:          jmp     LE441
  5537:  .else
  5538:          jsr     bSTROUT
  5539:  .endif
  5540:          lda     zMEMSIZ
  5541:          sec
  5542:          sbc     zTXTTAB
  5543:          tax
  5544:          lda     zMEMSIZ + 1
  5545:          sbc     zTXTTAB + 1
  5546:          jsr     LBDCD
  5547:          lda     #<LE460
  5548:          ldy     #>LE460
  5549:  LE441:  jsr     bSTROUT
  5550:          jmp     LA644
  5551:  
  5552:  .if CompileComputer < C64_GENERAL
  5553:  ;       .include "../vic20/basic-texts.inc"
  5554:  LE460:
  5555:          .byte   " BYTES FREE",$0D,$00
  5556:  
  5557:  LE473:  .byte   $93
  5558:          .byte   "**** CBM BASIC V2 ****"
  5559:          .byte   $0D,$00
  5560:  .endif
  5561:  
  5562:  LE447:
  5563:  .if CompileComputer >= C64_GENERAL
  5564:    .ifdef JIFFY
  5565:          .addr   JDLF763
  5566:    .else
  5567:          .addr   PatchErrorOut ; for the C64, check if bit 7 of the error code is set.
  5568:    .endif
  5569:  .else
  5570:          .addr   ErrorOut ; for the VIC20, this is always an error.
  5571:  .endif
  5572:  
  5573:  .if CompileComputer = C64_GS
  5574:          .addr   C64GS_Init
  5575:  .else
  5576:          .addr   IMAIN
  5577:  .endif
  5578:  
  5579:  .ifdef JIFFY
  5580:          .addr   LEA64
  5581:  .else
  5582:          .addr   LA57C
  5583:  .endif
  5584:          .addr   LA71A
  5585:          .addr   LA7E4
  5586:          .addr   LAE86
  5587:  END_LE447:
  5588:  
  5589:  LE453:  ldx     #END_LE447 - LE447 - 1
  5590:  LE455:  lda     LE447,x
  5591:          sta     lIERROR,x
  5592:          dex
  5593:          bpl     LE455
  5594:          rts
  5595:  
  5596:  .if CompileComputer >= C64_GENERAL
  5597:          .byte   $00     ; basic checksum?
  5598:  
  5599:  ;       .include "../c64/basic-texts.inc"
  5600:  LE460:
  5601:          .byte   " BASIC BYTES FREE",$0D,$00
  5602:  
  5603:  LE473:  .byte   $93
  5604:  
  5605:  .ifdef JIFFY
  5606:          .byte   $0D,"       JIFFYDOS V6.01 (C)1989 CMD  "
  5607:          .byte   $0D,$0D
  5608:          .byte   " C-64 BASIC V2   ",$00
  5609:  .elseif CompileComputer = C64_SX64
  5610:          .byte   $0D,"     *****  SX-64 BASIC V2.0  *****"
  5611:          .byte   $0D,$0D
  5612:          .byte   " 64K RAM SYSTEM  ",$00
  5613:  .elseif CompileComputer = C64_4064
  5614:          .byte   $0D,"  **** COMMODORE 4064  BASIC V2.0 ****"
  5615:          .byte   $0D,$0D,$00
  5616:          .byte   "              "
  5617:  .elseif CompileComputer >= C64_GENERAL
  5618:          .byte   $0D,"    **** COMMODORE 64 BASIC V2 ****"
  5619:          .byte   $0D,$0D
  5620:          .byte   " 64K RAM SYSTEM  ",$00
  5621:  .endif
  5622:  .endif
  5623:  
  5624:  .if CompileComputer < C64_GENERAL
  5625:  
  5626:  LE37B:
  5627:          jsr     kCLRCHN
  5628:          lda     #0
  5629:          sta     z13
  5630:          jsr     LA67A
  5631:          cli
  5632:          jmp     bREADY
  5633:  
  5634:          .byte   CHECKSUM_E475
  5635:  
  5636:    .if CompileComputer >= VIC20_06
  5637:  LE476:
  5638:          jsr     bLINKPRG
  5639:          jmp     LA677
  5640:    .endif
  5641:  .endif
  5642:  
  5643:  ;       .include "../kernal/kernal-memory.inc"
  5644:  .segment "MEM_KERNAL_ZP": zeropage
  5645:  
  5646:  zSTATUS:        .res 1  ; $0090 ; status of TAPE/IEC routines
  5647:  
  5648:  zSTKEY:         .res 1  ; $0091
  5649:  zSVXT:          .res 1  ; $0092
  5650:  zVERCKK:        .res 1  ; $0093 ; verify flag: Remember in KLOAD if LOAD (=0) or VERIFY (=1) is requested.
  5651:  zC3PO:          .res 1  ; $0094 ; delayed byte for IEC output
  5652:                                  ; As an EOI must be signaled BEFORE the last byte is transferred,
  5653:                                  ; the KERNAL routines use a delayed write approach:
  5654:                                  ;
  5655:                                  ; It starts with zC3PO = 0.
  5656:                                  ; When the first byte to be output is given to the IEC routines,
  5657:                                  ; it is written to zBSOUR, and zC3PO.7 is set.
  5658:                                  ; When the next byte is written, zC3PO is tested. As it is negative,
  5659:                                  ; the byte in zBSOUR is being output to the IEC bus. Afterwards,
  5660:                                  ; the new byte is written into zBSOUR.
  5661:                                  ; When the last byte is transferred, the next command transmitted
  5662:                                  ; (i.e. LISTEN, TALK, UNLISTEN, UNTALK) tests for zC3PO. As it is
  5663:                                  ; negative, the last byte (in zBSOUR) is output to the IEC bus, and
  5664:                                  ; an EOI is signalled.
  5665:                                  ;
  5666:  zBSOUR:         .res 1  ; $0095 ; The byte to write on the IEC bus. (see also zC3PO)
  5667:  zSYNO:          .res 1  ; $0096
  5668:  zTEMPX:         .res 1  ; $0097
  5669:  zLDTND:         .res 1  ; $0098 ; number of active entries in the lLAT, lFAT and lSAT table
  5670:  zDFLTN:         .res 1  ; $0099
  5671:  zDFLTO:         .res 1  ; $009A
  5672:  zPRTY:          .res 1  ; $009B
  5673:  zDPSW:          .res 1  ; $009C
  5674:  zNSGFLG:        .res 1  ; $009D ; message output policy:
  5675:                                  ; bit 7: Output "Loading", "Saving", "Verifying", "Found", ... messages
  5676:                                  ; bit 6: Output "I/O ERROR #n" if KERNAL routines encounter an error
  5677:                                  ; This value is only set by kSETMSG.
  5678:  
  5679:  zPTR1:          .res 1  ; $009E
  5680:  zPTR2:          .res 1  ; $009F
  5681:  zTIME:          .res 3  ; $00A0
  5682:  zTSFCNT:        .res 1  ; $00A3 ; mark: signal EOI (== $80) or not (== $00) on IEC bus.
  5683:  zTBTCNT:        .res 1  ; $00A4
  5684:  zCNTDN:         .res 1  ; $00A5
  5685:  zBUFPNT:        .res 1  ; $00A6 ; pointer into tape buffer (lTBUFFR), stored as an index 0..(TBUFFR_SIZE - 1): Contains the last value that was written or read.
  5686:  zINBIT:         .res 1  ; $00A7
  5687:  zBITC1:         .res 1  ; $00A8
  5688:  zRINONE:        .res 1  ; $00A9
  5689:  zRIDATA:        .res 1  ; $00AA
  5690:  zRIPRTY:        .res 1  ; $00AB
  5691:  zSAL:           .res 2  ; $00AC
  5692:  zEAL:           .res 2  ; $00AE
  5693:  zCMPO:          .res 2  ; $00B0
  5694:  zTAPE1:         .res 2  ; $00B2
  5695:  zBITTS:         .res 1  ; $00B4
  5696:  zNXTBIT:        .res 1  ; $00B5
  5697:  zRODATA:        .res 1  ; $00B6
  5698:  zFNLEN:         .res 1  ; $00B7 ; length of the name of the file to be opened. Address at zFNADR. Only used on OPEN and LOAD.
  5699:  zLA:            .res 1  ; $00B8 ; logical device number of current open file (or in preparation to a call to OPEN)
  5700:  zSA:            .res 1  ; $00B9 ; device (primary) address of current open file (or in preparation to a call to OPEN)
  5701:  zFA:            .res 1  ; $00BA ; secondary address of current open file (or in preparation to a call to OPEN)
  5702:  zFNADR:         .res 2  ; $00BB ; address of the name of the file to be opened. Length at zFNLEN. Only used on OPEN and LOAD.
  5703:  zROPRTY:        .res 1  ; $00BD
  5704:  zFSBLK:         .res 1  ; $00BE
  5705:  zMYCH:          .res 1  ; $00BF
  5706:  zCAS1:          .res 1  ; $00C0 ; 0 if no tape operation in progress, != 0 otherwise. Use in the IRQ routine to switch off tape motor, if needed.
  5707:  zSTAL:          .res 2  ; $00C1
  5708:  zMEMUSS:        .res 2  ; $00C3
  5709:  zLSTX:          .res 1  ; $00C5 ; last pressed key. That is, after keyboard scanning completes, this becomes a copy of zSFDX. This is used for determining if key repetition is to be performed.
  5710:  zNDX:           .res 1  ; $00C6 ; current numbers of characters in the keyboard buffer (lKEYD). The maximum is stored in lXMAX.
  5711:  zRVS:           .res 1  ; $00C7
  5712:  zINDX:          .res 1  ; $00C8
  5713:  zLXSP:          .res 1  ; $00C9
  5714:  zTEMP_zPNTR:    .res 1  ; $00CA ; temporary buffer for cursorpos (zPNTR) inside of BASIN
  5715:  zSFDX:          .res 1  ; $00CB ; key code if the code that is currently found pressed
  5716:  zBLNSW:         .res 1  ; $00CC ; blink switch: <> 0 -> disable cursor, == 0 -> enable cursor
  5717:  zBLNCT:         .res 1  ; $00CD
  5718:  zGDBLN:         .res 1  ; $00CE
  5719:  zBLNON:         .res 1  ; $00CF ; current blink state: 0 = cursor currently invisible, 1 = cursor is just now visible on the screen
  5720:  zCRSW:          .res 1  ; $00D0 ; used in editor routines for sreen input: > 0 if CR has been pressed, 0 if there has not been any input yet (or no CR has been pressed yet)
  5721:  zPNT:           .res 2  ; $00D1 ; pointer to start of current cursor row in video RAM (cf. zUSER)
  5722:  zPNTR:          .res 1  ; $00D3 ; column of current cursor position (0 ... X-1)
  5723:  zQTSW:          .res 1  ; $00D4 ; quotation mark switch: 1 = we are in quotation mode, 0 = we are not.
  5724:  zLNMX:          .res 1  ; $00D5 ; maximum column number in the current (logical) line
  5725:  zTBLX:          .res 1  ; $00D6 ; row of current cursor positon (0 ... Y-1)
  5726:  zSCHAR:         .res 1  ; $00D7 ; temporary storage for a character in editor routines for input and output, and temporary storage in tape routines
  5727:  zINSRT:         .res 1  ; $00D8 ; number of characters to output in INSERT mode. 0 = we are not in insert mode
  5728:  zLDTB1:         .res 26 ; $00D9 ; high byte of start address of (logical) screen rows
  5729:                                  ; Bit 7 ($80) is 1 if this line is "stand-alone";
  5730:                                  ; it is 0 if this line is combined with the previous one
  5731:                                  ; the lower bits (and #>lVIDEORAM_SIZE) define the high byte bits of the start address of this row.
  5732:                                  ;
  5733:                                  ; For the last row, this table entry contains $FF as an end marker.
  5734:  
  5735:  zUSER:          .res 2  ; $00F3 ; pointer to start of current cursor row in color RAM (cf. zPNT)
  5736:  zKEYTAB:        .res 2  ; $00F5
  5737:  zRIBUF:         .res 2  ; $00F7 ; pointer to the RS232 input buffer (ring buffer) (see also lRIDBE, lRIDBS)
  5738:  zROBUF:         .res 2  ; $00F9 ; pointer to the RS232 output buffer (ring buffer) (see also lRODBE, lRODBS)
  5739:  zFREKXP:                .res 4  ; $00FB
  5740:  
  5741:          .segment "MEM_KERNAL_DATA_0200"
  5742:  
  5743:  ; the following table contains the data (logical file number, primary address, secondary address) for open files.
  5744:  ; The entries correspond to each other: That is, lLAT + x, lFAT + x and lSAT + x contain the data for the file
  5745:  ; with the index (*not* logical file number!) x.
  5746:  
  5747:  lLAT_Size       := 10
  5748:  lLAT:           .res lLAT_Size  ; $0259 ; table of logical file numbers for open files. Number of active entries in zLDTND. Cannot be 0 for active files.
  5749:  lFAT:           .res lLAT_Size  ; $0263 ; table of device (primary) addresses for open files. Number of active entries in zLDTND.
  5750:  lSAT:           .res lLAT_Size  ; $026D ; table of secondary addresses for open files. Number of active entries in zLDTND.
  5751:  
  5752:  lKEYD:          .res 10 ; $0277
  5753:  lMEMSTR:        .res 2  ; $0281
  5754:  lMEMSIZ:        .res 2  ; $0283
  5755:  lTIMOUT:        .res 1  ; $0285
  5756:  lCOLOR:         .res 1  ; $0286 ; default color (bit 7 must be 0, or CHROUT_SCREEN will behave erroneouskly!)
  5757:  lGDCOL:         .res 1  ; $0287
  5758:  lHIBASE:                .res 1  ; $0288 ; high byte of video RAM address
  5759:  lXMAX:          .res 1  ; $0289 ; maximum number of characters in the keyboard buffer (lKEYD). zNDX is checked against this value
  5760:  lRPTFLG:        .res 1  ; $028A ; repeat flag for keys
  5761:                                  ; bit 7 ($80) == 1 -> repeat all keys
  5762:                                  ; bit 6 ($40) == 1 -> do not repeat any key
  5763:                                  ; else: Repeat special keys (space, CRSRS, INS/DEL), but not the others
  5764:  
  5765:                                  ; the test is done starting with bit 7, then bit 6.
  5766:                                  ; thus, if both are set, all keys are repeated
  5767:  
  5768:  lKOUNT:         .res 1  ; $028B ; delay counter for key repetitions. This is decremented on every IRQ, starting from 4.
  5769:  
  5770:  lDELAY:         .res 1  ; $028C ; delay counter for key repetitions. It is used for the initial delay before the key repetition starts.
  5771:  
  5772:  lSHFLAG:        .res 1  ; $028D ; contains the state of the shift keys while scanning the keyboard.
  5773:                                  ; The state is an OR between the following values, if the correspondig key is pressed:
  5774:                                  ; bit 0 ($01) = shift
  5775:                                  ; bit 1 ($02) = C=
  5776:                                  ; bit 2 ($04) = CTRL
  5777:  lSHFLAG_SHIFT := $01
  5778:  lSHFLAG_CBM   := $02
  5779:  lSHFLAG_CTRL  := $04
  5780:  
  5781:  lLSTSHF:        .res 1  ; $028E ; contains the *last* shift state. That is, after the keyboard is scanned, this becomes a copy of lSHFLAG. This way, the KERNAL prevents a repeated toggling when pressend SHIFT + C=
  5782:  lKEYLOG:        .res 2  ; $028F
  5783:  lMODE:          .res 1  ; $0291 ; determines editor mode.
  5784:                                  ; bit 7 ($80) == 1 -> Switching between uppercase-mode and lowercase-mode via SHIFT + C= is not allowed
  5785:                                  ; bit 4 ($10) == 1 -> TODO ??? (used in VIC20-02)
  5786:                                  ; bit 3 ($08) == 1 -> we are in lowercase mode, == 0 -> we are in uppercase mode (only VIC20-02)
  5787:                                  ; on VIC20-02, lMODE also contains the offset into the @KEYTABS_VEC table ($00-$16)
  5788:  
  5789:                                  ; on the VIC20-02, lMODE is used in CHROUT_SCREEN to determine if some chars are to
  5790:                                  ; be translated (according to CHROUT_REPLACEMENT_TABLE). If lMODE is not 0, the
  5791:                                  ; translation is done. If it is 0, the translation is skipped.
  5792:  
  5793:  lAUTODN:        .res 1  ; $0292 ; TODO "Auto down" flag: (Flag: "combine line with next line, if needed")
  5794:  
  5795:                                  ; If the output is done because of some key press, lAUTODN is not 0. In this case,
  5796:                                  ; when the output reaches the end of a row, this row is combined with the next
  5797:                                  ; row. Furthermore, the screen contents below the current line are scrolled down.
  5798:  
  5799:                                  ; If the output is done without some key press, lAUTODN is 0. In this case,
  5800:                                  ; when the output reaches the end of a row, this row is combined with the next
  5801:                                  ; one, but the screen contents are NOT scrolled down.
  5802:  
  5803:  lM51CTR:        .res 1  ; $0293
  5804:  lM51CDR:        .res 1  ; $0294
  5805:  lM51AJB:        .res 2  ; $0295
  5806:  lRSSTAT:        .res 1  ; $0297
  5807:  lBITNUM:        .res 1  ; $0298
  5808:  lBAUDOF:        .res 2  ; $0299
  5809:  lRIDBE:         .res 1  ; $029B ; RS232 input buffer at zRIBUF: read pointer
  5810:  lRIDBS:         .res 1  ; $029C ; RS232 input buffer at zRIBUF: write pointer
  5811:  lRODBS:         .res 1  ; $029D ; RS232 output buffer at zROBUF: read pointer
  5812:  lRODBE:         .res 1  ; $029E ; RS232 output buffer at zROBUF: write pointer
  5813:  lIRQTMP:        .res 2  ; $029F
  5814:  
  5815:  .if CompileComputer >= C64_GENERAL
  5816:  
  5817:  lENABL:         .res 1  ; $02A1 ; CIA2 ICR temporary register
  5818:  lTODSNS:        .res 1  ; $02A2
  5819:  lTRDTMP:        .res 1  ; $02A3
  5820:  lTD1IRQ:        .res 1  ; $02A4
  5821:  lTLNIDX:        .res 1  ; $02A5
  5822:  lTVSFLG:        .res 1  ; $02A6
  5823:  
  5824:  .else
  5825:  
  5826:  lTLNIDX         := $00F2
  5827:  
  5828:  .endif
  5829:  
  5830:          .segment "MEM_KERNAL_DATA_0300"
  5831:  
  5832:  lCINV:          .res 2  ; $0314
  5833:  lCNBINV:        .res 2  ; $0316
  5834:  lNMINV:         .res 2  ; $0318
  5835:  lIOPEN:         .res 2  ; $031A
  5836:  lICLOSE:        .res 2  ; $031C
  5837:  lICHKIN:        .res 2  ; $031E
  5838:  lICKOUT:        .res 2  ; $0320
  5839:  lICLRCH:        .res 2  ; $0322
  5840:  lIBASIN:        .res 2  ; $0324
  5841:  lIBSOUT:        .res 2  ; $0326
  5842:  lISTOP:         .res 2  ; $0328
  5843:  lIGETIN:        .res 2  ; $032A
  5844:  lICLALL:        .res 2  ; $032C
  5845:  lUSRCMD:        .res 2  ; $032E
  5846:  lILOAD:         .res 2  ; $0330
  5847:  lISAVE:         .res 2  ; $0332
  5848:  
  5849:                  .res 8  ; $0334 - $033B, unused
  5850:  
  5851:  lTBUFFR_SIZE    := $00C0
  5852:  lTBUFFR:                .res  lTBUFFR_SIZE      ; $033C ; tape buffer. The pointer into this buffer can be found at zBUFPNT.
  5853:  
  5854:  .if CompileComputer >= C64_GENERAL
  5855:  lVIDEORAM       := $0400
  5856:    .if .defined(C64JAPAN)
  5857:  lBASICRAM       := $1000
  5858:    .else
  5859:  lBASICRAM       := $0800
  5860:    .endif
  5861:  .endif
  5862:  
  5863:  lVIDEORAM_SIZE  := $03FF
  5864:  
  5865:  .if CompileComputer = VIC20_02
  5866:  zMEMUSS_2       := zC3PO
  5867:  .else
  5868:  zMEMUSS_2       := zMEMUSS
  5869:  .endif
  5870:  
  5871:  ;       .include "../kernal/fileio_data.inc"
  5872:      .macro LOAD_OVERWRITE_START_ADDRESS
  5873:          txa
  5874:  bne     :+
  5875:          lda     zMEMUSS
  5876:          sta     zEAL
  5877:          lda     zMEMUSS + 1
  5878:          sta     zEAL + 1
  5879:  :
  5880:  
  5881:      .endmacro
  5882:  
  5883:      .macro FILEIO_PATCH_CLOSE_TAPE
  5884:  
  5885:          jsr     TapeWriteCompleteBuffer                 ; write out the tape buffer to tape
  5886:          bcc     FileIoPatch_NoError                     ; C = 0 -> no error -> branch
  5887:  
  5888:          pla                                             ; get back index into table of open files
  5889:          lda     #$00
  5890:  
  5891:      .endmacro
  5892:  
  5893:  ;       .include "../kernal/iec_data.inc"
  5894:  ; after calling IecGetDataClockIn, gets
  5895:  ; - DATA IN in Carry
  5896:  .macro IEC_GET_DATA_INTO_CARRY
  5897:    .if CompileComputer < C64_GENERAL
  5898:          lsr     a
  5899:    .endif
  5900:  .endmacro
  5901:  
  5902:  .macro IEC_REG__DATA_IN_INTO_CARRY
  5903:    .if CompileComputer >= C64_GENERAL
  5904:          asl     a
  5905:    .else
  5906:          lsr     a
  5907:          lsr     a
  5908:    .endif
  5909:  .endmacro
  5910:  
  5911:  .macro IEC_REG__CLOCK_IN_INTO_CARRY
  5912:    .if CompileComputer >= C64_GENERAL
  5913:          .error IEC_REG__CLOCK_IN_INTO_CARRY not defined for C64!
  5914:    .else
  5915:          lsr     a
  5916:    .endif
  5917:  .endmacro
  5918:  
  5919:          .segment "INIT"
  5920:          .byte   VERSION_E4AC
  5921:  
  5922:  .if CompileComputer >= C64_02
  5923:  
  5924:  LE4AD:  pha
  5925:          jsr     kCHKOUT
  5926:          tax
  5927:          pla
  5928:          bcc     LE4B6
  5929:          txa
  5930:  LE4B6:  rts
  5931:  
  5932:  .endif
  5933:  
  5934:  .if CompileComputer = C64_4064
  5935:  ;       FillUntil KERNAL_START + $04C8
  5936:          .segment "KERNALPATCH_4064"
  5937:  
  5938:  LE4C8:  bit     lCOLOR
  5939:          bmi     LE4D7
  5940:          lda     #COL_BLACK
  5941:          ldx     #(VICII_O_Spr7Col - VICII_O_BorderCol)
  5942:  LE4D1:  sta     VIC + VICII_O_BorderCol,x
  5943:          dex
  5944:          bpl     LE4D1
  5945:  LE4D7:  jmp     iSCNKEY
  5946:  
  5947:  .elseif CompileComputer >= C64_03
  5948:  
  5949:    .ifdef JIFFY
  5950:  JDLE4B7:
  5951:          jsr     LE453
  5952:          lda     #<$F672
  5953:          sta     zCMPO
  5954:          lda     #>$F672
  5955:          sta     zCMPO + 1
  5956:  
  5957:  JDLE4C2:
  5958:          inx
  5959:          stx     zPRTY
  5960:          rts
  5961:  
  5962:  JDLE4C6:
  5963:          lda     #$6F
  5964:          jsr     $F0E4
  5965:          jsr     kCHRIN
  5966:          cmp     #$35
  5967:          rts
  5968:    .endif
  5969:  
  5970:  ;       FillUntil KERNAL_START + $04D3,BASIC_FILLER
  5971:          .segment "KERNALPATCH_03"
  5972:  
  5973:  LE4D3:  sta     zRINONE
  5974:          lda     #$01
  5975:          sta     zRIPRTY
  5976:          rts
  5977:  .endif
  5978:  
  5979:  .if CompileComputer >= C64_02
  5980:  
  5981:  ;       FillUntil KERNAL_START + $04DA
  5982:          .segment "KERNALPATCH_02"
  5983:  
  5984:  Patch_StoreColor:
  5985:    .if CompileComputer >= C64_03 .AND CompileComputer <> C64_4064
  5986:          ; TODO: Generic define
  5987:          lda     lCOLOR
  5988:    .else
  5989:          lda     VIC + VICII_O_BackgCol0
  5990:    .endif
  5991:          sta     (zUSER),y
  5992:          rts
  5993:  
  5994:  ; Introduce a delay when the TAPE outputs a "FOUND <filename>" message
  5995:  ; We either wait for a timeout to happen,
  5996:  ; or for the user to press a key
  5997:  ;
  5998:  ; Input: A = zTIME + 1 (timer middle byte)
  5999:  ;
  6000:  ; Bugs:
  6001:  ; - In the case when the timer wraps around (after 24h), the middle byte
  6002:  ;   can be $18 or $19, and the end of timeout is calculated as $1A or $1B.
  6003:  ;   But: $1A or $1B is not reached before the wrap-around and the middle byte
  6004:  ;   going to $1A or $1B again.
  6005:  ;   This will result in a timeout of almost 2 minutes.
  6006:  ;
  6007:  TapeKeyOrTimeout:
  6008:          adc     #2                      ; add 2 to the middle byte, resulting in a timeout of
  6009:                                          ; not more than $0200 * 1/60th seconds
  6010:                                          ; ("not more" because we do not care about the lower byte)
  6011:  @Loop:
  6012:          ldy     zSTKEY                  ; get the status of the keyboard column at the time the keyboard was checked the last time
  6013:  
  6014:          iny                             ; key pressed?
  6015:          bne     @Ret                    ; yes -> branch, end this loop
  6016:  
  6017:          cmp     zTIME + 1               ; compare the timer middle byte with the calculated end of the timeout
  6018:          bne     @Loop                   ; timeout not yet reached -> spin more
  6019:  @Ret:
  6020:          rts
  6021:          ; ------------------------
  6022:  
  6023:  LE4EC:
  6024:          .word   $2619
  6025:          .word   $1944
  6026:          .word   $111A
  6027:          .word   $0DE8
  6028:          .word   $0C70
  6029:          .word   $0606
  6030:          .word   $02D1
  6031:          .word   $0137
  6032:          .word   $00AE
  6033:          .word   $0069
  6034:  .endif
  6035:  
  6036:  ;       FillUntil KERNAL_START + $0500
  6037:          .segment "KERNAL"
  6038:  
  6039:  ;       .include "../kernal/editor.a65"
  6040:  ;  B-12. Function Name: IOBASE
  6041:  ;
  6042:  ;    Purpose: Define I/O memory page
  6043:  ;    Call address: $FFF3 (hex) 65523 (decimal)
  6044:  ;    Communication registers: X, Y
  6045:  ;    Preparatory routines: None
  6046:  ;    Error returns:
  6047:  ;    Stack requirements: 2
  6048:  ;    Registers affected: X, Y
  6049:  ;
  6050:  ;
  6051:  ;    Description: This routine sets the X and Y registers to the address of
  6052:  ;  the memory section where the memory mapped 110 devices are located. This
  6053:  ;  address can then be used with an offset to access the memory mapped I/O
  6054:  ;  devices in the Commodore 64. The offset is the number of locations from
  6055:  ;  the beginning of the page on which the I/O register you want is located.
  6056:  ;  The X register contains the low order address byte, while the Y register
  6057:  ;  contains the high order address byte.
  6058:  ;    This routine exists to provide compatibility between the Commodore 64,
  6059:  ;  VIC-20, and future models of the Commodore 64. If the J/0 locations for
  6060:  ;  a machine language program are set by a call to this routine, they should
  6061:  ;  still remain compatible with future versions of the Commodore 64, the
  6062:  ;  KERNAL and BASIC.
  6063:  ;
  6064:  ;
  6065:  ;  How to Use:
  6066:  ;
  6067:  ;    1) Call this routine by using the JSR instruction.
  6068:  ;    2) Store the X and the Y registers in consecutive locations.
  6069:  ;    3) Load the Y register with the offset.
  6070:  ;    4) Access that I/O location.
  6071:  ;
  6072:  ;  EXAMPLE:
  6073:  ;
  6074:  ;    ;SET THE DATA DIRECTION REGISTER OF THE USER PORT TO 0 (INPUT)
  6075:  ;    JSR IOBASE
  6076:  ;    STX POINT       ;SET BASE REGISTERS
  6077:  ;    STY POINT+1
  6078:  ;    LDY #2
  6079:  ;    LDA #0          ;OFFSET FOR DDR OF THE USER PORT
  6080:  ;    STA (POINT),Y   ;SET DDR TO 0
  6081:  ;
  6082:  ;
  6083:  iIOBASE:
  6084:          ; return IO base address in x/y
  6085:          ; On the VIC-20 and C64, this is interpreted as
  6086:          ; the base address of the first VIA/CIA.
  6087:  
  6088:          ldx     #<IOBASE
  6089:          ldy     #>IOBASE
  6090:          rts
  6091:  
  6092:  ;  B-26. Function Name: SCREEN
  6093:  ;
  6094:  ;    Purpose: Return screen format
  6095:  ;    Call address: $FFED (hex) 65517 (decimal)
  6096:  ;    Communication registers: X, Y
  6097:  ;    Preparatory routines: None
  6098:  ;    Stack requirements: 2
  6099:  ;    Registers affected: X, Y
  6100:  ;
  6101:  ;    Description: This routine returns the format of the screen, e.g., 40
  6102:  ;  columns in X and 25 lines in Y. The routine can be used to determine what
  6103:  ;  machine a program is running on. This function has been implemented on
  6104:  ;  the Commodore 64 to help upward compatibility of your programs.
  6105:  ;
  6106:  ;
  6107:  ;
  6108:  ;
  6109:  ;  How to Use:
  6110:  ;
  6111:  ;    1) Call this routine.
  6112:  ;
  6113:  ;  EXAMPLE:
  6114:  ;
  6115:  ;    JSR SCREEN
  6116:  ;    STX MAXCOL
  6117:  ;    STY MAXROW
  6118:  ;
  6119:  ;
  6120:  iSCREEN:
  6121:          ; return screen resolution in x / y
  6122:  
  6123:          ldx     #EDITOR_COLS
  6124:          ldy     #EDITOR_ROWS
  6125:          rts
  6126:  
  6127:  ;  B-19. Function Name: PLOT
  6128:  ;
  6129:  ;    Purpose: Set cursor location
  6130:  ;    Call address: $FFF0 (hex) 65520 (decimal)
  6131:  ;    Communication registers: A, X, Y
  6132:  ;    Preparatory routines: None
  6133:  ;    Error returns: None
  6134:  ;    Stack requirements: 2
  6135:  ;    Registers affected: A, X, Y
  6136:  ;
  6137:  ;    Description: A call to this routine with the accumulator carry flag
  6138:  ;  set loads the current position of the cursor on the screen (in X,Y
  6139:  ;  coordinates) into the Y and X registers. Y is the column number of the
  6140:  ;  cursor location (0-39), and X is the row number of the location of the
  6141:  ;  cursor (0-24). A call with the carry bit clear moves the cursor to X,Y
  6142:  ;  as determined by the Y and X registers.
  6143:  ;
  6144:  ;  How to Use:
  6145:  ;
  6146:  ;
  6147:  ;  READING CURSOR LOCATION
  6148:  ;
  6149:  ;    1) Set the carry flag.
  6150:  ;    2) Call this routine.
  6151:  ;    3) Get the X and Y position from the Y and X registers, respectively.
  6152:  ;
  6153:  ;
  6154:  ;  SETTING CURSOR LOCATION
  6155:  ;
  6156:  ;    1) Clear carry flag.
  6157:  ;    2) Set the Y and X registers to the desired cursor location.
  6158:  ;    3) Call this routine.
  6159:  ;
  6160:  ;
  6161:  ;  EXAMPLE:
  6162:  ;
  6163:  ;    ;MOVE THE CURSOR TO ROW 10, COLUMN 5 (5,10)
  6164:  ;    LDX #10
  6165:  ;    LDY #5
  6166:  ;    CLC
  6167:  ;    JSR PLOT
  6168:  ;
  6169:  ;
  6170:  iPLOT:
  6171:          bcs     iPLOTReadOnly                   ; carry set -> read values
  6172:  
  6173:  JDLE50C:
  6174:          stx     zTBLX                           ; save new cursor pos: y position from X
  6175:          sty     zPNTR                           ; save new cursor pos: x position from Y
  6176:  
  6177:          jsr     SET_CURSORPOS                   ; update all other internal states to the new position
  6178:  
  6179:  iPLOTReadOnly:
  6180:          ldx     zTBLX                           ; get cursor position in x and y
  6181:          ldy     zPNTR
  6182:  
  6183:          rts
  6184:  
  6185:  ;  B-7. Function Name: CINT
  6186:  ;
  6187:  ;    Purpose: Initialize screen editor & 6567 video chip
  6188:  ;    Call address: $FF81 (hex) 65409 (decimal)
  6189:  ;    Communication registers: None
  6190:  ;    Preparatory routines: None
  6191:  ;    Error returns: None
  6192:  ;    Stack requirements: 4
  6193:  ;    Registers affected: A, X, Y
  6194:  ;
  6195:  ;
  6196:  ;    Description: This routine sets up the 6567 video controller chip in the
  6197:  ;  Commodore 64 for normal operation. The KERNAL screen editor is also
  6198:  ;  initialized. This routine should be called by a Commodore 64 program
  6199:  ;  cartridge.
  6200:  ;
  6201:  ;  How to Use:
  6202:  ;
  6203:  ;    1) Call this routine.
  6204:  ;
  6205:  ;  EXAMPLE:
  6206:  ;
  6207:  ;    JSR CINT
  6208:  ;    JMP RUN       ;BEGIN EXECUTION
  6209:  ;
  6210:  ;
  6211:  iCINT:  jsr     CLRCHN_AND_VIC_DEFAULTS
  6212:  
  6213:  .if CompileComputer < C64_GENERAL
  6214:  
  6215:          ; adjust the VIC-I to take the screen memory from the memory
  6216:          ; area that is configured in lHIBASE.
  6217:  
  6218:          ; on the VIC-I,
  6219:          ; bits 13-10 of the video RAM address is stored in VICI_O_MemoryLocations.7-VICI_O_MemoryLocations.4,
  6220:          ; and bit 9 of the video RAM address is stored in VIC_02.7.
  6221:  
  6222:          ; Now, bit 13 of the VIC-I is connected to the INVERSE of A15 of the 6502.
  6223:          ; Thus, the VIC-I sees another memory map than the 6502:
  6224:          ;
  6225:          ; VIC-I       <-> 6502
  6226:          ; $0000-$1FFF <-> $8000-$9FFF
  6227:          ; $2000-$3FFF <-> $0000-$1FFF (*)
  6228:          ;
  6229:          ; (*) Note that the VIC-I cannot see $0400-$0FFF of the 6502 memory map
  6230:          ;     ($2400-$2FFF in the VIC-I memory map) due to the way the memory
  6231:          ;     is connected on the external RAM cartridge
  6232:  
  6233:  
  6234:          lda     lHIBASE                 ; get high byte of video RAM address
  6235:          and     #~$02                   ; mask out bit 9 (bit 8-0 of the base address
  6236:                                          ; must be 0, anyway)
  6237:  
  6238:          asl     a                       ; shift the address to the right position
  6239:          asl     a
  6240:  
  6241:          ; here, A.7 - A.4 contain the address of the video RAM start, as needed in VICI_O_MemoryLocations
  6242:  
  6243:          ora     #$80                    ; b13 of the VIC-I is connected to the INVERSE of A15
  6244:                                          ; of the 6502 (cf. comment above).
  6245:                                          ; Take this into account and make the  VIC-I see
  6246:                                          ; the 6502 memory area $0000-$1FFF.
  6247:  
  6248:          sta     VIC + VICI_O_MemoryLocations    ; store b
  6249:  
  6250:          lda     lHIBASE                 ; get back the high byte of the video RAM address
  6251:          and     #$02                    ; is bit 9 set?
  6252:          beq     @NoSetBit9              ; no, branch -> do not set VICI_O_VideoColumns.7
  6253:                                          ; (it has been already reset in CLRCHN_AND_VIC_DEFAULTS)
  6254:  
  6255:          lda     #VICI_B_VideoColumns_ScreenMemoryB9     ; set bit 9 of video RAM address
  6256:          ora     VIC + VICI_O_VideoColumns               ; in VICI_O_02.7
  6257:          sta     VIC + VICI_O_VideoColumns
  6258:  
  6259:  @NoSetBit9:
  6260:  
  6261:  .endif
  6262:  
  6263:          lda     #$00                    ; set editor mode
  6264:          sta     lMODE
  6265:  
  6266:          sta     zBLNON                  ; blink mode: Currently, the cursor is not on
  6267:  
  6268:          lda     #<CHECK_SHIFT_CTRL_CBM
  6269:          sta     lKEYLOG
  6270:          lda     #>CHECK_SHIFT_CTRL_CBM
  6271:          sta     lKEYLOG + 1
  6272:  
  6273:          lda     #10
  6274:          sta     lXMAX                   ; maximum number of characters in the keyboard buffer is 10
  6275:          sta     lDELAY                  ; set delay for delay of the start of key repetition to default (10)
  6276:  
  6277:          lda     #DEFAULT_COLOR          ; set default color
  6278:          sta     lCOLOR
  6279:  
  6280:          lda     #$04                    ; set delay counter for key repetitions
  6281:          sta     lKOUNT
  6282:  
  6283:          lda     #$0C
  6284:          sta     zBLNCT                  ; set the blink counter
  6285:          sta     zBLNSW                  ; disable cursor
  6286:  
  6287:          ; update the table of low bytes and link bits for the screen row
  6288:  
  6289:  ClearScreen:
  6290:          lda     lHIBASE                 ; get the high byte of the start of the video RAM
  6291:          ora     #$80                    ; set link bit -> this row is not connected to the previous one
  6292:          tay
  6293:          lda     #$00                    ; low byte of the start of the video RAM (A) := 0
  6294:          tax                             ; row counter (X) := 0, start in row zero
  6295:  
  6296:  @Next:  sty     zLDTB1,x                ; store the high byte and the link bit of this line
  6297:  
  6298:          ; proceed to next row by adding the number of columns in one row (EDITOR_COLS)
  6299:  
  6300:          clc
  6301:          adc     #EDITOR_COLS            ; add the number of columns in a line to the low byte
  6302:          bcc     @NoHighByte             ; no carry -> we do not need to increment the high byte
  6303:          iny                             ; increment the high byte
  6304:  
  6305:  @NoHighByte:
  6306:          inx                             ; increment row counter
  6307:          cpx     #EDITOR_ROWS + 1        ; did we reach the last row?
  6308:          bne     @Next                   ; not yet, store the next high byte and link bit
  6309:  
  6310:          lda     #$FF                    ; write the "end marker"
  6311:          sta     zLDTB1,x                ; into the location for the row past the last one
  6312:  
  6313:          ; Erase the screen rows (overwrite with spaces)
  6314:  
  6315:          ldx     #EDITOR_ROWS - 1        ; start in the last row
  6316:  @NextLine:
  6317:          jsr     EraseScreenRow          ; erase the row
  6318:          dex                             ; go to previous line
  6319:          bpl     @NextLine               ; not all rows are processed, branch -> process previous one
  6320:  
  6321:  CURSOR_HOME:
  6322:          ; set cursor position to 0/0
  6323:  
  6324:          ldy     #0
  6325:          sty     zPNTR                   ; column
  6326:          sty     zTBLX                   ; row
  6327:  
  6328:  SET_CURSORPOS:
  6329:  
  6330:          ; this routine updates the internal pointer to conform to the cursor
  6331:          ; position set in zPNTR/zTBLX. As this function is used from other
  6332:          ; places, for example from iPLOT, it is completely implemented, and it
  6333:          ; does not use any hard-coded constants for CURSOR_HOME only.
  6334:  
  6335:          ldx     zTBLX                   ; get row into X
  6336:          lda     zPNTR                   ; get column into A
  6337:  
  6338:  @AddLine:
  6339:          ldy     zLDTB1,x                ; is this row combined with the previous one?
  6340:          bmi     @StandaloneLine         ; no, branch
  6341:  
  6342:          ; otherwise, add the number of columns to the col position
  6343:          clc
  6344:          adc     #EDITOR_COLS
  6345:          sta     zPNTR                   ; store (updated) column position
  6346:          dex                             ; ... and the row is one less
  6347:          bpl     @AddLine                ; unconditional jump (row 0 should never be combined with the previous row!)
  6348:          ; --------------
  6349:  
  6350:  @StandaloneLine:
  6351:  
  6352:  .if CompileComputer >= C64_03 .or .defined(C64JAPAN)
  6353:          jsr     CalculateScreenPointerFromRowNumber                     ; This is essentially the same as the VIC20 (and C64-02 and earlier) implementation. Only the order in which high and low byte are calculated is changed.
  6354:                                          ; This subroutine is used to gain memory for the later patch
  6355:  .else
  6356:          lda     zLDTB1,x                ; get high byte of the starting address of this row
  6357:          and     #>lVIDEORAM_SIZE        ; mask out additional bits used as flags
  6358:          ora     lHIBASE                 ; add the video RAM base
  6359:          sta     zPNT + 1                ; remember high byte
  6360:  
  6361:          lda     SCREEN_LOWBYTE,x        ; get low byte of the starting address of this row
  6362:          sta     zPNT                    ; remember low byte
  6363:  
  6364:  .endif
  6365:  
  6366:          ; calculate the number of columns (more precisely: The last column number)
  6367:          ; in this logical line
  6368:  
  6369:          lda     #EDITOR_COLS - 1        ; start with one physical line
  6370:  
  6371:          inx                             ; Here, X points to the first line *before* the extended long line. Thus, go back into the long line area
  6372:  
  6373:  @Loop:  ldy     zLDTB1,x                ; is this line combined with the previous one?
  6374:          bmi     @StoreLineLength        ; no, branch -> quit loop
  6375:  
  6376:          clc                             ; add a complete line length
  6377:          adc     #EDITOR_COLS
  6378:  
  6379:          inx                             ; proceed to the next line
  6380:          bpl     @Loop                   ; (unconditional branch)
  6381:          ; -----------------------------
  6382:  
  6383:  @StoreLineLength:
  6384:          sta     zLNMX                   ; store line length
  6385:  
  6386:  .if CompileComputer >= C64_03 .or .defined(C64JAPAN)
  6387:          ; this fixes a bug in the C64 ROMs:
  6388:          ; If the last row is combined to build a long line (80 chars),
  6389:          ; and the last character is deleted afterwards with backspace,
  6390:          ; the C64 will start a LOAD command and will not react
  6391:          ; anymore unless there is an attached tape recorder.
  6392:  
  6393:          ; This patch fixes this:
  6394:  
  6395:          jmp     UpdateColorRAMPointerToVideoramPointer  ; also update the color RAM pointer (zUSER)
  6396:  
  6397:          ; this is another patch on the C64-03 ROMs:
  6398:          ; TODO: why?
  6399:          ;
  6400:          ; It is called after LDX zTBLX (get current cursor row)
  6401:  
  6402:  Patch_CursorOneRowUp:
  6403:          cpx     zLXSP                                   ; did the cursor row change while we were in the routine?
  6404:          beq     @Ret                                    ; no -> branch, we're done
  6405:          jmp     CursorOneRowUp
  6406:  @Ret:   rts
  6407:  
  6408:          nop
  6409:  
  6410:  .else
  6411:          rts
  6412:  .endif
  6413:  
  6414:  
  6415:          ; unused in VIC20 and C64 ROM!
  6416:  
  6417:          jsr     CLRCHN_AND_VIC_DEFAULTS
  6418:          jmp     CURSOR_HOME
  6419:  
  6420:  
  6421:  CLRCHN_AND_VIC_DEFAULTS:
  6422:          ; This routine restores input and output to the terminal
  6423:          ; (screen and keyboard).
  6424:          ; Afterwards, it initialises the VIC (or VIC-II) registers
  6425:  
  6426:          lda     #FILE_SCREEN                    ; default output to screen
  6427:          sta     zDFLTO
  6428:          lda     #FILE_KEYBOARD                  ; default input to keyboard
  6429:          sta     zDFLTN
  6430:  
  6431:  SET_VIC_DEFAULTS:
  6432:  
  6433:          ; This routine initialises the VIC (or VIC-II) registers
  6434:  
  6435:          ; Loop throught the table and overwrite the VIC (-II) registers
  6436:          ; with the table contents
  6437:  
  6438:          ldx     #END_VIC_DEFAULTS - VIC_DEFAULTS + 1    ; number of register values in the table
  6439:  @Loop:  lda     VIC_DEFAULTS - 1,x
  6440:          sta     VIC - 1,x
  6441:          dex
  6442:          bne     @Loop
  6443:          rts
  6444:  
  6445:  GETIN_KEYB:
  6446:  
  6447:          ; Get a character from the keyboard buffer
  6448:          ; this function returns a character from the keyboard buffer
  6449:          ; It also deletes it from there.
  6450:          ;
  6451:          ; Prerequisites:
  6452:          ;
  6453:          ; - Before calling this function, the I flag must be set (SEI)
  6454:          ;   It will be cleared on exit
  6455:          ;
  6456:          ; - Make sure the keyboard buffer is not empty before calling this function!
  6457:  
  6458:          ldy     lKEYD                                   ; remember first key press in the keyboard buffer
  6459:  
  6460:          ; move all key presses in the keyboard buffer one step to the front
  6461:  
  6462:          ldx     #0
  6463:  @Loop:  lda     lKEYD + 1,x                             ; move entry one step ahead
  6464:          sta     lKEYD,x
  6465:          inx                                             ; proceed to next one
  6466:          cpx     zNDX                                    ; did we already process all keys?
  6467:          bne     @Loop                                   ; no, branch -> process the next key
  6468:  
  6469:          dec     zNDX                                    ; we just removed and key, thus, decrement the number of keys in the buffer
  6470:  
  6471:          tya                                             ; get back the first key press in the keyboard buffer
  6472:  
  6473:          cli
  6474:          clc                                             ; quit with success
  6475:          rts
  6476:  
  6477:  OutputCharacterAndWaitForKeyPress:
  6478:          jsr     CHROUT_SCREEN
  6479:  
  6480:  WaitForKeyPress:
  6481:          lda     zNDX                                    ; number of key presses in keyboard buffer
  6482:          sta     zBLNSW                                  ; if > 0: disable cursor blinking, otherwise: Enable cursor blinking
  6483:          sta     lAUTODN                                 ; If there was some key press, mark that any output that will combine two rows will scroll down the screen contents
  6484:                                                          ; (this loop cannot be quit with lAUTODN = 0)
  6485:          beq     WaitForKeyPress                         ; no key presses -> wait until some key has been pressed
  6486:  
  6487:          ; now that one or more key has been pressed, output it/them
  6488:  
  6489:          ; first, restore the character under the cursor (if the cursor has been visible)
  6490:  
  6491:          sei
  6492:          lda     zBLNON                                  ; cursor currently visible?
  6493:          beq     @CursorNotVisible                       ; no, skip restoring it
  6494:  
  6495:          ; restore character under the cursor
  6496:  
  6497:          lda     zGDBLN                                  ; get character code
  6498:          ldx     lGDCOL                                  ; and color of character under cursor
  6499:  
  6500:          ldy     #0
  6501:          sty     zBLNON                                  ; mark: Cursor is currently invisible
  6502:  
  6503:          jsr     StoreCharacterOnScreenAndDisableBlinking        ; store the character under the cursor on the screen
  6504:  
  6505:  @CursorNotVisible:
  6506:  
  6507:  .ifdef JIFFY
  6508:          jsr     JDLF9E5
  6509:  .else
  6510:          jsr     GETIN_KEYB                              ; get the next character
  6511:  .endif
  6512:          cmp     #KEY_SHIFTRUN                           ; was is Shift + Run/Stop?
  6513:          bne     NoShiftRunStop                          ; no, branch -> jump special processing
  6514:  
  6515:          ; If we reach here, the user pressed Shift + Run/Stop
  6516:          ; Then, store the special text into the keyboard buffer and
  6517:          ; process the characters, one after the other.
  6518:          ;
  6519:          ; Note that any other key presses that might have been
  6520:          ; in the keyboard buffer are removed.
  6521:  
  6522:          ldx     #END_TEXT_SHIFTRUNSTOP - TEXT_SHIFTRUNSTOP
  6523:          sei
  6524:          stx     zNDX                                    ; set the count of characters
  6525:  
  6526:  @ShiftRunStop:
  6527:          lda     TEXT_SHIFTRUNSTOP - 1,x                 ; copy text
  6528:          sta     lKEYD - 1,x                             ; into the keyboard buffer
  6529:          dex
  6530:          bne     @ShiftRunStop                           ; until all characters have been processed
  6531:          beq     WaitForKeyPress                         ; now, process the key presses (uncond. branch)
  6532:          ; -------------------------------
  6533:  
  6534:  NoShiftRunStop:
  6535:          cmp     #ASC_CR                                 ; was the key a CR?
  6536:          bne     OutputCharacterAndWaitForKeyPress       ; no, output the character and wait for the next key press
  6537:  
  6538:          ; When we reach here, the user has entered anything and pressed CR.
  6539:          ; Now, we process the input
  6540:  
  6541:          ldy     zLNMX                                   ; get the (logical) line length of the current line
  6542:          sty     zCRSW                                   ; store it as number of characters to read
  6543:  
  6544:  @CheckSpaceNext:
  6545:          lda     (zPNT),y                                ; read the next character at the end of the line
  6546:          cmp     #' '                                    ; is it a space?
  6547:          bne     @NoSpace                                ; No -> branch,
  6548:          dey                                             ; Yes, it was a space: Test the previous character
  6549:          bne     @CheckSpaceNext                         ; until we have checked all characters in this line, branch
  6550:  
  6551:  @NoSpace:
  6552:          iny
  6553:          sty     zINDX                                   ; remember the number of characters in the current line
  6554:          ldy     #0
  6555:          sty     lAUTODN                                 ; Mark: No key press yet, thus, any output will scroll down the screen contents if some rows will be combined
  6556:          sty     zPNTR                                   ; start reading at the beginning of the line
  6557:          sty     zQTSW                                   ; We are not in quotation mark mode
  6558:          lda     zLXSP                                   ; value of zTBLX before calling BASIN (zTBLX is not changed when calling GETIN
  6559:          bmi     BASIN_KEYB_PROCESS_KEY                  ; TODO what?
  6560:  
  6561:          ldx     zTBLX                                   ; current cursor row on screen
  6562:  
  6563:          ; set the cursor one (virtual) row up
  6564:  
  6565:  .if CompileComputer >= C64_03 .or .defined(C64JAPAN)
  6566:          ; for -03 ROMs, it was decided that this the cursor row is only moved up
  6567:          ; if it has already changed since this function began
  6568:          ; TODO why?
  6569:          ;
  6570:          jsr     Patch_CursorOneRowUp
  6571:  .else
  6572:          jsr     CursorOneRowUp
  6573:  .endif
  6574:  
  6575:          ; here: with X := current row (modified in CursorOneRowUp / Patch_CursorOneRowUp)
  6576:  
  6577:          cpx     zLXSP                                   ; has the cursor row on screen changed?
  6578:          bne     BASIN_KEYB_PROCESS_KEY                  ; yes -> branch, get keyboard input
  6579:  
  6580:  .if CompileComputer < C64_GENERAL
  6581:          bne     BASIN_KEYB_PROCESS_KEY                  ; some superfluous leftover
  6582:  .endif
  6583:  
  6584:          lda     zTEMP_zPNTR                             ; restore current cursor column (zPNTR) from zTEMP_zPNTR
  6585:          sta     zPNTR
  6586:          cmp     zINDX                                   ; did the column change while we were in the routine?
  6587:          bcc     BASIN_KEYB_PROCESS_KEY                  ; we are now to the left of the column at the beginning -> branch, get new key input
  6588:          bcs     BASIN_KEYB_END_LINE                     ; we are at the same column or right from it -> branch, done
  6589:          ; -------------------------
  6590:  
  6591:  BASIN_KEYB:
  6592:  
  6593:          ; remember Y and X on the stack
  6594:  
  6595:          tya
  6596:          pha
  6597:          txa
  6598:          pha
  6599:  
  6600:          lda     zCRSW                                   ; has CR been pressed already?
  6601:                                                          ; that is, are there already keys to
  6602:                                                          ; process on the screen?
  6603:          beq     WaitForKeyPress                         ; No, wait for input of a complete line
  6604:  
  6605:  BASIN_KEYB_PROCESS_KEY:
  6606:          ldy     zPNTR                                   ; get pointer into current line
  6607:          lda     (zPNT),y                                ; get current character at that position
  6608:  
  6609:  .if CompileComputer >= C64_GENERAL
  6610:  .elseif CompileComputer >= VIC20_06
  6611:  
  6612:  ;       FillUntil $E672,$EA
  6613:          FillNOP 23
  6614:  
  6615:  .else
  6616:  
  6617:          ; It seems the VIC20_0▀2 ROM has some kind of "cooked" screen codes.
  6618:          ; This routine converts some characters into others, bypassing the
  6619:          ; screen code to PETSCII conversion later
  6620:  
  6621:          ldx     lMODE                                   ; if lMODE == 0 then we do not use the "cooked" mode
  6622:          beq     @End                                    ; Thus, in  this case, skip the conversion
  6623:  
  6624:          ldx     #SpecialScreenCodeHandleTable_END - SpecialScreenCodeHandleTable - 2
  6625:  @FindChar:
  6626:          cmp     SpecialScreenCodeHandleTable,x          ; is the current character a special one?
  6627:          beq     @FoundCharacter                         ; yes, branch -> convert it
  6628:          dex                                             ; no, proceed to previous special character
  6629:          dex
  6630:          bpl     @FindChar                               ; test the next char
  6631:          bmi     @End                                    ; table has completed -> branch, quit
  6632:          ; ---------------
  6633:  
  6634:  @FoundCharacter:
  6635:          lda     SpecialScreenCodeHandleTable + 1,x      ; convert the screen code to the replacement
  6636:          bne     @ProceedToNextScreenLocation            ; (uncond. branch)
  6637:          ; --------------------------------------
  6638:  
  6639:  @End:
  6640:  
  6641:  .endif
  6642:  
  6643:          ; convert the character (in A) into PETSCII TODO
  6644:          ;
  6645:          ; Here, we convert the codes as follows:
  6646:          ;
  6647:          ; SCREEN CODE -> PETSCII
  6648:          ; $00-$1F     -> $40-$5F
  6649:          ; $20-$3F     -> $20-$3F
  6650:          ; $40-$5F     -> $60-$7F
  6651:          ; TODO ???
  6652:          ;
  6653:  
  6654:          sta     zSCHAR                                  ; store the character
  6655:  
  6656:          and     #$3F                                    ; mask out the upper 2 bits (7, 6)
  6657:          asl     zSCHAR                                  ; put bit 7 into C
  6658:          bit     zSCHAR                                  ; test the remaining part
  6659:  
  6660:          ; now, we have the following status of the flags:
  6661:          ; C = bit 7 of A on input
  6662:          ; N = bit 6 of A on input
  6663:          ; V = bit 5 of A on input
  6664:  
  6665:          bpl     @DoNotSetBit7                           ; N=0 -> bit 6 was 0, that is, we have $00-$3F or $80-$BF
  6666:  
  6667:          ora     #$80                                    ; otherwise, set bit 7
  6668:  
  6669:  @DoNotSetBit7:
  6670:          bcc     @Process0x00_To_0x7F                    ; was bit 7 == 0? --> branch
  6671:  
  6672:          ldx     zQTSW                                   ; Check quotation mark mode
  6673:          bne     @ProceedToNextScreenLocation            ; branch if we are in quotation mark mode
  6674:  
  6675:  @Process0x00_To_0x7F:
  6676:          bvs     @ProceedToNextScreenLocation            ; was bit 5 == 1? --> branch
  6677:          ora     #$40                                    ; otherwise, set bit 6
  6678:  
  6679:          ; here, we converted: (TODO: check again!)
  6680:          ; $00-$1F -> $40-$5F
  6681:          ; $20-$3F -> $20-$3F
  6682:          ; $40-$5F -> $80-$9F
  6683:          ; $60-$7F -> $C0-$DF
  6684:  
  6685:  @ProceedToNextScreenLocation:
  6686:          inc     zPNTR                                   ; proceed to next screen location
  6687:  
  6688:          jsr     CheckQuote                              ; update the quotation mark mode flag
  6689:  
  6690:          cpy     zINDX                                   ; have we reached the end of the line?
  6691:          bne     BASIN_KEYB_QUIT                         ; no, return the current character
  6692:  
  6693:          ; if we reach here, then we have read the complete line
  6694:          ; Thus, clear all states and return the CR as marker for end-of-line
  6695:  
  6696:  BASIN_KEYB_END_LINE:
  6697:          lda     #0
  6698:          sta     zCRSW                                   ; remember: We do not have any characters anymore
  6699:          lda     #ASC_CR                                 ; return a CR Value
  6700:  
  6701:          ldx     zDFLTN
  6702:          cpx     #FILE_SCREEN                            ; default input file = screen?
  6703:          beq     @OutputCharacter                        ; yes, output the CR
  6704:  
  6705:          ldx     zDFLTO
  6706:          cpx     #FILE_SCREEN                            ; default output file = screen?
  6707:          beq     @QuitWithCR                             ; yes, quit
  6708:  
  6709:          ; if we reach here, the input was from the keyboard, and the output was not the screen.
  6710:          ; Thus, output the CR we got from the keyboard
  6711:  
  6712:  @OutputCharacter:
  6713:          jsr     CHROUT_SCREEN                           ; output the character on the screen
  6714:  
  6715:  @QuitWithCR:
  6716:          lda     #ASC_CR                                 ; return a CR value
  6717:  
  6718:  BASIN_KEYB_QUIT:
  6719:          sta     zSCHAR                                  ; remember read char
  6720:  
  6721:          ; restore X and Y from stack
  6722:          pla
  6723:          tax
  6724:          pla
  6725:          tay
  6726:  
  6727:          lda     zSCHAR                                  ; get back remembered read char
  6728:          cmp     #ASC_PI                                 ; is it the PETSCII code for PI?
  6729:          bne     @ClcRts                                 ; no, branch -> we are done
  6730:          lda     #TokPi                                  ; yes, replace it by the BASIC token for PI (TODO why did CBM choose this route?)
  6731:  @ClcRts:
  6732:          clc                                             ; we successfully ended the routine
  6733:          rts
  6734:          ; --------------
  6735:  
  6736:  CheckQuote:
  6737:          cmp     #'"'                                    ; Is the current char a quotation mark?
  6738:          bne     @Rts                                    ; no, quit
  6739:  
  6740:          ; invert the state of the quotation mark
  6741:          lda     zQTSW
  6742:          eor     #$01
  6743:          sta     zQTSW
  6744:  
  6745:          lda     #'"'                                    ; restore the character
  6746:  @Rts:   rts
  6747:  
  6748:  
  6749:  ; @@@@@
  6750:  
  6751:  LE691:  ora     #$40
  6752:  
  6753:  CHROUT_SCREEN_OUTPUT_WITH_TEST_RVS:
  6754:          ldx     zRVS                                    ; Is the flag "output in reverse" set?
  6755:          beq     CHROUT_OUTPUT_SCREEN_IN_NORMAL          ; no -> branch, output in normal
  6756:  
  6757:  CHROUT_SCREEN_OUTPUT_IN_RVS:
  6758:          ora     #$80                                    ; setting bit 7 of the char to output: reverse the char
  6759:  
  6760:  CHROUT_OUTPUT_SCREEN_IN_NORMAL:
  6761:          ldx     zINSRT                                  ; Number of characters to output in "insert mode"
  6762:          beq     @NoInsertMode                           ; none -> we are not in insert mode -> branch
  6763:          dec     zINSRT                                  ; decrement number of characters to output in revers mode
  6764:  
  6765:  @NoInsertMode:
  6766:          ldx     lCOLOR                                  ; get the current color
  6767:          jsr     StoreCharacterOnScreenAndDisableBlinking        ; output character in A, color in X
  6768:          jsr     MoveCursorRightAfterOutput              ; move the cursor to the next output position
  6769:  
  6770:  CHROUT_SCREEN_END:
  6771:          pla                                             ; restore Y from stack
  6772:          tay
  6773:  
  6774:          lda     zINSRT                                  ; insert mode?
  6775:          beq     @DontStopQuotationMode                  ; no, branch
  6776:          lsr     zQTSW                                   ; end quotation mark mode
  6777:  @DontStopQuotationMode:
  6778:          pla                                             ; restore X from stack
  6779:          tax
  6780:  
  6781:          pla                                             ; restore A from stack
  6782:          clc                                             ; we ended successfully
  6783:          cli
  6784:          rts
  6785:          ; --------------
  6786:  
  6787:  MoveCursorRightAfterOutput:
  6788:          jsr     AdjustCursorRowBeforeMovingRight        ; if we will move to the next row, increment row number
  6789:          inc     zPNTR                                   ; increment column into current row -> move cursor to the right
  6790:          lda     zLNMX                                   ; get number of column in current row
  6791:          cmp     zPNTR                                   ; did we go past the last column?
  6792:          bcs     EditorRts                               ; no -> branch, we do not need to adjust column
  6793:          cmp     #(EDITOR_MAX_COMBINED_ROWS * EDITOR_COLS) - 1   ; did we reach the maximum length of a virtual row?
  6794:          beq     SetCursorToTheBeginningOfTheNextLine    ; yes -> branch, set cursor to the beginning of the next line
  6795:  
  6796:          lda     lAUTODN                                 ; do we have to scroll down the screen contents?
  6797:          beq     @CombineRows                            ; no, skip the scrolling
  6798:          jmp     LE967                                   ; (will return to LogicallyCombineTwoRows)
  6799:          ; ------------------
  6800:  
  6801:  @CombineRows:
  6802:          ldx     zTBLX
  6803:          cpx     #EDITOR_ROWS
  6804:          bcc     LogicallyCombineTwoRows
  6805:          jsr     LE8EA
  6806:          dec     zTBLX
  6807:          ldx     zTBLX
  6808:  
  6809:  LogicallyCombineTwoRows:
  6810:          asl     zLDTB1,x                                ; clear bit 7 -> combine this phyiscal row with the previous one
  6811:          lsr     zLDTB1,x
  6812:  
  6813:    .macro EDITOR_PATCH_LogicallyCombineTwoRows_FIX
  6814:  
  6815:          ; only present on VIC20-06 ROMs and above, and C64 ROMs.
  6816:  
  6817:          ; mark the next row as being stand-alone
  6818:  
  6819:          ; TODO what exactly does this patch fix?
  6820:  
  6821:          inx                                             ; go to the next row
  6822:          lda     zLDTB1,x
  6823:          ora     #$80                                    ; set bit 7 --> this row is not combined with the previous one
  6824:          sta     zLDTB1,x
  6825:          dex                                             ; go back to the previous row
  6826:    .endmacro
  6827:  
  6828:    .macro EDITOR_PATCH_LogicallyCombineTwoRows_COMMON
  6829:          ; from here on, this is done for all variants, including the VIC20-2
  6830:  
  6831:          lda     zLNMX                                   ; maximum number of columns on the current (virtual) row
  6832:          clc
  6833:    .endmacro
  6834:  
  6835:          ; depending on the firmware built,
  6836:  .if CompileComputer >= C64_GENERAL
  6837:          EDITOR_PATCH_LogicallyCombineTwoRows_FIX
  6838:          EDITOR_PATCH_LogicallyCombineTwoRows_COMMON
  6839:  .elseif CompileComputer >= VIC20_06
  6840:          ; on the VIC20-06 and -07, this patch is really a patch.
  6841:          ; We come back with a JMP
  6842:          jmp     EditorPatchLogicallyCombineTwoRows
  6843:  EditorPatchLogicallyCombineTwoRows_Return:
  6844:  
  6845:  .else
  6846:          ; old implementation for VIC20-02
  6847:          EDITOR_PATCH_LogicallyCombineTwoRows_COMMON
  6848:  .endif
  6849:  
  6850:          adc     #EDITOR_COLS                            ; add the number of column of one (physical) row
  6851:          sta     zLNMX                                   ; and set it as the new maximum number of columns on the current (virtual) row
  6852:  
  6853:  CursorOneRowUp:
  6854:          ; input: X := Cursor row
  6855:          ;
  6856:          ; set the cursor row to point to the (virtual) row above us.
  6857:  
  6858:          lda     zLDTB1,x                                        ; is the current row combined with the previous one?
  6859:          bmi     @NotCombined                                    ; no, we're done
  6860:          dex                                                     ; cursor on (physical) row up
  6861:          bne     CursorOneRowUp                                  ; not 0 -> not at top of screen -> branch, test the next (physical) row
  6862:  
  6863:  @NotCombined:
  6864:          jmp     CalculateScreenPointerFromRowNumber             ; adjust screen pointer
  6865:          ; -----------------------------------------
  6866:  
  6867:  SetCursorToTheBeginningOfTheNextLine:
  6868:          dec     zTBLX                                           ; go up one row (will be undone in the next routine)
  6869:          jsr     GoDownOneVirtualRow                             ; go down one (virtual) row
  6870:          lda     #0
  6871:          sta     zPNTR                                           ; set column to the beginning of the row
  6872:  EditorRts:
  6873:          rts
  6874:          ; -----------------------------------------
  6875:  
  6876:  
  6877:  ; Perform the wrap-around to the previous row of
  6878:  ; INS/DEL or CRSR LEFT is pressed on the leftmost column.
  6879:  ;
  6880:  ; If the cursor is not at the home position, it
  6881:  ; puts the cursor one row to the top, and on the last
  6882:  ; column if that row.
  6883:  ;
  6884:  ; NOTE:
  6885:  ; If the cursor is already at the home position,
  6886:  ; this function removes the return address from the stack!
  6887:  ; Instead, it jumps to CHROUT_SCREEN_END.
  6888:  ;
  6889:  CHROUT_SCREEN_WrapAroundToPreviousRow:
  6890:          ldx     zTBLX                                   ; get row of current cursor position
  6891:          bne     @CanGoBack                                      ; not zero -> branch
  6892:  
  6893:          ; if we reach here, then we are already on the first ("0th") row, and we are in the first ("0th") column (as we were called in the first place).
  6894:          ; Thus, we do not have an option to go more to the left.
  6895:  
  6896:          stx     zPNTR                                   ; set column to 0 (TODO: should not be necessary, as it is already set to 0!)
  6897:  
  6898:          ; Remove the return address from the stack:
  6899:          ; we do not want to return to the caller;
  6900:          ; instead, we will abort the output!
  6901:          ;
  6902:          pla
  6903:          pla
  6904:  
  6905:          bne     CHROUT_SCREEN_END                       ; end the output (uncond. branch as long as the caller of the caller does not reside on the memory area $00xx.)
  6906:          ; -----------------------
  6907:  
  6908:  @CanGoBack:
  6909:          dex
  6910:          stx     zTBLX                                   ; set the cursor one row to the top
  6911:  
  6912:          jsr     SET_CURSORPOS                           ; set the cursor position (and calculate the line length of the current line, in zLNMX)
  6913:  
  6914:          ; set the cursor to the last column of the line
  6915:          ldy     zLNMX                                   ; get current (virtual) line length
  6916:          sty     zPNTR                                   ; and set the cursor to that column
  6917:          rts
  6918:  
  6919:  ; CHROUT onto screen
  6920:  ;
  6921:  ; Output the character in A to the current cursor position on the screen
  6922:  ;
  6923:  CHROUT_SCREEN:
  6924:          pha                                             ; remember the character to output on stack
  6925:          sta     zSCHAR                                  ; and in memory
  6926:  
  6927:          ; remember X and Y on the stack
  6928:          txa
  6929:          pha
  6930:          tya
  6931:          pha
  6932:  
  6933:          lda     #$00                                    ; no CR has been pressed yet
  6934:          sta     zCRSW                                   ; That is, on next BASIN, the routine will wait for an input again, regardless if the input has been completely used yet.
  6935:  
  6936:          ldy     zPNTR                                   ; get pointer into current (logical) line
  6937:          lda     zSCHAR                                  ; character to be output
  6938:          bpl     @PositiveChar                           ; is it positive (<= $7F) -> branch
  6939:          jmp     @NegativeChar
  6940:          ; ------------
  6941:  
  6942:  @PositiveChar:
  6943:          cmp     #ASC_CR                                 ; is the character a CR?
  6944:          bne     @NoCR                                   ; No -> branch, next test
  6945:          jmp     CHROUT_SCREEN_CR                        ; Output a CR
  6946:  
  6947:  @NoCR:
  6948:          ; Here, we convert the codes as follows:
  6949:          ;
  6950:          ; PETSCII -> SCREEN CODE
  6951:          ; $20-$3F -> $20-$3F
  6952:          ; $40-$5F -> $00-$1F
  6953:          ; $60-$7F -> $40-$5F
  6954:  
  6955:          cmp     #$20                                    ; is the character a control code (< $20)?
  6956:          bcc     @TestControlCode                        ; yes, process the control code
  6957:  
  6958:          cmp     #$60                                    ; is the character small than $60 (i.e., $20..$5F)?
  6959:          bcc     @Convert0x20_0x60                       ; yes, branch -> convert char
  6960:          and     #~$20                                   ; convert $60-$7F --> $40-$5F
  6961:          bne     @CheckQuoteAndOutput                    ; (uncond. branch)
  6962:          ; -----------------
  6963:  
  6964:  @Convert0x20_0x60:
  6965:          and     #$3F                                    ; converts $20-$3F --> $20-$3F, but $40-$5F -> $00-$1F
  6966:  
  6967:  @CheckQuoteAndOutput:
  6968:          jsr     CheckQuote                              ; update quote state, if necessary
  6969:          jmp     CHROUT_SCREEN_OUTPUT_WITH_TEST_RVS
  6970:          ; -----------------
  6971:  
  6972:  @TestControlCode:
  6973:          ldx     zINSRT                                  ; are we in insert mode?
  6974:          beq     @ProcessControlCode                     ; no, branch -> process control codes
  6975:          jmp     CHROUT_SCREEN_OUTPUT_IN_RVS             ; output the control codes in reverse (and quit), do not process them
  6976:          ; -----------------
  6977:  
  6978:  @ProcessControlCode:
  6979:          cmp     #ASC_INSDEL                             ; is the character an INS/DEL?
  6980:          bne     @NoINSDEL                               ; no -> branch, skip special handling of INS/DEL
  6981:  
  6982:          tya                                             ; A := Y (zPNTR), offset of current column into current screen line
  6983:          bne     @NotFirstColumn                         ; not the first column -> branch
  6984:  
  6985:          jsr     CHROUT_SCREEN_WrapAroundToPreviousRow   ; Perform the wrap around to the previous row, putting the cursor on the rightmost column of the previous line.
  6986:                                                          ; If we are at the home position already, this function does NOT return, but goes to CHROUT_SCREEN_END instead.
  6987:          jmp     @AddBlankAtCurrentPosition
  6988:          ; -----------------
  6989:  
  6990:  @NotFirstColumn:
  6991:          jsr     AdjustCursorRowBeforeMovingLeft         ; we want to move the cursor to the left. If we will cross a row this way, decrement the row number.
  6992:  
  6993:          ; move cursor one to the left
  6994:  
  6995:          dey
  6996:          sty     zPNTR
  6997:          jsr     UpdateColorRAMPointerToVideoramPointer  ; update color RAM pointer
  6998:  
  6999:          ; move the screen parts to the right of the cursor one to the left
  7000:  
  7001:  @MoveLoop:
  7002:          iny                                             ; get the char to the right
  7003:          lda     (zPNT),y
  7004:          dey                                             ; and copy it one to the left
  7005:          sta     (zPNT),y
  7006:  
  7007:          iny                                             ; get the color to the right
  7008:          lda     (zUSER),y
  7009:          dey                                             ; and copy it one to the left
  7010:          sta     (zUSER),y
  7011:  
  7012:          iny                                             ; proceed to the next position (to the right)
  7013:          cpy     zLNMX                                   ; did we reach the end of the (logical) line?
  7014:          bne     @MoveLoop                               ; no, move the next char
  7015:  
  7016:          ; if we "fall through", then Y points to the last location on the current (logical) screen line
  7017:  
  7018:  @AddBlankAtCurrentPosition:
  7019:          lda     #' '                                    ; put a space char (blank)
  7020:          sta     (zPNT),y                                ; into the current screen location
  7021:          lda     lCOLOR                                  ; put the default color
  7022:          sta     (zUSER),y                               ; into the current color location
  7023:          bpl     @End2                                   ; BUG: This is meant as an uncond. branch. It is one as long as no-one has the idea to put a negative color into lCOLOR!
  7024:          ; ------------------
  7025:  
  7026:  @NoINSDEL:
  7027:          ldx     zQTSW                                   ; are we in quotation mark mode?
  7028:          beq     @NoQuotationMode                        ; no -> branch
  7029:          jmp     CHROUT_SCREEN_OUTPUT_IN_RVS             ; output the control codes in reverse
  7030:          ; ---------------------------------
  7031:  
  7032:  @NoQuotationMode:
  7033:          cmp     #ASC_RVS                                ; character code for reverse (RVS) mode?
  7034:          bne     @NotReverse                             ; no -> branch, next test
  7035:          sta     zRVS                                    ; remember the reverse mode
  7036:  
  7037:  @NotReverse:
  7038:          cmp     #ASC_HOME                               ; character code for cursor home?
  7039:          bne     @NoCrsrHome                             ; no -> branch, next test
  7040:          jsr     CURSOR_HOME                             ; put the cursor at the home position
  7041:  
  7042:  @NoCrsrHome:
  7043:          cmp     #ASC_CURSORLEFTRIGHT                    ; character code for cursor left/right?
  7044:          bne     @NoCrsrLeftRight                        ; no -> branch, next test
  7045:  
  7046:          iny                                             ; move cursor to the right
  7047:          jsr     AdjustCursorRowBeforeMovingRight        ; if we will move to the next row, increment row number
  7048:          sty     zPNTR                                   ; store cursor column
  7049:  
  7050:          dey                                             ; get old cursor position back
  7051:          cpy     zLNMX                                   ; was the cursor before the end of the (virtual) row?
  7052:          bcc     @End                                    ; yes -> branch
  7053:  
  7054:          ; If we reach here, we moved from the end of the previous row to the current row
  7055:  
  7056:          dec     zTBLX                                   ; decrement the row number (go up one row)
  7057:                                                          ; the first operation GoDownOneVirtualRow does is increment
  7058:                                                          ; the row number. This dec is a countermeasure
  7059:                                                          ; for this incrementing.
  7060:          jsr     GoDownOneVirtualRow                     ; go down one (virtual) row
  7061:          ldy     #0                                      ; set cursor to the beginning of the row
  7062:  @StoreColAndEnd:
  7063:          sty     zPNTR
  7064:  
  7065:  @End:   jmp     CHROUT_SCREEN_END
  7066:          ; -------------------------
  7067:  
  7068:  @NoCrsrLeftRight:
  7069:          cmp     #ASC_CURSORUPDOWN                       ; character code for cursor up/down?
  7070:          bne     @NoCrsrUpDown                           ; no -> branch, next test
  7071:  
  7072:          ; In case we moved down one phyiscal row, but we are still in the
  7073:          ; same (virtual) row, we calculate the new column we would be at
  7074:          ; If this case is not true, the calculation will be thrown away.
  7075:          ; Otherwise, we will use this value.
  7076:  
  7077:          clc
  7078:          tya                                             ; A := Y (current column number)
  7079:          adc     #EDITOR_COLS                            ; add the number of columns in a physical row
  7080:          tay                                             ; Y := A (column number if we are still in the same virtual row)
  7081:  
  7082:          ;
  7083:          inc     zTBLX                                   ; go down one row
  7084:          cmp     zLNMX                                   ; compare just calculated column number with maximum number of column in the current row
  7085:          bcc     @StoreColAndEnd                         ; calculated row number is smaller -> we are still in the same virtual row -> branch, store column
  7086:          beq     @StoreColAndEnd                         ; calculated row number is equal -> we are still in the same virtual row -> branch, store column
  7087:          dec     zTBLX                                   ; go up one row (again to where we started)
  7088:                                                          ; this is a preparation to the JSR GoDownOneVirtualRow below
  7089:  
  7090:          ; "Normalise" the column (in zPNTR)
  7091:          ; That is, calculate zPNTR MOD EDITOR_COLS with a loop
  7092:          ; TODO why?
  7093:  
  7094:  @Normalise:
  7095:          ; sec, but we already have C=1: If we come from "above", then we would have branched in the bcc
  7096:          ; if C=0
  7097:          ; if we looped, then we would have branched in the other bcc from below
  7098:  
  7099:          sbc     #EDITOR_COLS                            ; subtract the number of columns in a physical row
  7100:          bcc     @GoDown                                 ; if we reached < 0, end the loop
  7101:          sta     zPNTR                                   ; store the column
  7102:          bne     @Normalise                              ; if we did not reach 0 yet, loop again
  7103:  
  7104:  @GoDown:
  7105:          jsr     GoDownOneVirtualRow                     ; go down one (virtual) row
  7106:  @End2:
  7107:          jmp     CHROUT_SCREEN_END
  7108:  
  7109:  @NoCrsrUpDown:
  7110:          jsr     EditorCheckColorCodeAndSetColor         ; check if the current PETSCII code is a color. IF yes, set lCOLOR. Return anyway
  7111:  
  7112:  .if CompileComputer >= VIC20_06
  7113:          jmp     EditorCheckForAscLowercase              ; check for additional codes (change uppercase, change lowercase, allow changing uppercase/lowercase, disallow it)
  7114:  .else
  7115:          jmp     CHROUT_SCREEN_END                       ; we're done
  7116:  .endif
  7117:  
  7118:  
  7119:  @NegativeChar:
  7120:  
  7121:  .if CompileComputer >= C64_GENERAL
  7122:  
  7123:  .elseif CompileComputer < VIC20_06
  7124:          ; depending on lMODE, the old VIC20 KERNAL does some translation of
  7125:          ; character codes to be output.
  7126:          ; All of these codes being replaced have in common that their
  7127:          ; 7th bit ($80) is set.
  7128:          ;
  7129:          ; TODO Why is this done?
  7130:  
  7131:          ldx     lMODE                                   ; get lMODE
  7132:          beq     @LE815                                  ; is it 0? Then do NOT do any conversion
  7133:  
  7134:          ldx     #$31
  7135:  @LE807: cmp     CHROUT_REPLACEMENT_TABLE,x
  7136:          beq     @LE812
  7137:          dex
  7138:          dex
  7139:          bpl     @LE807
  7140:          bmi     @LE815
  7141:  @LE812: lda     CHROUT_REPLACEMENT_TABLE - 1,x
  7142:  .else
  7143:  
  7144:  ;       FillUntil $E815, $EA
  7145:          FillNOP 21
  7146:  
  7147:  .endif
  7148:  
  7149:  @LE815:
  7150:  
  7151:          and     #$7F
  7152:          cmp     #TokPi  - $80
  7153:          bne     @LE7DC
  7154:  .if .defined(C64JAPAN)
  7155:          lda     #ASC_PI - $40                                   ; @@@???
  7156:  .else
  7157:          lda     #ASC_PI - $80
  7158:  .endif
  7159:  @LE7DC:
  7160:  .if CompileComputer >= C64_GENERAL
  7161:  
  7162:  .elseif CompileComputer >= VIC20_06
  7163:      .repeat 6
  7164:          nop
  7165:      .endrep
  7166:  .else
  7167:          cmp     #$04
  7168:          bne     @LE823
  7169:          lda     #$7F
  7170:  .endif
  7171:  
  7172:  @LE823:
  7173:          cmp     #' '
  7174:          bcc     @LE7E3
  7175:          jmp     LE691
  7176:          ; ----------------
  7177:  
  7178:  @LE7E3: cmp     #ASC_CR
  7179:          bne     @LE7EA
  7180:          jmp     CHROUT_SCREEN_CR
  7181:  
  7182:  @LE7EA: ldx     zQTSW                                           ; are we in quotation mark mode?
  7183:          bne     @LE82D                                          ; yes -> branch
  7184:          cmp     #ASC_INSDEL
  7185:          bne     @LE829
  7186:          ldy     zLNMX
  7187:          lda     (zPNT),y
  7188:          cmp     #' '
  7189:          bne     @LE7FE
  7190:          cpy     zPNTR
  7191:          bne     @LE805
  7192:  @LE7FE: cpy     #(EDITOR_MAX_COMBINED_ROWS * EDITOR_COLS) - 1
  7193:          beq     @LE826
  7194:          jsr     LE965
  7195:  @LE805: ldy     zLNMX
  7196:          jsr     UpdateColorRAMPointerToVideoramPointer
  7197:  @LE80A: dey
  7198:          lda     (zPNT),y
  7199:          iny
  7200:          sta     (zPNT),y
  7201:          dey
  7202:          lda     (zUSER),y
  7203:          iny
  7204:          sta     (zUSER),y
  7205:          dey
  7206:          cpy     zPNTR
  7207:          bne     @LE80A
  7208:          lda     #' '
  7209:          sta     (zPNT),y
  7210:          lda     lCOLOR
  7211:          sta     (zUSER),y
  7212:          inc     zINSRT                                          ; increment number of characters to output in insert mode
  7213:  @LE826: jmp     CHROUT_SCREEN_END
  7214:          ; -----------------------
  7215:  
  7216:  @LE829: ldx     zINSRT                                          ; number of characters to output in insert mode
  7217:          beq     @LE832
  7218:  @LE82D: ora     #$40
  7219:          jmp     CHROUT_SCREEN_OUTPUT_IN_RVS
  7220:  
  7221:  @LE832: cmp     #ASC_CURSORUPDOWN
  7222:          bne     @LE84C
  7223:          ldx     zTBLX
  7224:          beq     @LE871
  7225:          dec     zTBLX
  7226:          lda     zPNTR
  7227:          sec
  7228:          sbc     #EDITOR_COLS
  7229:          bcc     @LE847
  7230:          sta     zPNTR
  7231:          bpl     @LE871
  7232:  @LE847: jsr     SET_CURSORPOS
  7233:          bne     @LE871
  7234:  @LE84C: cmp     #ASC_RVS
  7235:          bne     @LE854
  7236:          lda     #$00
  7237:          sta     zRVS
  7238:  @LE854: cmp     #ASC_CURSORLEFTRIGHT
  7239:          bne     @LE86A
  7240:          tya
  7241:          beq     @LE864
  7242:          jsr     AdjustCursorRowBeforeMovingLeft         ; we want to move the cursor to the left. If we will cross a row this way, decrement the row number.
  7243:          dey
  7244:          sty     zPNTR
  7245:          jmp     CHROUT_SCREEN_END
  7246:  
  7247:  @LE864: jsr     CHROUT_SCREEN_WrapAroundToPreviousRow
  7248:          jmp     CHROUT_SCREEN_END
  7249:  @LE86A: cmp     #ASC_HOME
  7250:          bne     @LE874
  7251:          jsr     ClearScreen
  7252:  @LE871: jmp     CHROUT_SCREEN_END
  7253:  @LE874: ora     #$80
  7254:          jsr     EditorCheckColorCodeAndSetColor
  7255:  .if CompileComputer >= VIC20_06
  7256:          jmp     EditorCheckForAscUppercase
  7257:  .else
  7258:          jmp     CHROUT_SCREEN_END
  7259:  .endif
  7260:          ; -----------------------
  7261:  
  7262:  GoDownOneVirtualRow:
  7263:          lsr     zLXSP
  7264:          ldx     zTBLX
  7265:  @LE880: inx
  7266:          cpx     #EDITOR_ROWS
  7267:          bne     @LE888
  7268:          jsr     LE8EA
  7269:  @LE888: lda     zLDTB1,x
  7270:          bpl     @LE880
  7271:          stx     zTBLX
  7272:          jmp     SET_CURSORPOS
  7273:  
  7274:  CHROUT_SCREEN_CR:
  7275:          ; output a CR onto the screen at the current cursor position
  7276:  
  7277:          ldx     #$00
  7278:          stx     zINSRT                                  ; end INSERT mode
  7279:          stx     zRVS                                    ; end REVERSE (RVS) mode
  7280:          stx     zQTSW                                   ; end quotation mark mode
  7281:          stx     zPNTR                                   ; put cursor to the beginning of the current line (that is, CR w/o NL, so to speak)
  7282:  
  7283:          jsr     GoDownOneVirtualRow                     ; go down one (virtual) row
  7284:          jmp     CHROUT_SCREEN_END
  7285:          ; --------------
  7286:  
  7287:  ; If the cursor will be part of the previous row after being moved to the left
  7288:  ; (that is, the cursor is at the beginning of the current row now), move
  7289:  ; the cursor one row to the top.
  7290:  
  7291:  AdjustCursorRowBeforeMovingLeft:
  7292:          ldx     #EDITOR_MAX_COMBINED_ROWS               ; maximum number of rows that can be combined in one virtual row
  7293:          lda     #$00                                    ; start counter at column 0
  7294:  @Loop:
  7295:          cmp     zPNTR                                   ; is current cursor column the same as our counter?
  7296:          beq     @DecrementAndExit                       ; yes -> branch, decrement row and exit
  7297:          clc
  7298:          adc     #EDITOR_COLS                            ; calculate next multiple of EDITOR_COLS to test against
  7299:          dex                                             ; still a row to handle?
  7300:          bne     @Loop                                   ; yes -> branch, process next row
  7301:          rts
  7302:  
  7303:  @DecrementAndExit:
  7304:          dec     zTBLX                                   ; decrement current cursor row
  7305:          rts
  7306:  
  7307:  
  7308:  ; If the cursor will be part of the next row after being moved to the right
  7309:  ; (that is, the cursor is at the end of the current row now), move
  7310:  ; the cursor one row to the bottom.
  7311:  
  7312:  AdjustCursorRowBeforeMovingRight:
  7313:          ldx     #EDITOR_MAX_COMBINED_ROWS               ; maximum number of rows that can be combined in one virtual row
  7314:          lda     #EDITOR_COLS - 1                        ; start counter at last column of a physical row
  7315:  @Loop:
  7316:          cmp     zPNTR                                   ; is current cursor column the same as our counter?
  7317:          beq     @IncrementAndExit                       ; yes -> branch, increment row and exit
  7318:          clc
  7319:          adc     #EDITOR_COLS                            ; calculate next column to test against
  7320:          dex                                             ; still a row to handle?
  7321:          bne     @Loop                                   ; yes -> branch, process next row
  7322:          rts
  7323:  
  7324:  @IncrementAndExit:
  7325:          ldx     zTBLX                                   ; is current cursor row
  7326:          cpx     #EDITOR_ROWS                            ; less than the maximum?
  7327:          beq     @Rts                                    ; no, we cannot increment as we are already at the last row -> branch, skip increment
  7328:          inc     zTBLX                                   ; increment cursor row
  7329:  @Rts:   rts
  7330:  
  7331:  ; Check if the current PETSCII code is a color code
  7332:  ; If it is, set lCOLOR accordingly.
  7333:  ; Input:  A := PETSCII code
  7334:  ; Output: if A is a color code:
  7335:  ;            lCOLOR := X := color code
  7336:  ;         else
  7337:  ;            X := $FF, lCOLOR unchanged
  7338:  ; Uses:   X
  7339:  ;
  7340:  EditorCheckColorCodeAndSetColor:
  7341:          ldx     #END_ColorCodes - ColorCodes - 1        ; get number of color codes
  7342:  @CheckColor:
  7343:          cmp     ColorCodes,x                            ; is the current char a color code?
  7344:          beq     @ColorFound                             ; yes -> branch, we found a color
  7345:          dex                                             ; test the next color
  7346:          bpl     @CheckColor                             ; until there is not one left
  7347:          rts
  7348:  @ColorFound:
  7349:          stx     lCOLOR                                  ; store the color code in lCOLOR
  7350:          rts
  7351:  
  7352:  ColorCodes:
  7353:  
  7354:          ; These are the PETSCII values of the color codes
  7355:  
  7356:          .byte   $90,$05,$1C,$9F,$9C,$1E,$1F,$9E         ; colors no. 0-7
  7357:  
  7358:  .if CompileComputer >= C64_GENERAL
  7359:          .byte   $81,$95,$96,$97,$98,$99,$9A,$9B         ; The C64 has 8 additional colors defined here: colors no. 8-15
  7360:  
  7361:  .endif
  7362:  
  7363:  END_ColorCodes:
  7364:  
  7365:  .if CompileComputer < C64_GENERAL
  7366:  
  7367:          ; depending on lMODE, the old VIC20 KERNAL does some translation of
  7368:          ; character codes to be output.
  7369:          ; All of these codes being replaced have in common that their
  7370:          ; 7th bit ($80) is set.
  7371:          ;
  7372:          ; TODO Why is this done?
  7373:  
  7374:          ; this table is organised as follows: Each entry consists of a byte pair.
  7375:          ; the byte at offset 1 is the character that is to be replaced, and
  7376:          ; the byte at offset 0 is the character with which to replace.
  7377:  
  7378:          ; This is only used in VIC20_02 ROMs, although the
  7379:          ; table is also present in later ROMs.
  7380:  
  7381:  CHROUT_REPLACEMENT_TABLE:
  7382:          .byte   $EF,$A1
  7383:          .byte   $DF,$A6
  7384:          .byte   $E1,$B1
  7385:          .byte   $E2,$B2
  7386:          .byte   $E3,$B3
  7387:          .byte   $E4,$B4
  7388:          .byte   $E5,$B5
  7389:          .byte   $E6,$B6
  7390:          .byte   $E7,$B7
  7391:          .byte   $E8,$B8
  7392:          .byte   $E9,$B9
  7393:          .byte   $FA,$BA
  7394:          .byte   $FB,$BB
  7395:          .byte   $FC,$BC
  7396:          .byte   $EC,$BD
  7397:          .byte   $FE,$BE
  7398:          .byte   $84,$BF
  7399:          .byte   $F7,$C0
  7400:          .byte   $F8,$DB
  7401:          .byte   $F9,$DD
  7402:          .byte   $EA,$DE
  7403:  
  7404:  SpecialScreenCodeHandleTable:
  7405:          ; special screen code to PETSCII conversion table
  7406:          ; the first character is the screen code to convert,
  7407:          ; the second character is the PETSCII code to convert in
  7408:          ;
  7409:          ; This is only used in VIC20_02 ROMs, although the
  7410:          ; table is also present in later ROMs.
  7411:  
  7412:          .byte   $5E,$E0
  7413:          .byte   $5B,$E1
  7414:          .byte   $5D,$E2
  7415:          .byte   $40,$B0
  7416:          .byte   $61,$B1
  7417:          .byte   $78,$DB
  7418:          .byte   $79,$DD
  7419:          .byte   $66,$B6
  7420:          .byte   $77,$C0
  7421:          .byte   $70,$F0
  7422:          .byte   $71,$F1
  7423:          .byte   $72,$F2
  7424:          .byte   $73,$F3
  7425:          .byte   $74,$F4
  7426:          .byte   $75,$F5
  7427:          .byte   $76,$F6
  7428:          .byte   $7D,$FD
  7429:  
  7430:  SpecialScreenCodeHandleTable_END:
  7431:  
  7432:  .endif
  7433:  
  7434:  LE8EA:  lda     zSAL
  7435:          pha
  7436:          lda     zSAL + 1
  7437:          pha
  7438:          lda     zEAL
  7439:          pha
  7440:          lda     zEAL + 1
  7441:          pha
  7442:  @LE8F6: ldx     #$FF
  7443:          dec     zTBLX
  7444:          dec     zLXSP
  7445:          dec     lTLNIDX
  7446:  
  7447:  @LE8FF: inx
  7448:          jsr     CalculateScreenPointerFromRowNumber
  7449:          cpx     #EDITOR_ROWS - 1
  7450:          bcs     @LE913
  7451:          lda     SCREEN_LOWBYTE + 1,x
  7452:          sta     zSAL
  7453:          lda     zLDTB1 + 1,x
  7454:          jsr     CopyPhysicalScreenRow
  7455:          bmi     @LE8FF                                  ; => jmp, as CopyPhysicalScreenRow will not return with N=0 ("bpl loop")
  7456:          ; -----------------
  7457:  
  7458:  @LE913:
  7459:          jsr     EraseScreenRow
  7460:          ldx     #0
  7461:  @LE918: lda     zLDTB1,x
  7462:          and     #$7F
  7463:          ldy     zLDTB1 + 1,x
  7464:          bpl     @LE922
  7465:          ora     #$80
  7466:  @LE922: sta     zLDTB1,x
  7467:          inx
  7468:          cpx     #EDITOR_ROWS - 1
  7469:          bne     @LE918
  7470:          lda     zLDTB1 + EDITOR_ROWS - 1
  7471:          ora     #$80
  7472:          sta     zLDTB1 + EDITOR_ROWS - 1
  7473:          lda     zLDTB1
  7474:          bpl     @LE8F6
  7475:          inc     zTBLX
  7476:          inc     lTLNIDX
  7477:  
  7478:          ; check for a pressed CTRL key:
  7479:          ; If it is pressed, incorporate an additional delay
  7480:  
  7481:  .ifdef JIFFY
  7482:  
  7483:  JDLE938:
  7484:          jsr     RestoreKeyboardRowAndRet
  7485:  
  7486:  .else
  7487:          lda     #KEYB_ROW_CTRL                          ; set the keyboard row to the row that has the CTRL key
  7488:          sta     KEYB_ROW
  7489:  .endif
  7490:          lda     KEYB_COL                                ; test the keyboard columns
  7491:          cmp     #KEYB_COL_CTRL                          ; check the CTRL key specifically
  7492:  
  7493:  .ifdef JIFFY
  7494:          bne     @SkipDelay
  7495:          ldx     zNDX
  7496:          beq     JDLE938
  7497:          lda     $0276,x
  7498:          sbc     #$13
  7499:          bne     @SkipDelay
  7500:          sta     zNDX
  7501:  @JDLE94F:       cli
  7502:          cmp     zNDX
  7503:          beq     @JDLE94F
  7504:          sta     zNDX
  7505:  
  7506:  .else
  7507:          php                                             ; remember status
  7508:          lda     #KEYB_ROW_STANDARD              ; restore the keyboard row
  7509:          sta     KEYB_ROW
  7510:          plp                                             ; get back the status
  7511:          bne     @SkipDelay                                      ; Z=1 --> CTRL key not pressed --> branch, skip delay
  7512:  
  7513:          ; create a delay of TODO clock cycles
  7514:          ldy     #0
  7515:  @Delay:
  7516:          nop
  7517:          dex
  7518:          bne     @Delay
  7519:          dey
  7520:          bne     @Delay
  7521:          sty     zNDX
  7522:  
  7523:  .endif
  7524:  
  7525:  @SkipDelay:
  7526:          ldx     zTBLX
  7527:  
  7528:  Restore_zEAL_and_zSAL:
  7529:          pla
  7530:          sta     zEAL + 1
  7531:          pla
  7532:          sta     zEAL
  7533:          pla
  7534:          sta     zSAL + 1
  7535:          pla
  7536:          sta     zSAL
  7537:          rts
  7538:  
  7539:  LE965:
  7540:          ldx     zTBLX
  7541:  LE967:
  7542:          ; find next (virtual) row
  7543:          inx                                     ; proceed to next (physical) row
  7544:          lda     zLDTB1,x                        ; is it combined with the previous one (bit 7 = 0)?
  7545:          bpl     LE967                           ; yes -> branch, loop to test the next row
  7546:  
  7547:          stx     lTLNIDX                         ; remember the row number of the next (virtual) row
  7548:          cpx     #EDITOR_ROWS - 1                ; is this the last (phyiscal) row?
  7549:          beq     @LE981                          ; yes -> branch
  7550:          bcc     @LE981                          ; row number is less than last row -> also branch
  7551:  
  7552:          jsr     LE8EA
  7553:          ldx     lTLNIDX
  7554:          dex
  7555:          dec     zTBLX
  7556:          jmp     LogicallyCombineTwoRows
  7557:          ; --------------------
  7558:  
  7559:          ; Make room on the screen for the extension of a logical screen row to comprise another
  7560:          ; physical screen row. This involves scrolling every row below lTLNIDX down (to make
  7561:          ; room), erasing the new row, and adjusting the pointers in zLDTB1.
  7562:  
  7563:  @LE981:
  7564:          ; save zEAL/zEAL+1 and zSAL/zSAL+1 on the stack as they will be used
  7565:          ; as temporary storage for pointers.
  7566:          ; These will be restored before leaving.
  7567:  
  7568:          lda     zSAL
  7569:          pha
  7570:          lda     zSAL + 1
  7571:          pha
  7572:          lda     zEAL
  7573:          pha
  7574:          lda     zEAL + 1
  7575:          pha
  7576:  
  7577:          ; Move screen contents below the current cursor position downwards
  7578:  
  7579:          ldx     #EDITOR_ROWS                            ; start at the last physical row
  7580:  @CopyRow:
  7581:          dex
  7582:          jsr     CalculateScreenPointerFromRowNumber     ; update the destination pointer into video RAM (zPNT/zPNT+1)
  7583:          cpx     lTLNIDX                                 ; have we already reached the current screen row?
  7584:          bcc     @EndMove                                ; we are above the current screen row -> branch, end the copy (TODO is this needed at all?)
  7585:          beq     @EndMove                                ; we are at the current screen row -> branch, end the copy
  7586:  
  7587:          ; update the source pointers
  7588:          lda     SCREEN_LOWBYTE - 1,x                    ; get low byte of the starting address of this row
  7589:          sta     zSAL                                    ; remember low byte
  7590:          lda     zLDTB1 - 1,x                            ; get high byte of the starting address of this row
  7591:          jsr     CopyPhysicalScreenRow                   ; copy the current screen row from source to destination, moving it down
  7592:          bmi     @CopyRow                                ; => jmp, as CopyPhysicalScreenRow will not return with N=0 ("bpl loop")
  7593:          ; ---------------------------
  7594:  
  7595:  @EndMove:
  7596:          jsr     EraseScreenRow                          ; erase the (physical) screen row in X
  7597:  
  7598:          ; update zLDTB1 to reflect the new situation
  7599:          ; copy the high order (7th) bit of the byte for each row that has been moved
  7600:          ; to the next row.
  7601:          ; source row is the row that is copied, destination row is the next row
  7602:  
  7603:          ldx     #EDITOR_ROWS - 2                        ; start at 2nd to last row of source row
  7604:  
  7605:  @MoveCombinationBits:
  7606:          cpx     lTLNIDX                                 ; have we already reached (<=) the current row?
  7607:          bcc     @EndMoveCombinationBits                 ; yes, quit
  7608:  
  7609:          lda     zLDTB1 + 1,x                            ; get the byte for the next row
  7610:          and     #~$80                                   ; clear bit 7 in all cases
  7611:          ldy     zLDTB1,x                                ; read 7th bit of source row
  7612:          bpl     @Positive                               ; if it is unset (positive), skip
  7613:          ora     #$80                                    ; set the 7th bit of destination row
  7614:  @Positive:
  7615:          sta     zLDTB1 + 1,x                            ; store byte for destination row
  7616:          dex                                             ; proceed with previous row
  7617:          bne     @MoveCombinationBits
  7618:  
  7619:  @EndMoveCombinationBits:
  7620:          ldx     lTLNIDX
  7621:          jsr     LogicallyCombineTwoRows
  7622:  
  7623:          ; restore zEAL/zEAL+1 and zSAL/zSAL+1
  7624:  
  7625:  .if CompileComputer >= C64_GENERAL
  7626:          jmp     Restore_zEAL_and_zSAL                           ; same implementation like VIC-20, but we save memory as it is already there
  7627:  .else
  7628:          pla
  7629:          sta     zEAL + 1
  7630:          pla
  7631:          sta     zEAL
  7632:          pla
  7633:          sta     zSAL + 1
  7634:          pla
  7635:          sta     zSAL
  7636:          rts
  7637:  .endif
  7638:  
  7639:          ; Copy one (physical) screen row on screen to another screen row
  7640:  
  7641:          ; This will copy a physical screen row in memory, including the video and the color RAM.
  7642:          ; It is used to scroll the screen up or down, but it is not limited to this usage.
  7643:  
  7644:          ; Input: A = high byte of start address of (logical TODO) screen row (cf. zLDTB1) from which to copy
  7645:          ;        zSAL = low byte of start address of (physical) screen row (cf. SCREEN_LOWBYTE) from which to copy
  7646:  
  7647:          ;        zPNT/zPNT+1   = Start address of physical screen row video RAM destination
  7648:          ;        zUSER/zUSER+1 = Start address of physical screen row color RAM destination
  7649:  
  7650:  CopyPhysicalScreenRow:
  7651:          and     #>lVIDEORAM_SIZE                        ; make sure to let the start address
  7652:          ora     lHIBASE                                 ; point into the current video RAM
  7653:          sta     zSAL + 1                                ; store the address as pointer
  7654:          jsr     @UpdateColorRamPointers
  7655:  
  7656:          ; Copy one (physical) row
  7657:  
  7658:          ldy     #EDITOR_COLS - 1                        ; index of last character in a (physical) row
  7659:  @CopyPreviousChar:
  7660:          lda     (zSAL),y                                ; get character from source
  7661:          sta     (zPNT),y                                ; and store it at the destination
  7662:          lda     (zEAL),y                                ; get color from source
  7663:          sta     (zUSER),y                               ; and store it at the destination
  7664:          dey                                             ; go to previous character
  7665:          bpl     @CopyPreviousChar                       ; non-negative -> branch, there is still a character to be processed
  7666:          rts
  7667:          ; -----------------------
  7668:  
  7669:          ; Update the color RAM pointers in zUSER/zUSER+1 and zEAL/zEAL+1, respectively,
  7670:          ; to point to the same locations as the video RAM pointers
  7671:          ; in zPNT/zPNT+1 and zSAL/zSAL+1, respectively.
  7672:  
  7673:  @UpdateColorRamPointers:
  7674:          jsr     UpdateColorRAMPointerToVideoramPointer  ; update the color RAM pointer to match the video RAM pointer
  7675:  
  7676:          ; adjust video RAM pointer in zSAL/zSAL+1 to point to the color RAM (in zEAL/zEAL+1)
  7677:          lda     zSAL
  7678:          sta     zEAL
  7679:          lda     zSAL + 1
  7680:          and     #>lVIDEORAM_SIZE
  7681:          ora     #>COLORRAM
  7682:          sta     zEAL + 1
  7683:          rts
  7684:  
  7685:  CalculateScreenPointerFromRowNumber:
  7686:          ; calculate the start of the screen row of which the number
  7687:          ; is given in X. Store it in zPNT.
  7688:  
  7689:          lda     SCREEN_LOWBYTE,x        ; get low byte of the starting address of this row
  7690:          sta     zPNT                    ; remember low byte
  7691:          lda     zLDTB1,x                ; get high byte of the starting address of this row
  7692:          and     #>lVIDEORAM_SIZE        ; mask out additional bits used as flags
  7693:          ora     lHIBASE                 ; add the video RAM base
  7694:          sta     zPNT + 1                ; remember high byte
  7695:          rts
  7696:  
  7697:  
  7698:  EraseScreenRow:
  7699:  
  7700:          ; this routine erases the screen row no. X
  7701:  
  7702:          ldy     #EDITOR_COLS - 1                ; start in the last column
  7703:          jsr     CalculateScreenPointerFromRowNumber     ; set the video RAM pointer in zPNT to the row we want to process
  7704:          jsr     UpdateColorRAMPointerToVideoramPointer  ; update the video RAM pointer in zUSER to correspond to zPNT
  7705:  
  7706:  @Loop:
  7707:  .if CompileComputer >= C64_03 .AND CompileComputer <> C64_4064
  7708:          jsr     Patch_StoreColor                        ; set the color of the location
  7709:  .endif
  7710:          lda     #' '                                    ; store a SPACE (' ') into the video RAM position
  7711:          sta     (zPNT),y
  7712:  .if CompileComputer = C64_02 .OR CompileComputer = C64_4064
  7713:          jsr     Patch_StoreColor                        ; set the color of the location
  7714:          nop
  7715:  .elseif CompileComputer <= C64_01
  7716:          lda     #COL_WHITE                              ; set the color of the location to white
  7717:          sta     (zUSER),y
  7718:  .endif
  7719:          dey                                             ; proceed to the previous column
  7720:          bpl     @Loop                                   ; still >= 0, branch -> process the next column
  7721:          rts
  7722:          ; ----------------------------------
  7723:  
  7724:  .if CompileComputer >= C64_03 .AND CompileComputer <> C64_4064
  7725:          nop
  7726:  .endif
  7727:  
  7728:  
  7729:  StoreCharacterOnScreenAndDisableBlinking:
  7730:          tay                                             ; remember character to output
  7731:  
  7732:          lda     #$02                                    ; set blink counter to $02 (TODO WHY?)
  7733:          sta     zBLNCT
  7734:  
  7735:          jsr     UpdateColorRAMPointerToVideoramPointer  ; set pointer to video RAM at cursor position
  7736:  
  7737:          tya                                             ; get back character to output
  7738:  
  7739:  ;
  7740:  ; Store character on screen at the current cursor position
  7741:  ;
  7742:  ; A = character
  7743:  ; X = color
  7744:  ;
  7745:  StoreCharacterOnScreen:
  7746:          ldy     zPNTR                                   ; get column offset in of current screen position
  7747:          sta     (zPNT),y                                ; store character in video RAM
  7748:          txa                                             ; get color
  7749:          sta     (zUSER),y                               ; store color in color RAM
  7750:          rts
  7751:  
  7752:  UpdateColorRAMPointerToVideoramPointer:
  7753:          lda     zPNT
  7754:          sta     zUSER
  7755:          lda     zPNT + 1
  7756:          and     #>lVIDEORAM_SIZE
  7757:          ora     #>COLORRAM
  7758:          sta     zUSER + 1
  7759:          rts
  7760:  
  7761:  KIRQ:
  7762:          jsr     kUDTIM
  7763:          lda     zBLNSW
  7764:          bne     @LEA61
  7765:          dec     zBLNCT
  7766:          bne     @LEA61
  7767:          lda     #$14
  7768:          sta     zBLNCT
  7769:          ldy     zPNTR
  7770:          lsr     zBLNON
  7771:          ldx     lGDCOL
  7772:          lda     (zPNT),y
  7773:          bcs     @LEA5C
  7774:          inc     zBLNON
  7775:          sta     zGDBLN
  7776:          jsr     UpdateColorRAMPointerToVideoramPointer
  7777:          lda     (zUSER),y
  7778:          sta     lGDCOL
  7779:          ldx     lCOLOR
  7780:          lda     zGDBLN
  7781:  @LEA5C: eor     #$80
  7782:          jsr     StoreCharacterOnScreen
  7783:  
  7784:  @LEA61:
  7785:  
  7786:  .ifdef JIFFY
  7787:  
  7788:  LEA61:  jmp     LEA7B
  7789:  LEA64:  pla
  7790:          pha
  7791:          cmp     #$98
  7792:          beq     JDLEA6D
  7793:  JDLEA6A:  jmp     LA57C
  7794:  JDLEA6D:  jsr     JDLF72C
  7795:          bne     JDLEA6A
  7796:          ldx     zTXTPTR
  7797:          ldy     #$04
  7798:          tya
  7799:          jmp     JDLA5E3
  7800:          .byte   $01
  7801:  
  7802:  .else
  7803:          lda     TAPE_REG_SENSE
  7804:          and     #TAPE_B_SENSE
  7805:          beq     @LEA71
  7806:          ldy     #$00
  7807:          sty     zCAS1
  7808:          lda     TAPE_REG_MOTOR
  7809:          ora     #TAPE_B_MOTOR_ON
  7810:          bne     @LEA79
  7811:          ; -------------------------
  7812:  
  7813:  @LEA71: lda     zCAS1
  7814:          bne     LEA7B
  7815:          lda     TAPE_REG_MOTOR
  7816:          and     #TAPE_B_MOTOR_OFF_AND
  7817:  @LEA79:
  7818:    .if CompileComputer < C64_GENERAL
  7819:          bit     VIA1_IEC
  7820:          bvs     LEA7B
  7821:    .endif
  7822:          sta     TAPE_REG_MOTOR
  7823:  
  7824:  .endif
  7825:  
  7826:  LEA7B:
  7827:  .if CompileComputer = C64_4064
  7828:          jsr     LE4C8
  7829:  .else
  7830:          jsr     iSCNKEY
  7831:  .endif
  7832:  
  7833:  .if CompileComputer >= C64_GENERAL
  7834:          lda     CIA1 + CIA_O_ICR
  7835:  .else
  7836:          bit     VIA2_T1CL
  7837:  .endif
  7838:          pla
  7839:          tay
  7840:          pla
  7841:          tax
  7842:          pla
  7843:          rti
  7844:  
  7845:  ;  B-25. Function Name: SCNKEY
  7846:  ;
  7847:  ;    Purpose: Scan the keyboard
  7848:  ;    Call address: $FF9F (hex) 65439 (decimal)
  7849:  ;    Communication registers: None
  7850:  ;    Preparatory routines: IOINIT
  7851:  ;    Error returns: None
  7852:  ;    Stack requirements: 5
  7853:  ;    Registers affected: A, X, Y
  7854:  ;
  7855:  ;    Description: This routine scans the Commodore 64 keyboard and checks
  7856:  ;  for pressed keys. It is the same routine called by the interrupt handler.
  7857:  ;  If a key is down, its ASCII value is placed in the keyboard queue. This
  7858:  ;  routine is called only if the normal IRQ interrupt is bypassed.
  7859:  ;
  7860:  ;  How to Use:
  7861:  ;
  7862:  ;  1) Call this routine.
  7863:  ;
  7864:  ;  EXAMPLE:
  7865:  ;
  7866:  ;    GET  JSR SCNKEY      ;SCAN KEYBOARD
  7867:  ;         JSR GETIN       ;GET CHARACTER
  7868:  ;         CMP #0          ;IS IT NULL?
  7869:  ;         BEQ GET         ;YES... SCAN AGAIN
  7870:  ;         JSR CHROUT      ;PRINT IT
  7871:  ;
  7872:  ;
  7873:  iSCNKEY:
  7874:          lda     #0              ; start with: No shift key (SHIFT, CTRL, CBM) is pressed
  7875:          sta     lSHFLAG
  7876:  
  7877:          ldy     #KEY_NONE       ; start with: No key pressed
  7878:          sty     zSFDX
  7879:  
  7880:          ; check if any key is pressed at all
  7881:          sta     KEYB_ROW        ; set all rows to 0
  7882:          ldx     KEYB_COL        ; get columns
  7883:          cpx     #$FF            ; everything set?
  7884:          beq     iSCNKEY_EndScan ; yes, no key is pressed, abort.
  7885:                                  ; Note that X = $FF is crucial here, as iSCNKEY_EndScan checked for the keycode (in X). If there were anything else in X, then this would be used as keycode and stored into the keyboard buffer
  7886:  
  7887:  .if CompileComputer >= C64_GENERAL
  7888:          tay                     ; Place of the key pressed in the KEYTAB (stored in Y) = 0
  7889:  .else
  7890:          lda     #~$01           ; start at row 0 (2^0)
  7891:          sta     KEYB_ROW
  7892:          ldy     #$00            ; Place of the key pressed in the KEYTAB (stored in Y) = 0
  7893:  .endif
  7894:          lda     #<KEYTAB_UNSHIFTED      ; start with the unshifted keytab
  7895:          sta     zKEYTAB
  7896:          lda     #>KEYTAB_UNSHIFTED
  7897:          sta     zKEYTAB + 1
  7898:  
  7899:  .if CompileComputer >= C64_GENERAL
  7900:          lda     #~$01           ; start at row 0 (2^0)
  7901:          sta     KEYB_ROW
  7902:  .endif
  7903:  
  7904:  @CheckAllRows:
  7905:          ldx     #8              ; process every of the 8 keyboard columns
  7906:  
  7907:  .if CompileComputer >= C64_GENERAL
  7908:          pha                     ; remember the mask we put into KEYB_ROW for later processing
  7909:  .endif
  7910:  
  7911:  @UnbounceColumns:
  7912:          lda     KEYB_COL        ; get column
  7913:          cmp     KEYB_COL        ; unbounce it
  7914:  .if CompileComputer >= C64_GENERAL
  7915:          bne     @UnbounceColumns        ; if it changed between reading, re-read it
  7916:  .else
  7917:          bne     @CheckAllRows   ; if colum changed between reading, re-read it. The LDX #8 does not do any harm here; however, for the additional PHA on the C64, we would corrupt the stack. Thus, the target of the branch was changed on the C64.
  7918:  
  7919:  .endif
  7920:  
  7921:          ; the following loop tests each column one after one if the bit was 0
  7922:          ; if it was, the key on the row/column was pressed.
  7923:          ; This is not completely right if more than one key was pressed,
  7924:          ; but this is a hardware limitation we cannot handle.
  7925:  
  7926:  @ProcessColumn:
  7927:          lsr     a                       ; get bit from column into C
  7928:          bcs     @KeyNotPressed          ; C set -> jump, key was not pressed
  7929:  
  7930:          pha                             ; remember current column mask
  7931:  
  7932:          lda     (zKEYTAB),y             ; get the key code that corresponds to the current row/column
  7933:          cmp     #5                      ; is it >= 5?
  7934:          bcs     @StoreKey               ; yes, it is a printable char, branch in order to store it
  7935:          cmp     #KEY_STOP               ; is it the Run/Stop key?
  7936:          beq     @StoreKey               ; yes, store it
  7937:  
  7938:          ; if we reached here, the character code is 1, 2, or 4: One of the keys shift or CBM
  7939:          ; thus, remember the shift flag
  7940:  
  7941:          ora     lSHFLAG                 ; set the corresponding flag
  7942:          sta     lSHFLAG                 ;
  7943:  
  7944:          bpl     @DoNotStoreKey          ; unconditional jump, as lSHFLAG.7 is never set.
  7945:          ; ----------------------------
  7946:  
  7947:  @StoreKey:
  7948:          sty     zSFDX                   ; remember key code
  7949:  
  7950:  @DoNotStoreKey:
  7951:          pla                             ; get back column mask
  7952:  
  7953:  @KeyNotPressed:
  7954:          iny                             ; this keytable entry was processed, go to the next one
  7955:          cpy     #$41                    ; did we already process all $40 entries?
  7956:          bcs     @EndScanning            ; yes, we are done (for now)
  7957:  
  7958:          dex                             ; decrement the column counter
  7959:          bne     @ProcessColumn          ; and repeat scanning, if the counter did not reach 0.
  7960:  
  7961:          ; The following code rotates the mask at KEYB_ROW to the left.
  7962:          ; This moves the "0" bit from right to left.
  7963:          ; Thus, every row is processed, one after the other.
  7964:          ; The implementation was changed between VIC20 and C64, though:
  7965:          ; While the VIC20 uses a ROL on the KEYB_ROW address directly,
  7966:          ; the C64 performs the ROL in a register and puts the value into
  7967:          ; KEYB_ROW afterwards.
  7968:          ; This change most likely occurred since ROL is a read-modify-write
  7969:          ; instruction. Thus, it will write to the location two times, in two
  7970:          ; consecutives cycles: First, it will write the old value, and after-
  7971:          ; wards, it will write the new one. This might generate some "spike"
  7972:          ; which could inadvertedly affect the reading.
  7973:  
  7974:          sec                             ; make sure to ROL in a "1" bit
  7975:  
  7976:  .if CompileComputer >= C64_GENERAL
  7977:          pla                             ; get back the mask we put at KEYB_ROW last time
  7978:          rol     a                       ; rotate it to the left
  7979:          sta     KEYB_ROW                ; and set the new mask
  7980:  .else
  7981:          rol     KEYB_ROW                ; rotate to mask to the left
  7982:  .endif
  7983:          bne     @CheckAllRows
  7984:  
  7985:  @EndScanning:
  7986:  
  7987:  .if CompileComputer >= C64_GENERAL
  7988:          pla                             ; we do not need the mask we put at KEYB_ROW last time anymore, remove it
  7989:  .endif
  7990:  
  7991:          ; Essentially, we are done with scanning here. However, we have to determine
  7992:          ; if a shift key (SHIFT, C=, CTRL) was pressed, which changes the meaning of
  7993:          ; some keys. Thus, process the shift keys now.
  7994:          jmp     (lKEYLOG)               ; points to CHECK_SHIFT_CTRL_CBM
  7995:  
  7996:  ConvertRawKeycodeToInterpretedKeycode:
  7997:          ldy     zSFDX                           ; get the character code
  7998:          lda     (zKEYTAB),y                     ; and read in the right ASCII value of it according to the right KEYTAB
  7999:          tax
  8000:  
  8001:          cpy     zLSTX
  8002:          beq     @CheckRepeat
  8003:          ldy     #$10
  8004:          sty     lDELAY
  8005:          bne     StoreKeyCodeIntoKeyBuffer
  8006:  
  8007:  @CheckRepeat:
  8008:          and     #$7F                            ; ignore bit 7 of key (TODO why?)
  8009:  
  8010:          ; determine if the key press is to be repeated
  8011:  
  8012:          bit     lRPTFLG                         ; check repeat flag
  8013:          bmi     RepeatKey                       ; bit 7 set, repeat all keys --> branch
  8014:          bvs     RestoreKeyboardRowAndRet        ; bit 6 set, do not repeat any key --> branch
  8015:  
  8016:          cmp     #$7F                            ; Is this the key ... (TODO Which key is this?)
  8017:  
  8018:  iSCNKEY_EndScan:
  8019:          beq     StoreKeyCodeIntoKeyBuffer       ; Yes, branch -> Store the key into the keyboard buffer
  8020:                                                  ; TODO Why this extra handling?
  8021:  
  8022:          cmp     #ASC_INSDEL                     ; did the user press INS/DEL?
  8023:          beq     RepeatKey                       ; yes, branch -> process repetition
  8024:  
  8025:          cmp     #' '                            ; did the user press SPACE (" "), or shifted SPACE ($A0)?
  8026:          beq     RepeatKey                       ; yes, process the repetition
  8027:  
  8028:          cmp     #ASC_CURSORLEFTRIGHT            ; did the user press CRSR LEFT/CRSR RIGHT key?
  8029:          beq     RepeatKey                       ; yes, branch -> process the repetition
  8030:  
  8031:          cmp     #ASC_CURSORUPDOWN               ; did the user press CRSR LEFT/CRSR RIGHT key?
  8032:          bne     RestoreKeyboardRowAndRet        ; no, branch -> do not store the key at all
  8033:  
  8034:  RepeatKey:
  8035:  
  8036:          ; wait for the initial delay counter lDELAY
  8037:  
  8038:          ; For key repetitions, there are two delay: One is the initial delay, that is,
  8039:          ; how long must a key be pressed before the repetition takes place.
  8040:          ; This is counted by lDELAY.
  8041:  
  8042:          ; The other delay is the counter between repeated keys, if the key is hold
  8043:          ; long enough. This is counted by lKOUNT.
  8044:  
  8045:          ldy     lDELAY                          ; is there an initial delay?
  8046:          beq     @NoInitialDelay                 ; no, repeat immediately
  8047:  
  8048:          dec     lDELAY                          ; yes, decrement the initial delay counter
  8049:          bne     RestoreKeyboardRowAndRet        ; still not delayed enough -> branch, do nothing
  8050:  
  8051:  @NoInitialDelay:
  8052:          dec     lKOUNT                          ; decrement the delay counter
  8053:          bne     RestoreKeyboardRowAndRet        ; not yet 0, do nothing
  8054:  
  8055:          ldy     #$04                            ; restore the delay counter
  8056:          sty     lKOUNT
  8057:  
  8058:          ; test if the keyboard buffer is empty.
  8059:          ; if it is not empty, no key repetition will take place.
  8060:  
  8061:          ; this way, we prevent a full keyboard buffer with repeated keys,
  8062:          ; which would not be a good user experience (we repeat keys faster
  8063:          ; than the program can handle them)
  8064:  
  8065:          ldy     zNDX                            ; number of keys in keyboard buffer
  8066:          dey                                     ; - 1
  8067:          bpl     RestoreKeyboardRowAndRet        ; still > 0? Then, the buffer is not empty -> branch, do nothing
  8068:  
  8069:  StoreKeyCodeIntoKeyBuffer:
  8070:  
  8071:          ; Store key code in X into keybuffer
  8072:  
  8073:          ; remember key code for the next call of the keyboard routines.
  8074:          ; this is used for determining if a key was pressed for a longer time
  8075:          ; and if it has to be repeated, or not.
  8076:          ldy     zSFDX
  8077:          sty     zLSTX
  8078:  
  8079:          ; remember shift states for the next call of the keyboard routines.
  8080:          ; this way, we prevent that SHIFT-CBM is processed more than once, as
  8081:          ;it is only processed if the shift state changed.
  8082:          ldy     lSHFLAG
  8083:          sty     lLSTSHF
  8084:  
  8085:          cpx     #$FF                            ; is the key an invalid one ($FF in the keyboard tables?)
  8086:          beq     RestoreKeyboardRowAndRet        ; yes, branch -> do not store it
  8087:          txa
  8088:  
  8089:          ; here, we store the keycode that is in A into the keyboard buffer
  8090:          ; Note that this routine will generate a race in case it is called w/o
  8091:          ; interrupts disabled
  8092:  
  8093:          ldx     zNDX                    ; get the index into the keyboard buffer
  8094:          cpx     lXMAX                   ; is the buffer full?
  8095:          bcs     RestoreKeyboardRowAndRet        ; yes, branch -> do not store the key
  8096:          sta     lKEYD,x                 ; store the keycode into the buffer
  8097:          inx                             ; increment the number of keys in the buffer
  8098:          stx     zNDX                    ; and store it
  8099:  
  8100:  RestoreKeyboardRowAndRet:
  8101:          lda     #KEYB_ROW_STANDARD      ; restore the keyboard row
  8102:          sta     KEYB_ROW
  8103:          rts
  8104:  
  8105:  
  8106:  CHECK_SHIFT_CTRL_CBM:
  8107:  
  8108:          ; Determine if a shift key (SHIFT, C=, CTRL) was pressed, which changes
  8109:          ; the meaning of some keys.
  8110:  
  8111:          lda     lSHFLAG                         ; get the shift state
  8112:          cmp     #lSHFLAG_SHIFT | lSHFLAG_CBM    ; shift and commodore pressed?
  8113:          bne     @SwitchToShiftedKeyTable        ; no, branch -> process a shifted key table instead
  8114:  
  8115:          cmp     lLSTSHF                         ; yes, check if the state changed from the last scan
  8116:          beq     RestoreKeyboardRowAndRet        ; it's the same state, branch -> do nothing
  8117:  
  8118:          ; If we reach here, SHIFT and C= were pressed simultaneously.
  8119:          ; Thus, the user wants to switch between Uppercase+Graphics mode,
  8120:          ; and Lowercase + Uppercase mode.
  8121:  
  8122:          lda     lMODE                           ; are we allowed to switch modes?
  8123:          bmi     @ConvertRawKeycodeToInterpretedKeycode                          ; no, branch -> skip
  8124:  
  8125:  .if CompileComputer >= C64_GENERAL
  8126:  
  8127:          ; we change mode by changing the base address of the character ROM in the VIC-II
  8128:  
  8129:          lda     VIC + VICII_O_MemControl
  8130:          eor     #$02
  8131:          sta     VIC + VICII_O_MemControl
  8132:  .elseif CompileComputer >= VIC20_06
  8133:      .repeat 19
  8134:          nop
  8135:      .endrep
  8136:  
  8137:          ; we change mode by changing the base address of the character ROM in the VIC-II
  8138:  
  8139:          lda     VIC + VICI_O_MemoryLocations
  8140:          eor     #$02
  8141:          sta     VIC + VICI_O_MemoryLocations
  8142:  
  8143:      .repeat 4
  8144:          nop
  8145:      .endrep
  8146:  .else
  8147:          ; this is just a complicated way to EOR VICI_O_MemoryLocations with $02
  8148:          ; furthermore, it keeps track if the state in lMODE.4 ($10)
  8149:  
  8150:          and     #$18                    ; determine current mode
  8151:          beq     @SwitchToLowercase      ; it is uppercase, branch -> switch to lowercase
  8152:  
  8153:          ; if we reach here, we are in lowercase mode and want to switch to uppercase mode
  8154:  
  8155:          ; remember uppercase mode
  8156:          lda     #$00
  8157:          sta     lMODE
  8158:  
  8159:          ; switch VIC to uppercase mode
  8160:          lda     VIC + VICI_O_MemoryLocations
  8161:          and     #~$02
  8162:          sta     VIC + VICI_O_MemoryLocations
  8163:  
  8164:          bne     @ConvertRawKeycodeToInterpretedKeycode                  ; unconditional branch
  8165:          ; --------------
  8166:  
  8167:  @SwitchToLowercase:
  8168:          ; switch VIC to lowercase mode
  8169:          lda     VIC + VICI_O_MemoryLocations
  8170:          ora     #$02
  8171:          sta     VIC + VICI_O_MemoryLocations
  8172:  
  8173:          ; remember lowercase mode
  8174:          lda     #$08
  8175:          sta     lMODE
  8176:  .endif
  8177:  
  8178:  .if CompileComputer = VIC20_02
  8179:          bne     @ConvertRawKeycodeToInterpretedKeycode          ; unconditional jump
  8180:  .else
  8181:          jmp     @ConvertRawKeycodeToInterpretedKeycode
  8182:  .endif
  8183:          ; ---------------------------
  8184:  
  8185:  @SwitchToShiftedKeyTable:
  8186:  
  8187:          ; (here, we enter with A := lSHFLAG)
  8188:  
  8189:          ; Calculate the offset of the key table for the shift flags
  8190:          ; this is done by doubling the value of lSHFLAG, and special
  8191:          ; handling of lSHFLAG_CTRL which would double to 8, but 6 is
  8192:          ; the right offset
  8193:  
  8194:          asl     a                       ; double shift flag
  8195:          cmp     #2 * lSHFLAG_CTRL       ; is it CTRL?
  8196:          bcc     @UseOffset              ; no, use the offset
  8197:          lda     #$06                    ; yes, correct the offset
  8198:  
  8199:  .if CompileComputer >= C64_GENERAL
  8200:  .elseif CompileComputer >= VIC20_06
  8201:          nop
  8202:          nop
  8203:  .else
  8204:          bne     @VIC20_02_HandleOffsetDirectly  ; for VIC-20-02, use this offset. (unconditional branch)
  8205:          ; ------------------------------------
  8206:  .endif
  8207:  
  8208:  @UseOffset:
  8209:  
  8210:  .if CompileComputer >= C64_GENERAL
  8211:  
  8212:  .elseif CompileComputer >= VIC20_06
  8213:      .repeat 32
  8214:          nop
  8215:      .endrep
  8216:  .else
  8217:  
  8218:          ldx     lMODE                                   ; if lMODE = 0, use the offset
  8219:          beq     @VIC20_02_HandleOffsetDirectly
  8220:  
  8221:          ldx     lSHFLAG                                 ; if C= key is not the only shift key pressed:
  8222:          cpx     #lSHFLAG_CBM
  8223:          bne     @VIC20_02_HandleOffsetDirectly          ; branch -> handle the offset
  8224:  
  8225:          ; if we reach here, the C= key is pressed (but not SHIFT or CTRL)
  8226:  
  8227:          cpx     lLSTSHF                                 ; did the shift state change from the last time?
  8228:          beq     @ConvertRawKeycodeToInterpretedKeycode  ; no, just convert the key code.
  8229:  
  8230:          ; TODO
  8231:          ; switch uppercase mode with lowercase mode (why?)
  8232:          ; switch bit 4 (???) (why?)
  8233:          ; but do not update the VIC itself (why?)
  8234:  
  8235:          lda     lMODE
  8236:          eor     #$18
  8237:          sta     lMODE
  8238:  
  8239:          bpl     @ConvertRawKeycodeToInterpretedKeycode          ; branches if lMODE.7 is 0: switching between uppercase-mode and lowercase-mode is allowed. (TODO why?)
  8240:  
  8241:  @VIC20_02_HandleOffsetDirectly:
  8242:          ora     lMODE                   ; get the offset into KEYTABS_VEC
  8243:          and     #$7F
  8244:  .endif
  8245:  
  8246:          tax                             ; X := offset into KEYTABS_VEC
  8247:  
  8248:          ; switch to the right KEYTAB according to the shift states
  8249:  
  8250:          lda     @KEYTABS_VEC,x
  8251:          sta     zKEYTAB
  8252:          lda     @KEYTABS_VEC + 1,x
  8253:          sta     zKEYTAB + 1
  8254:  
  8255:  @ConvertRawKeycodeToInterpretedKeycode:
  8256:          jmp     ConvertRawKeycodeToInterpretedKeycode
  8257:  
  8258:  @KEYTABS_VEC:
  8259:          .addr   KEYTAB_UNSHIFTED        ; $00
  8260:          .addr   KEYTAB_SHIFT            ; $02 (lSHFLAG=$01, SHIFT)
  8261:          .addr   KEYTAB_CBM              ; $04 (lSHFLAG=$02, C=)
  8262:          .addr   KEYTAB_CTRL             ; $06 (lSHFLAG=$04, CTRL)
  8263:  
  8264:  .if CompileComputer < C64_GENERAL
  8265:  
  8266:          ; these keytabs are only used in the VIC20-02 ROM, but they
  8267:          ; are still present in the later ones.
  8268:  
  8269:          ; these 4 tables are used if we are in lowercase mode
  8270:          .addr   KEYTAB_UNSHIFTED        ; $08
  8271:          .addr   KEYTAB_SHIFT            ; $0A
  8272:          .addr   KEYTAB6                 ; $0C
  8273:          .addr   KEYTAB_CTRL             ; $0E
  8274:  
  8275:          .addr   KEYTAB5                 ; $10
  8276:          .addr   KEYTAB6                 ; $12
  8277:          .addr   KEYTAB6                 ; $14
  8278:          .addr   KEYTAB_CTRL             ; $16
  8279:  
  8280:  .endif
  8281:  
  8282:  KEYTAB_UNSHIFTED:
  8283:  
  8284:  .if CompileComputer >= C64_GENERAL
  8285:  
  8286:          .byte   $14,$0D,$1D,$88,$85,$86,$87,$11
  8287:          .byte   $33,$57,$41,$34,$5A,$53,$45,$01
  8288:          .byte   $35,$52,$44,$36,$43,$46,$54,$58
  8289:          .byte   $37,$59,$47,$38,$42,$48,$55,$56
  8290:  
  8291:          .byte   $39,$49,$4A,$30,$4D,$4B,$4F,$4E
  8292:          .byte   $2B,$50,$4C,$2D,$2E,$3A,$40,$2C
  8293:          .byte   $5C,$2A,$3B,$13,$01,$3D,$5E,$2F
  8294:          .byte   $31,$5F,$04,$32,$20,$02,$51,$03
  8295:          .byte   $FF
  8296:  
  8297:  .else
  8298:  
  8299:          .byte   $31,$33,$35,$37,$39,$2B,$5C,$14
  8300:          .byte   $5F,$57,$52,$59,$49,$50,$2A,$0D
  8301:          .byte   $04,$41,$44,$47,$4A,$4C,$3B,$1D
  8302:          .byte   $03,$01,$58,$56,$4E,$2C,$2F,$11
  8303:  
  8304:          .byte   $20,$5A,$43,$42,$4D,$2E,$01,$85
  8305:          .byte   $02,$53,$46,$48,$4B,$3A,$3D,$86
  8306:          .byte   $51,$45,$54,$55,$4F,$40,$5E,$87
  8307:          .byte   $32,$34,$36,$38,$30,$2D,$13,$88
  8308:  
  8309:          .byte   $FF
  8310:  
  8311:  .endif
  8312:  
  8313:  KEYTAB_SHIFT:
  8314:  
  8315:  .if CompileComputer >= C64_GENERAL
  8316:  
  8317:    .if .defined(C64JAPAN)
  8318:          .byte   $94,$8D,$9D,$8C,$89,$8A,$8B,$91
  8319:          .byte   $23,$A8,$AA,$24,$AD,$AB,$A9,$01
  8320:          .byte   $25,$A5,$AC,$26,$AF,$A4,$FF,$AE
  8321:          .byte   $27,$FF,$FF,$28,$FF,$FF,$FF,$FF
  8322:  
  8323:          .byte   $29,$FF,$FF,$30,$FF,$FF,$FF,$FF
  8324:          .byte   $A1,$FF,$FF,$A2,$3E,$5B,$FF,$3C
  8325:          .byte   $A3,$FF,$5D,$93,$01,$3D,$B0,$3F
  8326:          .byte   $21,$5F,$04,$22,$A0,$02,$A7,$83
  8327:          .byte   $FF
  8328:    .else
  8329:          .byte   $94,$8D,$9D,$8C,$89,$8A,$8B,$91
  8330:          .byte   $23,$D7,$C1,$24,$DA,$D3,$C5,$01
  8331:          .byte   $25,$D2,$C4,$26,$C3,$C6,$D4,$D8
  8332:          .byte   $27,$D9,$C7,$28,$C2,$C8,$D5,$D6
  8333:  
  8334:          .byte   $29,$C9,$CA,$30,$CD,$CB,$CF,$CE
  8335:          .byte   $DB,$D0,$CC,$DD,$3E,$5B,$BA,$3C
  8336:          .byte   $A9,$C0,$5D,$93,$01,$3D,$DE,$3F
  8337:          .byte   $21,$5F,$04,$22,$A0,$02,$D1,$83
  8338:          .byte   $FF
  8339:    .endif
  8340:  
  8341:  
  8342:  .else
  8343:  
  8344:          .byte   $21,$23,$25,$27,$29
  8345:    .if CompileComputer >= VIC20_06
  8346:          .byte                       $DB,$A9
  8347:    .else
  8348:          .byte                       $AB,$DC
  8349:    .endif
  8350:          .byte                               $94
  8351:  
  8352:    .if CompileComputer >= VIC20_06
  8353:          .byte   $5F
  8354:    .else
  8355:          .byte   $DF
  8356:    .endif
  8357:          .byte       $D7,$D2,$D9,$C9,$D0
  8358:    .if CompileComputer >= VIC20_06
  8359:          .byte                           $C0
  8360:    .else
  8361:          .byte                           $AA
  8362:    .endif
  8363:          .byte                               $8D
  8364:  
  8365:          .byte   $04,$C1,$C4,$C7,$CA,$CC,$5D,$9D
  8366:          .byte   $83,$01,$D8,$D6,$CE,$3C,$3F,$91
  8367:  
  8368:          .byte   $A0,$DA,$C3,$C2,$CD,$3E,$01,$89
  8369:          .byte   $02,$D3,$C6,$C8,$CB,$5B
  8370:    .if CompileComputer >= VIC20_06
  8371:          .byte   $3D
  8372:    .else
  8373:          .byte   $BD
  8374:    .endif
  8375:          .byte       $8A
  8376:  
  8377:          .byte           $D1,$C5,$D4,$D5,$CF
  8378:    .if CompileComputer >= VIC20_06
  8379:          .byte                               $BA
  8380:    .else
  8381:          .byte                               $C0
  8382:    .endif
  8383:          .byte   $DE,$8B
  8384:  
  8385:          .byte           $22,$24,$26,$28
  8386:    .if CompileComputer >= VIC20_06
  8387:          .byte                           $30,$DD
  8388:    .else
  8389:          .byte                           $B0,$AD
  8390:    .endif
  8391:          .byte   $93,$8C
  8392:  
  8393:          .byte   $FF
  8394:  
  8395:  .endif
  8396:  
  8397:  KEYTAB_CBM:
  8398:  
  8399:  .if CompileComputer >= C64_GENERAL
  8400:  
  8401:    .if .defined(C64JAPAN)
  8402:          .byte   $94,$8D,$9D,$8C,$89,$8A,$8B,$91
  8403:          .byte   $B1,$C3,$C1,$B3,$C2,$C4,$B2,$01
  8404:          .byte   $B4,$BD,$BC,$B5,$BF,$CA,$B6,$BB
  8405:          .byte   $D4,$DD,$B7,$D5,$BA,$B8,$C5,$CB
  8406:  
  8407:          .byte   $D6,$C6,$CF,$DC,$D3,$C9,$D7,$D0
  8408:          .byte   $CE,$BE,$D8,$CD,$D9,$DA,$DB,$C8
  8409:          .byte   $A6,$DE,$B9,$93,$01,$D1,$DF,$D2
  8410:          .byte   $C7,$5F,$04,$CC,$A0,$02,$C0,$83
  8411:          .byte   $FF
  8412:    .else
  8413:          .byte   $94,$8D,$9D,$8C,$89,$8A,$8B,$91
  8414:          .byte   $96,$B3,$B0,$97,$AD,$AE,$B1,$01
  8415:          .byte   $98,$B2,$AC,$99,$BC,$BB,$A3,$BD
  8416:          .byte   $9A,$B7,$A5,$9B,$BF,$B4,$B8,$BE
  8417:  
  8418:          .byte   $29,$A2,$B5,$30,$A7,$A1,$B9,$AA
  8419:          .byte   $A6,$AF,$B6,$DC,$3E,$5B,$A4,$3C
  8420:          .byte   $A8,$DF,$5D,$93,$01,$3D,$DE,$3F
  8421:          .byte   $81,$5F,$04,$95,$A0,$02,$AB,$83
  8422:          .byte   $FF
  8423:    .endif
  8424:  
  8425:  .elseif CompileComputer = VIC20_02
  8426:          .byte   $B1,$B3,$B5,$B7,$B9,$AB,$DC,$94
  8427:          .byte   $DF,$D7,$D2,$D9,$C9,$D0,$AA,$8D
  8428:          .byte   $04,$C1,$C4,$C7,$CA,$CC,$BB,$9D
  8429:          .byte   $83,$01,$D8,$D6,$CE,$AC,$AF,$91
  8430:  
  8431:          .byte   $0A,$DA,$C3,$C2,$CD,$AE,$01,$FF
  8432:          .byte   $02,$D3,$C6,$C8,$CB,$BA,$BD,$FF
  8433:          .byte   $D1,$C5,$D4,$D5,$CF,$C0,$DE,$FF
  8434:          .byte   $B2,$B4,$B6,$B8,$B0,$AD,$93,$FF
  8435:          .byte   $FF
  8436:  .else
  8437:          .byte   $21,$23,$25,$27,$29,$A6,$A8,$94
  8438:          .byte   $5F,$B3,$B2,$B7,$A2,$AF,$DF,$8D
  8439:          .byte   $04,$B0,$AC,$A5,$B5,$B6,$5D,$9D
  8440:          .byte   $83,$01,$BD,$BE,$AA,$3C,$3F,$91
  8441:  
  8442:          .byte   $A0,$AD,$BC,$BF,$A7,$3E,$01,$89
  8443:          .byte   $02,$AE,$BB,$B4,$A1,$5B,$3D,$8A
  8444:          .byte   $AB,$B1,$A3,$B8,$B9,$A4,$DE,$8B
  8445:          .byte   $22,$24,$26,$28,$30,$DC,$93,$8C
  8446:          .byte   $FF
  8447:  .endif
  8448:  
  8449:  .if CompileComputer >= VIC20_06
  8450:  
  8451:  KEYTAB5:        ; unused, but references for VIC20-06 and -07
  8452:  
  8453:  EditorCheckForAscLowercase:
  8454:          cmp     #ASC_LOWERCASE                          ; if this the code to change to lowercase chars?
  8455:          bne     EditorCheckForAscUppercase              ; no, test for the next code
  8456:  
  8457:          ; set the VIC memory control byte to point to the lowercase characters:
  8458:  
  8459:    .if CompileComputer >= C64_GENERAL
  8460:          lda     VIC + VICII_O_MemControl
  8461:          ora     #2
  8462:          bne     EditorSta_vMemControl                   ; sta VIC + VICII_O_MemControl ; this bne saves one byte
  8463:    .else
  8464:          lda     #2
  8465:          ora     VIC + VICI_O_MemoryLocations
  8466:          sta     VIC + VICI_O_MemoryLocations
  8467:          jmp     CHROUT_SCREEN_END                       ; we're done
  8468:                                                          ; this JMP is not necessary, but does not do any harm, either.
  8469:                                                          ; It has been removed from the C64 ROMs, presumably to save space.
  8470:    .endif
  8471:  
  8472:  EditorCheckForAscUppercase:
  8473:          cmp     #ASC_UPPERCASE                          ; if this the code to change to lowercase chars?
  8474:          bne     EditorCheckForDisallowLowercase         ; no, test for the next code
  8475:  
  8476:          ; set the VIC memory control byte to point to the uppercase characters:
  8477:  
  8478:    .if CompileComputer >= C64_GENERAL
  8479:          lda     VIC + VICII_O_MemControl
  8480:          and     #~2
  8481:  EditorSta_vMemControl:
  8482:          sta     VIC + VICII_O_MemControl
  8483:    .else
  8484:          lda     #~2
  8485:          and     VIC + VICI_O_MemoryLocations
  8486:          sta     VIC + VICI_O_MemoryLocations
  8487:    .endif
  8488:  
  8489:  EditorChroutScreenEnd:
  8490:          jmp     CHROUT_SCREEN_END
  8491:          ; ----------------------------
  8492:  
  8493:  EditorCheckForDisallowLowercase:
  8494:          cmp     #ASC_DISALLOW_LOWERCASE                 ; if this the code to disallow changing to lowercase mode via keyboard?
  8495:          bne     @CheckForAllowLowercase                 ; no, test for the next code
  8496:  
  8497:          ; disallow changing mode with SHIFT + C= by setting bit 7 of lMODE:
  8498:  
  8499:          lda     #$80
  8500:          ora     lMODE
  8501:    .if CompileComputer >= C64_GENERAL
  8502:          bmi     @Sta_lMODE                              ; sta lMODE (uncond. branch)
  8503:          ; ------------------
  8504:    .else
  8505:          sta     lMODE
  8506:          bmi     EditorChroutScreenEnd
  8507:    .endif
  8508:  @CheckForAllowLowercase:
  8509:          cmp     #ASC_ALLOW_LOWERCASE                    ; if this the code to allow changing to lowercase mode via keyboard?
  8510:          bne     EditorChroutScreenEnd                   ; no -> branch, this is no special code (or it has been already handled)
  8511:  
  8512:          ; (re-)allow changing mode with SHIFT + C= by clearing bit 7 of lMODE:
  8513:  
  8514:          lda     #$7F
  8515:          and     lMODE
  8516:  @Sta_lMODE:
  8517:          sta     lMODE
  8518:  
  8519:          ; end chrout to the screen.
  8520:          ; the VIC-20 and C64 do exactly the same.
  8521:  
  8522:    .if CompileComputer >= C64_GENERAL
  8523:          jmp     CHROUT_SCREEN_END
  8524:    .else
  8525:          bpl     EditorChroutScreenEnd                   ; branches to a "JMP CHROUT_SCREEN_END" (uncond. branch)
  8526:          ; ------------------------------
  8527:  
  8528:          ; a patch: cf. directly before EditorPatchLogicallyCombineTwoRows_Return
  8529:  
  8530:  EditorPatchLogicallyCombineTwoRows:
  8531:          EDITOR_PATCH_LogicallyCombineTwoRows_FIX
  8532:          EDITOR_PATCH_LogicallyCombineTwoRows_COMMON
  8533:          jmp     EditorPatchLogicallyCombineTwoRows_Return
  8534:  
  8535:    .endif
  8536:  .endif
  8537:  
  8538:  .if CompileComputer = VIC20_02
  8539:  
  8540:  KEYTAB5:
  8541:  
  8542:          .byte   $C7,$B1,$B4,$D4,$D6,$CE,$A6,$14
  8543:          .byte   $FF,$C3,$EC,$DD,$C6,$BE,$EA,$0D
  8544:          .byte   $04,$C1,$BC,$B7,$CF,$D8,$B9,$1D
  8545:          .byte   $03,$01,$BB,$CB,$D0,$C8,$D2,$11
  8546:          .byte   $20,$C2,$BF,$BA,$D3,$D9,$01,$85
  8547:          .byte   $02,$C4,$CA,$B8,$C9,$DA,$D1,$86
  8548:          .byte   $C0,$B2,$B6,$C5,$D7,$DB,$A1,$87
  8549:          .byte   $CC,$B3,$B5,$D5,$DC,$CD,$13,$88
  8550:          .byte   $FF
  8551:  .endif
  8552:  
  8553:  KEYTAB6:
  8554:  
  8555:  .if CompileComputer = VIC20_02
  8556:  
  8557:          .byte   $F1,$F3,$F5,$FF,$FF,$EB,$FF,$94
  8558:          .byte   $FF,$FF,$FF,$FF,$FF,$FF,$FF,$8D
  8559:          .byte   $04,$FF,$FF,$FF,$FF,$FF,$E2,$9D
  8560:          .byte   $83,$01,$FF,$FF,$FF,$FF,$FF,$91
  8561:          .byte   $A0,$FF,$FF,$FF,$FF,$EE,$01,$89
  8562:          .byte   $02,$FF,$FF,$FF,$FF,$E1,$FD,$8A
  8563:          .byte   $FF,$FF,$FF,$FF,$FF,$B0,$E0,$8B
  8564:          .byte   $F2,$F4,$F6,$FF,$F0,$ED,$93,$8C
  8565:          .byte   $FF
  8566:  
  8567:  .elseif CompileComputer < C64_GENERAL
  8568:  
  8569:          ; unused, but present
  8570:  
  8571:          .byte   $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
  8572:          .byte   $FF,$04,$FF,$FF,$FF,$FF,$FF,$E2
  8573:          .byte   $9D,$83,$01,$FF,$FF,$FF,$FF,$FF
  8574:          .byte   $91,$A0,$FF,$FF,$FF,$FF,$EE,$01
  8575:          .byte   $89,$02,$FF,$FF,$FF,$FF,$E1,$FD
  8576:          .byte   $8A,$FF,$FF,$FF,$FF,$FF,$B0,$E0
  8577:          .byte   $8B,$F2,$F4,$F6,$FF,$F0,$ED,$93
  8578:          .byte   $8C,$FF
  8579:  
  8580:  .endif
  8581:  
  8582:  KEYTAB_CTRL:
  8583:  
  8584:  .if CompileComputer >= C64_GENERAL
  8585:  
  8586:    .if .defined(C64JAPAN)
  8587:          .byte   $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
  8588:          .byte   $1C,$95,$01,$9F,$1A,$13,$96,$FF
  8589:          .byte   $9C,$97,$04,$1E,$03,$06,$98,$18
  8590:          .byte   $1F,$99,$07,$9E,$02,$08,$9A,$16
  8591:  
  8592:          .byte   $12,$9B,$0A,$92,$0D,$0B,$0F,$0E
  8593:          .byte   $08,$10,$0C,$09,$11,$14,$00,$09
  8594:          .byte   $FF,$05,$15,$FF,$FF,$17,$19,$12
  8595:          .byte   $90,$06,$FF,$05,$FF,$FF,$81,$FF
  8596:          .byte   $FF
  8597:    .else
  8598:          .byte   $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
  8599:          .byte   $1C,$17,$01,$9F,$1A,$13,$05,$FF
  8600:          .byte   $9C,$12,$04,$1E,$03,$06,$14,$18
  8601:          .byte   $1F,$19,$07,$9E,$02,$08,$15,$16
  8602:  
  8603:          .byte   $12,$09,$0A,$92,$0D,$0B,$0F,$0E
  8604:          .byte   $FF,$10,$0C,$FF,$FF,$1B,$00,$FF
  8605:          .byte   $1C,$FF,$1D,$FF,$FF,$1F,$1E,$FF
  8606:          .byte   $90,$06,$FF,$05,$FF,$FF,$11,$FF
  8607:          .byte   $FF
  8608:    .endif
  8609:  
  8610:  .else
  8611:  
  8612:          .byte   $90,$1C,$9C,$1F
  8613:    .if CompileComputer = VIC20_02
  8614:          .byte                   $FF
  8615:    .else
  8616:          .byte                   $12
  8617:    .endif
  8618:          .byte                       $FF,$FF,$FF
  8619:    .if CompileComputer = VIC20_02
  8620:          .byte   $FF
  8621:    .else
  8622:          .byte   $06
  8623:    .endif
  8624:          .byte       $FF,$12,$FF,$FF,$FF,$FF,$FF
  8625:          .byte   $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
  8626:          .byte   $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
  8627:          .byte   $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
  8628:          .byte   $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
  8629:          .byte   $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF
  8630:          .byte   $05,$9F,$1E,$9E,$92,$FF,$FF,$FF
  8631:          .byte   $FF
  8632:  
  8633:  .endif
  8634:  
  8635:  VIC_DEFAULTS:
  8636:  
  8637:          ; the default values for the VIC or VIC-II
  8638:          ; these will be copied in a loop into the
  8639:          ; VIC or VIC-II register when initialising the VIC(-II)
  8640:          ;
  8641:  
  8642:  .if CompileComputer >= C64_GENERAL
  8643:  
  8644:          .byte   $00,$00,$00,$00,$00,$00,$00,$00
  8645:          .byte   $00,$00,$00,$00,$00,$00,$00,$00
  8646:          .byte   $00
  8647:    .if CompileComputer >= C64_02
  8648:          .byte       $1B | (>311 .SHL 7) ,<311
  8649:    .else
  8650:          .byte       $1B,$00
  8651:    .endif
  8652:          .byte               $00,$00,$00,$08,$00
  8653:          .byte   $14
  8654:    .if CompileComputer >= C64_02
  8655:          .byte       $0F
  8656:    .else
  8657:          .byte       $00
  8658:    .endif
  8659:          .byte           $00,$00,$00,$00,$00,$00
  8660:  
  8661:          .byte   SET_COLOR_FRAME,SET_COLOR_BACKGROUND
  8662:    .if CompileComputer = C64_4064
  8663:          .byte           $00,$00,$00,$00,$00
  8664:          .byte   $00,$00,$00,$00,$00,$00,$00
  8665:    .else
  8666:          .byte           $01,$02,$03,$04,$00
  8667:          .byte   $01,$02,$03,$04,$05,$06,$07
  8668:    .endif
  8669:  
  8670:  .else
  8671:  
  8672:    .if CompileComputer >= VIC20_07
  8673:          .byte   $0C,$26
  8674:    .else
  8675:          .byte   $05,$19
  8676:    .endif
  8677:          .byte           $16,$2E,$00,$C0,$00,$00
  8678:          .byte   $00,$00,$00,$00,$00,$00,$00
  8679:  
  8680:  .endif
  8681:  
  8682:  END_VIC_DEFAULTS:
  8683:  
  8684:  .if CompileComputer < C64_GENERAL
  8685:  
  8686:          .byte   $1B                     ; TODO unused?
  8687:  
  8688:  .endif
  8689:  
  8690:  TEXT_LOADRUN:
  8691:          .byte   "LOAD",ASC_CR
  8692:          .byte   "RUN",ASC_CR
  8693:  END_TEXT_LOADRUN:
  8694:  
  8695:  SCREEN_LOWBYTE:
  8696:  
  8697:          ; the low bytes of the screen addresses
  8698:  
  8699:      .repeat EDITOR_ROWS,i
  8700:          .byte   <(i*EDITOR_COLS)
  8701:      .endrep
  8702:  
  8703:  ;       .include "../kernal/iec.a65"
  8704:  ;  B-34. Function Name: TALK
  8705:  ;
  8706:  ;    Purpose: Command a device on the serial bus to TALK
  8707:  ;    Call address: $FFB4 (hex) 65460 (decimal)
  8708:  ;    Communication registers: A
  8709:  ;    Preparatory routines: None
  8710:  ;    Error returns: See READST
  8711:  ;    Stack requirements: 8
  8712:  ;    Registers affected: A
  8713:  ;
  8714:  ;    Description: To use this routine the accumulator must first be loaded
  8715:  ;  with a device number between 0 and 31. When called, this routine then
  8716:  ;  ORs bit by bit to convert this device number to a talk address. Then this
  8717:  ;  data is transmitted as a command on the serial bus.
  8718:  ;
  8719:  ;  How to Use:
  8720:  ;
  8721:  ;    1) Load the accumulator with the device number.
  8722:  ;    2) Call this routine.
  8723:  ;
  8724:  ;  EXAMPLE:
  8725:  ;
  8726:  ;    ;COMMAND DEVICE #4 TO TALK
  8727:  ;    LDA #4
  8728:  ;    JSR TALK
  8729:  ;
  8730:  iTALK:
  8731:          ora     #IEEE_TALK                      ; create primary address for TALK
  8732:  
  8733:          .byte   ASM_BIT3                        ; hide next instruction
  8734:  
  8735:  ;  B-14. Function Name: LISTEN
  8736:  ;
  8737:  ;    Purpose: Command a device on the serial bus to listen
  8738:  ;    Call Address: $FFB1 (hex) 65457 (decimal)
  8739:  ;    Communication registers: A
  8740:  ;    Preparatory routines: None
  8741:  ;    Error returns: See READST
  8742:  ;    Stack requirements: None
  8743:  ;    Registers affected: A
  8744:  ;
  8745:  ;    Description: This routine will command a device on the serial bus to
  8746:  ;  receive data. The accumulator must be loaded with a device number between
  8747:  ;  0 and 31 before calling the routine. LISTEN will OR the number bit by bit
  8748:  ;  to convert to a listen address, then transmits this data as a command on
  8749:  ;  the serial bus. The specified device will then go into listen mode, and
  8750:  ;  be ready to accept information.
  8751:  ;
  8752:  ;  How to Use:
  8753:  ;    1) Load the accumulator with the number of the device to command
  8754:  ;       to LISTEN.
  8755:  ;    2) Call this routine using the JSR instruction.
  8756:  ;
  8757:  ;  EXAMPLE:
  8758:  ;    ;COMMAND DEVICE #8 TO LISTEN
  8759:  ;    LDA #8
  8760:  ;    JSR LISTEN
  8761:  ;
  8762:  ;
  8763:  iLISTEN:
  8764:          ora     #IEEE_LISTEN                    ; create primary address for TALK
  8765:          jsr     LF0A4                           ; TODO (assumed: Wait for RS232 transmission to stop)
  8766:  
  8767:  IecOutputCommand:
  8768:          pha                                     ; remember byte to be output
  8769:  
  8770:          bit     zC3PO                           ; test: Is there already some character in the output buffer?
  8771:          bpl     @BufferByte                     ; no -> branch, do not output but put the byte into the buffer instead
  8772:  
  8773:          ; there is some byte in the output buffer.
  8774:          ; output it on the IEC bus.
  8775:  
  8776:          sec
  8777:          ror     zTSFCNT                         ; set zTSFCNT.7, thus: Signal an EOI on output
  8778:  
  8779:  .ifdef JIFFY
  8780:          jsr     JDLFBFE
  8781:  .else
  8782:          jsr     IecOutputByte                           ; output a byte on IEC bus
  8783:  .endif
  8784:  
  8785:          ; IecOutputByte returns with C == 0
  8786:          lsr     zC3PO                           ; unset zC3PO.7, thus:
  8787:                                                  ; mark: There is no byte in the buffer
  8788:          lsr     zTSFCNT                         ; unset zTSFCNT.7. Subsequent bytes will not be signalled with EOI
  8789:  
  8790:  @BufferByte:
  8791:          ; here, zC3PO.7 is unset.
  8792:          ; Either we jumped here because of the bpl, or it was specifically unset two lines above
  8793:  
  8794:          ; Thus, the buffer is already marked as empty
  8795:  
  8796:          pla                                     ; get back the byte to be output
  8797:          sta     zBSOUR                          ; and store it into the output buffer
  8798:  
  8799:  .if CompileComputer >= C64_GENERAL
  8800:          sei                                     ; make sure the interrupt does not disturb our timing
  8801:  
  8802:                                                  ; it is not completely clear if this command is missing
  8803:                                                  ; on the VIC20, or if it is not critical there, as the VIC20
  8804:                                                  ; does not have badlines, which might help the timing here.
  8805:  .endif
  8806:  
  8807:          ; TODO: document
  8808:  .ifdef JIFFY
  8809:          jsr     JDLF0ED
  8810:  .else
  8811:          jsr     IecDataClear
  8812:  .endif
  8813:  
  8814:          cmp     #IEEE_UNLISTEN
  8815:          bne     @NotUNLISTEN
  8816:  
  8817:          jsr     IecClkClear
  8818:  
  8819:  @NotUNLISTEN:
  8820:  
  8821:          ; set ATN state
  8822:  
  8823:          lda     IEC_REG_ATN_OUT
  8824:          ora     #IEC_B_ATN_OUT
  8825:          sta     IEC_REG_ATN_OUT
  8826:  
  8827:  IecOutputByte2:
  8828:  .if CompileComputer >= C64_GENERAL
  8829:          sei                                     ; make sure the interrupt does not disturb our timing
  8830:  
  8831:                                                  ; it is not completely clear if this command is missing
  8832:                                                  ; on the VIC20, or if it is not critical there, as the VIC20
  8833:                                                  ; does not have badlines, which might help the timing here.
  8834:  .endif
  8835:          jsr     IecClkSet
  8836:          jsr     IecDataClear
  8837:          jsr     IecDelay1ms
  8838:  
  8839:  
  8840:  
  8841:  IecOutputByte:
  8842:          sei                                     ; make sure the interrupt does not disturb our timing
  8843:  
  8844:  .if CompileComputer >= VIC20_06
  8845:          jsr     IecDataClear
  8846:  .endif
  8847:  
  8848:          jsr     IecGetDataClockIn
  8849:          IEC_GET_DATA_INTO_CARRY
  8850:          bcs     @DeviceNotPresent
  8851:          jsr     IecClkClear
  8852:          bit     zTSFCNT
  8853:          bpl     @LED5A
  8854:  
  8855:  @WaitDataInactive:
  8856:          jsr     IecGetDataClockIn
  8857:          IEC_GET_DATA_INTO_CARRY
  8858:          bcc     @WaitDataInactive
  8859:  
  8860:  @WaitDataActive:
  8861:          jsr     IecGetDataClockIn
  8862:          IEC_GET_DATA_INTO_CARRY
  8863:          bcs     @WaitDataActive
  8864:  
  8865:  @LED5A:
  8866:          jsr     IecGetDataClockIn
  8867:          IEC_GET_DATA_INTO_CARRY
  8868:          bcc     @LED5A
  8869:  
  8870:          jsr     IecClkSet
  8871:  
  8872:  .ifdef JIFFY
  8873:          txa
  8874:          pha
  8875:          ldx     #8
  8876:  .else
  8877:          lda     #8                                      ; number of bits to be output
  8878:          sta     zCNTDN
  8879:  .endif
  8880:  
  8881:  @NextBit:
  8882:  
  8883:  .ifdef JIFFY
  8884:          pha
  8885:          pla
  8886:          bit     IEC_REG
  8887:          bmi     @JDLED72
  8888:          pla
  8889:          tax
  8890:          jmp     SendTimeout
  8891:  
  8892:  @JDLED72:
  8893:          jsr     IecDataClear
  8894:          ror     zBSOUR
  8895:          bcs     @JDLED7C
  8896:          jsr     IecDataSet
  8897:  
  8898:  @JDLED7C:
  8899:          jsr     IecClkClear
  8900:          lda     IEC_REG
  8901:          and     # ~ IEC_B_DATA_OUT
  8902:          ora     #IEC_B_CLK_OUT
  8903:          php
  8904:          pha
  8905:          jsr     JDLF8EA
  8906:          pla
  8907:          plp
  8908:          dex
  8909:          bne     @NextBit
  8910:          pla
  8911:          tax
  8912:  
  8913:  .else
  8914:          lda     IEC_REG_DATA_CLK_IN
  8915:          cmp     IEC_REG_DATA_CLK_IN
  8916:          bne     @NextBit                                ; wait for IEC register to settle (TODO entprellen)
  8917:          IEC_REG__DATA_IN_INTO_CARRY
  8918:          bcc     SendTimeout                             ; data set (inactive) -> something/someone else is messing with us, there is a transmission problem -> branch
  8919:  
  8920:          ror     zBSOUR                                  ; next bit to output (LSB) into C
  8921:          bcs     @OutputData1                            ; is it set -> output a "1" (inactive) on the IEC bus data line
  8922:          jsr     IecDataSet                              ; it was not set -> output a "0" (active) on the IEC bus data line
  8923:          bne     @ContinueAfterOutputData                ; skip next command
  8924:  
  8925:  @OutputData1:
  8926:          jsr     IecDataClear                            ; output a "1" (inactive) on the IEC bus data line
  8927:  
  8928:  @ContinueAfterOutputData:
  8929:          jsr     IecClkClear                             ; clear clock to indicate: Data has been set accordingly
  8930:  
  8931:          ; delay 8 (4*2) clock cycles, giving the other side time to read the value in
  8932:          nop
  8933:          nop
  8934:          nop
  8935:          nop
  8936:  
  8937:          ; clear DATA and set Clock again, indicating the bit is not available anymore
  8938:          lda     IEC_REG_DATA_CLK_OUT
  8939:          and     #~IEC_B_DATA_OUT
  8940:          ora     #IEC_B_CLK_OUT
  8941:          sta     IEC_REG_DATA_CLK_OUT
  8942:  
  8943:          dec     zCNTDN                                  ; still bits to be output?
  8944:          bne     @NextBit                                ; yes -> branch -> process the next bit
  8945:  .endif
  8946:  
  8947:          ; TODO document
  8948:  
  8949:          ; wait for acknowledgement from other side
  8950:  
  8951:          lda     #>$0400                                 ; set timer to approx. 1000 Ás ( = 1 ms)
  8952:          sta     IEC_TIMER_HI
  8953:  
  8954:  .if CompileComputer >= C64_GENERAL
  8955:  
  8956:          ; start timer B with one-shot mode, no PB7, counting PHI2
  8957:          lda     #CIA_CRB_B_START | CIA_CRB_B_ONESHOT | CIA_CRB_B_FORCE_LOAD
  8958:          sta     CIA1 + CIA_O_CRB
  8959:  
  8960:          lda     IEC_TIMER_FLAG_REG                      ; make sure the ICR is cleared, so we do not
  8961:                                                          ; immediately stop the following loop because
  8962:                                                          ; some other TB underflow condition has occurred before
  8963:  .endif
  8964:  
  8965:  
  8966:  @WaitForAck:
  8967:          lda     IEC_TIMER_FLAG_REG
  8968:          and     #IEC_TIMER_FLAG_B
  8969:          bne     SendTimeout
  8970:          jsr     IecGetDataClockIn
  8971:          IEC_GET_DATA_INTO_CARRY
  8972:          bcs     @WaitForAck
  8973:          cli
  8974:          rts
  8975:  
  8976:  
  8977:  @DeviceNotPresent:
  8978:          lda     #$80                            ; set bit: device not present error
  8979:  
  8980:          .byte   ASM_BIT3                        ; hide the next instruction
  8981:  
  8982:  SendTimeout:
  8983:          lda     #$03                            ; set bits: read timeout and write timeout
  8984:  
  8985:  IecSetStatusAndFreeBus:
  8986:          jsr     SetStatus                       ; set the status bits
  8987:  
  8988:  .if CompileComputer = VIC20_02
  8989:          jsr     IEC_CLR_ATN
  8990:          jsr     IecClkSet
  8991:  .endif
  8992:  
  8993:          cli
  8994:  .if CompileComputer >= VIC20_06
  8995:          clc
  8996:          bcc     IecClearAtnAndClockAndDataAfterDelay
  8997:          ; ------------------
  8998:  .else
  8999:          jmp     IecDataClear
  9000:          ; ------------------
  9001:  .endif
  9002:  
  9003:  ;  B-27. Function Name: SECOND
  9004:  ;
  9005:  ;    Purpose: Send secondary address for LISTEN
  9006:  ;    Call address: $FF93 (hex) 65427 (decimal)
  9007:  ;    Communication registers: A
  9008:  ;    Preparatory routines: LISTEN
  9009:  ;    Error returns: See READST
  9010:  ;    Stack requirements: 8
  9011:  ;    Registers affected: A
  9012:  ;
  9013:  ;    Description: This routine is used to send a secondary address to an
  9014:  ;  I/O device after a call to the LISTEN routine is made, and the device is
  9015:  ;  commanded to LISTEN. The routine canNOT be used to send a secondary
  9016:  ;  address after a call to the TALK routine.
  9017:  ;    A secondary address is usually used to give setup information to a
  9018:  ;  device before I/O operations begin.
  9019:  ;    When a secondary address is to be sent to a device on the serial bus,
  9020:  ;  the address must first be ORed with $60.
  9021:  ;
  9022:  ;  How to Use:
  9023:  ;
  9024:  ;    1) load the accumulator with the secondary address to be sent.
  9025:  ;    2) Call this routine.
  9026:  ;
  9027:  ;  EXAMPLE:
  9028:  ;
  9029:  ;    ;ADDRESS DEVICE #8 WITH COMMAND (SECONDARY ADDRESS) #15
  9030:  ;    LDA #8
  9031:  ;    JSR LISTEN
  9032:  ;    LDA #15
  9033:  ;    JSR SECOND
  9034:  ;
  9035:  ;
  9036:  iSECOND:
  9037:          sta     zBSOUR                  ; byte (secondary address after LISTEN) to be output
  9038:          jsr     IecOutputByte2
  9039:  
  9040:  IEC_CLR_ATN:
  9041:  
  9042:          ; clear ATN state
  9043:          lda     IEC_REG_ATN_OUT
  9044:          and     #~IEC_B_ATN_OUT
  9045:          sta     IEC_REG_ATN_OUT
  9046:  
  9047:          rts
  9048:  
  9049:  ;  B-35. Function Name: TKSA
  9050:  ;
  9051:  ;    Purpose: Send a secondary address to a device commanded to TALK
  9052:  ;    Call address: $FF96 (hex) 65430 (decimal)
  9053:  ;    Communication registers: A
  9054:  ;    Preparatory routines: TALK
  9055:  ;    Error returns: See READST
  9056:  ;    Stack requirements: 8
  9057:  ;    Registers affected: A
  9058:  ;
  9059:  ;
  9060:  ;
  9061:  ;    Description: This routine transmits a secondary address on the serial
  9062:  ;  bus for a TALK device. This routine must be called with a number between
  9063:  ;  0 and 31 in the accumulator. The routine sends this number as a secondary
  9064:  ;  address command over the serial bus. This routine can only be called
  9065:  ;  after a call to the TALK routine. It will not work after a LISTEN.
  9066:  ;
  9067:  ;  How to Use:
  9068:  ;
  9069:  ;    0) Use the TALK routine.
  9070:  ;    1) Load the accumulator with the secondary address.
  9071:  ;    2) Call this routine.
  9072:  ;
  9073:  ;  EXAMPLE:
  9074:  ;
  9075:  ;    ;TELL DEVICE #4 TO TALK WITH COMMAND #7
  9076:  ;    LDA #4
  9077:  ;    JSR TALK
  9078:  ;    LDA #7
  9079:  ;    JSR TALKSA
  9080:  ;
  9081:  iTKSA:
  9082:          sta     zBSOUR                  ; byte (secondary address after TALK) to be output
  9083:          jsr     IecOutputByte2
  9084:  
  9085:  ; perform talk - listener - change (TODO)
  9086:  
  9087:  iTKSA2:
  9088:          sei
  9089:          jsr     IecDataSet
  9090:          jsr     IEC_CLR_ATN
  9091:          jsr     IecClkClear
  9092:  
  9093:  @LEDD6:
  9094:  .ifdef JIFFY
  9095:          bit     IEC_REG
  9096:  .else
  9097:          jsr     IecGetDataClockIn
  9098:  .endif
  9099:  
  9100:  .ifdef JIFFY
  9101:          bvs     @LEDD6
  9102:  .elseif CompileComputer >= C64_GENERAL
  9103:          bmi     @LEDD6
  9104:  .else
  9105:          bcs     @LEDD6
  9106:  .endif
  9107:          cli
  9108:          rts
  9109:  
  9110:  ;  B-6. Function Name: CIOUT
  9111:  ;
  9112:  ;    Purpose: Transmit a byte over the serial bus
  9113:  ;    Call address: $FFA8 (hex) 65448 (decimal)
  9114:  ;    Communication registers: A
  9115:  ;    Preparatory routines: LISTEN, [SECOND]
  9116:  ;    Error returns: See READST
  9117:  ;    Stack requirements: 5
  9118:  ;    Registers affected: None
  9119:  ;
  9120:  ;    Description: This routine is used to send information to devices on the
  9121:  ;  serial bus. A call to this routine will put a data byte onto the serial
  9122:  ;  bus using full serial handshaking. Before this routine is called, the
  9123:  ;  LISTEN KERNAL routine must be used to command a device on the serial bus
  9124:  ;  to get ready to receive data. (If a device needs a secondary address, it
  9125:  ;  must also be sent by using the SECOND KERNAL routine.) The accumulator is
  9126:  ;  loaded with a byte to handshake as data on the serial bus. A device must
  9127:  ;  be listening or the status word will return a timeout. This routine
  9128:  ;  always buffers one character. (The routine holds the previous character
  9129:  ;  to be sent back.) So when a call to the KERNAL UNLSN routine is made to
  9130:  ;  end the data transmission, the buffered character is sent with an End Or
  9131:  ;  Identify (EOI) set. Then the UNLSN command is sent to the device.
  9132:  ;
  9133:  ;  How to Use:
  9134:  ;
  9135:  ;    0) Use the LISTEN KERNAL routine (and the SECOND routine if needed).
  9136:  ;    1) Load the accumulator with a byte of data.
  9137:  ;    2) Call this routine to send the data byte.
  9138:  ;
  9139:  ;  EXAMPLE:
  9140:  ;
  9141:  ;
  9142:  ;    LDA #'X       ;SEND AN X TO THE SERIAL BUS
  9143:  ;    JSR CIOUT
  9144:  ;
  9145:  ;
  9146:  iCIOUT:
  9147:          bit     zC3PO                                   ; check if there is already a byte buffered to be output
  9148:          bmi     @SendBufferedChar                       ; there is one -> branch, send it
  9149:  
  9150:          sec                                             ; there was none -> set bit 7 to mark that we now have a byte to be output
  9151:          ror     zC3PO
  9152:  
  9153:          bne     @NoCached                               ; uncond. branch: store the next byte to be output
  9154:          ; ------------------
  9155:  
  9156:  @SendBufferedChar:
  9157:          pha                                             ; remember the new byte to be output
  9158:  .ifdef JIFFY
  9159:          jsr     $FBFE
  9160:  .else
  9161:          jsr     IecOutputByte                           ; output the old buffered byte
  9162:  .endif
  9163:          pla                                             ; get back the new byte to be output
  9164:  
  9165:  @NoCached:
  9166:          sta     zBSOUR                                  ; store the new byte to be output on the next call
  9167:  
  9168:          clc                                             ; mark: no error
  9169:          rts
  9170:          ; ------------------
  9171:  
  9172:  
  9173:  ;  B-38. Function Name: UNTLK
  9174:  ;
  9175:  ;    Purpose: Send an UNTALK command
  9176:  ;    Call address: $FFAB (hex) 65451 (decimal)
  9177:  ;    Communication registers: None
  9178:  ;    Preparatory routines: None
  9179:  ;    Error returns: See READST
  9180:  ;    Stack requirements: 8
  9181:  ;    Registers affected: A
  9182:  ;
  9183:  ;    Description: This routine transmits an UNTALK command on the serial
  9184:  ;  bus. All devices previously set to TALK will stop sending data when this
  9185:  ;  command is received.
  9186:  ;
  9187:  ;  How to Use:
  9188:  ;    1) Call this routine.
  9189:  ;
  9190:  ;
  9191:  ;  EXAMPLE:
  9192:  ;    JSR UNTALK
  9193:  ;
  9194:  iUNTLK:
  9195:  .if CompileComputer >= C64_GENERAL
  9196:          sei
  9197:  .endif
  9198:  
  9199:          ; make sure to signal the talker that we will take over the bus now!
  9200:  
  9201:  .ifdef JIFFY
  9202:  .else
  9203:          jsr     IecClkSet
  9204:  .endif
  9205:  
  9206:          ; set ATN state
  9207:  
  9208:          lda     IEC_REG_ATN_OUT
  9209:          ora     #IEC_B_ATN_OUT
  9210:          sta     IEC_REG_ATN_OUT
  9211:  
  9212:  .ifdef JIFFY
  9213:          jsr     IecClkSet
  9214:  .endif
  9215:  
  9216:          lda     #IEEE_UNTALK                    ; set command byte: UNTALK
  9217:  
  9218:          .byte   ASM_BIT3                        ; hide the next instruction
  9219:  
  9220:  ;  B-37. Function Name: UNLSN
  9221:  ;
  9222:  ;    Purpose: Send an UNLISTEN command
  9223:  ;    Call address: $FFAE (hex) 65454 (decimal)
  9224:  ;    Communication registers: None
  9225:  ;    Preparatory routines: None
  9226:  ;    Error returns: See READST
  9227:  ;    Stack requirements: 8
  9228:  ;    Registers affected: A
  9229:  ;
  9230:  ;    Description: This routine commands all devices on the serial bus to
  9231:  ;  stop receiving data from the Commodore 64 (i.e., UNLISTEN). Calling this
  9232:  ;  routine results in an UNLISTEN command being transmitted on the serial
  9233:  ;  bus. Only devices previously commanded to listen are affected. This
  9234:  ;  routine is normally used after the Commodore 64 is finished sending data
  9235:  ;  to external devices. Sending the UNLISTEN commands the listening devices
  9236:  ;  to get off the serial bus so it can be used for other purposes.
  9237:  ;
  9238:  ;  How to Use:
  9239:  ;    1) Call this routine.
  9240:  ;
  9241:  ;  EXAMPLE:
  9242:  ;    JSR UNLSN
  9243:  ;
  9244:  iUNLSN:
  9245:          lda     #IEEE_UNLISTEN                  ; set command byte: UNLISTEN
  9246:  
  9247:          jsr     IecOutputCommand                ; output the command byte on the IEC bus
  9248:  
  9249:  .if CompileComputer = VIC20_02
  9250:          bne     IEC_CLR_ATN                     ; done (bug)
  9251:          ; ---------------------
  9252:  .else
  9253:  
  9254:  IecClearAtnAndClockAndDataAfterDelay:
  9255:          jsr     IEC_CLR_ATN                     ; clear ATN
  9256:  
  9257:          ; TODO document
  9258:  
  9259:  IecClearClockAndDataAfterDelay:
  9260:          txa
  9261:    .if CompileComputer >= C64_GENERAL
  9262:          ; TODO define
  9263:          ldx     #10
  9264:    .else
  9265:          ldx     #11
  9266:    .endif
  9267:  @Delay: dex
  9268:          bne     @Delay
  9269:          tax
  9270:          jsr     IecClkClear
  9271:          jmp     IecDataClear
  9272:  .endif
  9273:  
  9274:  ;  B-1. Function Name: ACPTR
  9275:  ;
  9276:  ;    Purpose: Get data from the serial bus
  9277:  ;    Call address: $FFA5 (hex) 65445 (decimal)
  9278:  ;    Communication registers: A
  9279:  ;    Preparatory routines: TALK, TKSA
  9280:  ;    Error returns: See READST
  9281:  ;    Stack requirements: 13
  9282:  ;    Registers affected: A, X
  9283:  ;
  9284:  ;
  9285:  ;
  9286:  ;    Description: This is the routine to use when you want to get informa-
  9287:  ;  tion from a device on the serial bus, like a disk. This routine gets a
  9288:  ;  byte of data off the serial bus using full handshaking. The data is
  9289:  ;  returned in the accumulator. To prepare for this routine the TALK routine
  9290:  ;  must be called first to command the device on the serial bus to send data
  9291:  ;  through the bus. If the input device needs a secondary command, it must
  9292:  ;  be sent by using the TKSA KERNAL routine before calling this routine.
  9293:  ;  Errors are returned in the status word. The READST routine is used to
  9294:  ;  read the status word.
  9295:  ;
  9296:  ;
  9297:  ;  How to Use:
  9298:  ;
  9299:  ;    0) Command a device on the serial bus to prepare to send data to
  9300:  ;       the Commodore 64. (Use the TALK and TKSA KERNAL routines.)
  9301:  ;    1) Call this routine (using JSR).
  9302:  ;    2) Store or otherwise use the data.
  9303:  ;
  9304:  ;
  9305:  ;  EXAMPLE:
  9306:  ;
  9307:  ;    ;GET A BYTE FROM THE BUS
  9308:  ;    JSR ACPTR
  9309:  ;    STA DATA
  9310:  ;
  9311:  ;
  9312:  ;
  9313:  iACPTR:
  9314:  .ifdef JIFFY
  9315:          jmp     $FBAA
  9316:  
  9317:  .else
  9318:  
  9319:          sei                                     ; make sure to be able to hold the timing
  9320:  
  9321:    .if CompileComputer < VIC20_06
  9322:          lda     #8                              ; 8 bits to be input
  9323:    .else
  9324:          lda     #0                              ; TODO: ???
  9325:    .endif
  9326:  .endif
  9327:  
  9328:  JDiACPTR:
  9329:          sta     zCNTDN                          ; and store it as counter
  9330:  
  9331:  
  9332:  
  9333:  .if CompileComputer >= VIC20_06
  9334:          jsr     IecClkClear                     ; clear CLOCK to signal: We are ready to handle the byte
  9335:  .endif
  9336:  
  9337:  
  9338:  @WaitDataInactive:
  9339:  
  9340:          ; wait for DATA to become inactive:
  9341:          ; That is, wait for the other side to be ready to send a byte
  9342:  
  9343:          jsr     IecGetDataClockIn
  9344:  .if CompileComputer >= C64_GENERAL
  9345:          bpl     @WaitDataInactive
  9346:  .else
  9347:          bcc     @WaitDataInactive
  9348:          jsr     IecDataClear                    ; clear DATA (unnecessary, as the loop would not terminate if we would not have data cleared!)
  9349:  .endif
  9350:  
  9351:  @LEE20:
  9352:  
  9353:          lda     #>$0100                         ; set timer to approx. 250 Ás
  9354:          sta     IEC_TIMER_HI
  9355:  
  9356:  .if CompileComputer >= C64_GENERAL
  9357:          ; start timer B with one-shot mode, no PB7, counting PHI2
  9358:          lda     #CIA_CRB_B_START | CIA_CRB_B_ONESHOT | CIA_CRB_B_FORCE_LOAD
  9359:          sta     CIA1 + CIA_O_CRB
  9360:  
  9361:          jsr     IecDataClear                    ; clear DATA
  9362:  
  9363:          lda     IEC_TIMER_FLAG_REG              ; make sure the ICR is cleared, so we do not
  9364:                                                  ; immediately stop the following loop because
  9365:                                                  ; some other TB underflow condition has occurred before
  9366:  
  9367:  .endif
  9368:  
  9369:  @LEE30: lda     IEC_TIMER_FLAG_REG
  9370:          and     #IEC_TIMER_FLAG_B
  9371:          bne     @LEE3E
  9372:  
  9373:          jsr     IecGetDataClockIn
  9374:  
  9375:  .if CompileComputer >= C64_GENERAL
  9376:          bmi     @LEE30
  9377:          bpl     @LEE56
  9378:  .else
  9379:          bcs     @LEE30
  9380:          bcc     @LEE56
  9381:  .endif
  9382:  
  9383:  
  9384:  @LEE3E:
  9385:  
  9386:  .if CompileComputer = VIC20_02
  9387:  
  9388:          jsr     IecDataSet
  9389:          txa
  9390:          ldx     #$10
  9391:  @Delay: dex
  9392:          bne     @Delay
  9393:          tax
  9394:          jsr     IecDataClear
  9395:          jsr     IecGetDataClockIn
  9396:  
  9397:          lda     #$40                                    ; status bit: EOI
  9398:          jsr     SetStatus                               ; set the status to EOI
  9399:  
  9400:  @LEE56: lda     IEC_REG_DATA_CLK_IN
  9401:          cmp     IEC_REG_DATA_CLK_IN
  9402:          bne     @LEE56
  9403:          IEC_REG__CLOCK_IN_INTO_CARRY
  9404:          bcc     @LEE56
  9405:          lsr     a
  9406:          ror     zTBTCNT
  9407:  
  9408:  @WaitClkInactive:
  9409:          lda     IEC_REG_DATA_CLK_IN
  9410:          cmp     IEC_REG_DATA_CLK_IN
  9411:          bne     @WaitClkInactive
  9412:  
  9413:          IEC_REG__CLOCK_IN_INTO_CARRY
  9414:          bcs     @WaitClkInactive
  9415:          dec     zCNTDN
  9416:          bne     @LEE56
  9417:          jsr     IecDataSet
  9418:          lda     zTBTCNT
  9419:          cli
  9420:          clc
  9421:          rts
  9422:  
  9423:  .else
  9424:  
  9425:          lda     zCNTDN
  9426:          beq     @Proceed
  9427:  
  9428:          lda     #$02                            ; set status: read timeout
  9429:          jmp     IecSetStatusAndFreeBus          ; ... and free the bus and exit
  9430:          ; ------------------
  9431:  
  9432:  @Proceed:
  9433:          jsr     IecDataSet
  9434:    .if CompileComputer >= C64_GENERAL
  9435:          jsr     IecClkClear
  9436:    .else
  9437:          jsr     IecClearClockAndDataAfterDelay
  9438:    .endif
  9439:          lda     #$40
  9440:          jsr     SetStatus
  9441:          inc     zCNTDN
  9442:          bne     @LEE20
  9443:  
  9444:  @LEE56: lda     #8                              ; number of bits to be input
  9445:          sta     zCNTDN
  9446:  @LEE5A:
  9447:          lda     IEC_REG_DATA_CLK_IN
  9448:          cmp     IEC_REG_DATA_CLK_IN
  9449:          bne     @LEE5A
  9450:  
  9451:    .if CompileComputer >= C64_GENERAL
  9452:          asl     a
  9453:          bpl     @LEE5A
  9454:    .else
  9455:          lsr     a
  9456:          bcc     @LEE5A
  9457:          lsr     a
  9458:    .endif
  9459:          ror     zTBTCNT
  9460:  @LEE67:
  9461:          lda     IEC_REG_DATA_CLK_IN
  9462:          cmp     IEC_REG_DATA_CLK_IN
  9463:          bne     @LEE67
  9464:    .if CompileComputer >= C64_GENERAL
  9465:          asl     a
  9466:          bmi     @LEE67
  9467:    .else
  9468:          lsr     a
  9469:          bcs     @LEE67
  9470:    .endif
  9471:  
  9472:          dec     zCNTDN
  9473:          bne     @LEE5A
  9474:          jsr     IecDataSet
  9475:    .if CompileComputer >= C64_GENERAL
  9476:          bit     zSTATUS
  9477:          bvc     @LEE80
  9478:    .else
  9479:          lda     zSTATUS
  9480:          beq     @LEE80
  9481:    .endif
  9482:          jsr     IecClearClockAndDataAfterDelay
  9483:  @LEE80: lda     zTBTCNT
  9484:          cli
  9485:          clc
  9486:          rts
  9487:  .endif
  9488:  
  9489:  IecClkClear:
  9490:          ; clear (set inactive) the clock line
  9491:          lda     IEC_REG_DATA_CLK_OUT
  9492:          and     #~IEC_B_CLK_OUT
  9493:          sta     IEC_REG_DATA_CLK_OUT
  9494:          rts
  9495:  
  9496:  IecClkSet:
  9497:          ; set (set active) the clock line
  9498:          lda     IEC_REG_DATA_CLK_OUT
  9499:          ora     #IEC_B_CLK_OUT
  9500:          sta     IEC_REG_DATA_CLK_OUT
  9501:          rts
  9502:  
  9503:  .segment "KERNAL_IEC_DATA"
  9504:  
  9505:  IecDataClear:
  9506:          lda     IEC_REG_DATA_CLK_OUT
  9507:          and     #~IEC_B_DATA_OUT
  9508:          sta     IEC_REG_DATA_CLK_OUT
  9509:          rts
  9510:  IecDataSet:
  9511:          lda     IEC_REG_DATA_CLK_OUT
  9512:          ora     #IEC_B_DATA_OUT
  9513:          sta     IEC_REG_DATA_CLK_OUT
  9514:          rts
  9515:  
  9516:  ; reads in IEC register and returns
  9517:  ; * C64:
  9518:  ;   - DATA IN in Carry
  9519:  ;   - CLOCK IN in A & 0x80
  9520:  ; * VIC20:
  9521:  ;   - CLOCK IN in Carry
  9522:  ;   - DATA IN in A & 0x01
  9523:  ;
  9524:  IecGetDataClockIn:
  9525:          lda     IEC_REG_DATA_CLK_IN
  9526:          cmp     IEC_REG_DATA_CLK_IN
  9527:          bne     IecGetDataClockIn
  9528:  .if CompileComputer >= C64_GENERAL
  9529:          asl     a
  9530:  .else
  9531:          lsr     a
  9532:  .endif
  9533:          rts
  9534:  
  9535:  
  9536:  .segment "KERNAL_IEC_DELAY"
  9537:  
  9538:  IecDelay1ms:
  9539:  
  9540:  .if CompileComputer >= C64_GENERAL
  9541:          txa
  9542:          ldx     #184
  9543:  @Delay: dex
  9544:          bne     @Delay
  9545:          tax
  9546:  .else
  9547:          lda     #>$0400                 ; program T2 for $0400 = 1024 cycles (approx. 1 ms)
  9548:          sta     VIA2_T2CH               ; (low byte is not written, thus, should be 0)
  9549:  
  9550:          ; wait for T2 flag being set in the IFR,
  9551:          ; telling us that the timer expired
  9552:  @Wait:
  9553:          lda     VIA2_IFR
  9554:          and     #VIA_IFR_B_T2
  9555:          beq     @Wait
  9556:  .endif
  9557:          rts
  9558:  
  9559:  ;       .include "../kernal/rs232.a65"
  9560:  LEEBB:
  9561:          lda     zBITTS
  9562:          beq     LEF06
  9563:          bmi     @LEF00
  9564:          lsr     zRODATA
  9565:          ldx     #$00
  9566:          bcc     @LEEC8
  9567:          dex
  9568:  @LEEC8:
  9569:          txa
  9570:          eor     zROPRTY
  9571:          sta     zROPRTY
  9572:          dec     zBITTS
  9573:          beq     @LEED7
  9574:  @LEED1:
  9575:          txa
  9576:  .if CompileComputer >= C64_GENERAL
  9577:          and     #$04
  9578:  .else
  9579:          and     #$20
  9580:  .endif
  9581:          sta     zNXTBIT
  9582:          rts
  9583:  
  9584:  @LEED7:
  9585:          lda     #$20
  9586:          bit     lM51CDR
  9587:          beq     @LEEF2
  9588:          bmi     @LEEFC
  9589:          bvs     @LEEF6
  9590:          lda     zROPRTY
  9591:          bne     @LEEE7
  9592:  @LEEE6:
  9593:          dex
  9594:  @LEEE7:
  9595:          dec     zBITTS
  9596:          lda     lM51CTR
  9597:          bpl     @LEED1
  9598:          dec     zBITTS
  9599:          bne     @LEED1
  9600:  @LEEF2:
  9601:          inc     zBITTS
  9602:          bne     @LEEE6
  9603:  @LEEF6:
  9604:          lda     zROPRTY
  9605:          beq     @LEEE7
  9606:          bne     @LEEE6
  9607:  @LEEFC:
  9608:          bvs     @LEEE7
  9609:          bvc     @LEEE6
  9610:          ; ------------------
  9611:  
  9612:  @LEF00:
  9613:          inc     zBITTS
  9614:          ldx     #$FF
  9615:          bne     @LEED1
  9616:  
  9617:  LEF06:
  9618:          lda     lM51CDR
  9619:          lsr     a
  9620:          bcc     @LEF13
  9621:          bit     RS232_REG_2
  9622:          bpl     LF016
  9623:          bvc     LEF31
  9624:  @LEF13:
  9625:          lda     #$00
  9626:          sta     zROPRTY
  9627:          sta     zNXTBIT
  9628:          ldx     lBITNUM
  9629:          stx     zBITTS
  9630:          ldy     lRODBS
  9631:          cpy     lRODBE
  9632:          beq     LEF39
  9633:          lda     (zROBUF),y
  9634:          sta     zRODATA
  9635:          inc     lRODBS
  9636:          rts
  9637:  
  9638:  LF016:
  9639:          lda     #$40
  9640:          .byte   ASM_BIT3
  9641:  LEF31:
  9642:          lda     #$10
  9643:          ora     lRSSTAT
  9644:          sta     lRSSTAT
  9645:  LEF39:
  9646:  .if CompileComputer >= C64_GENERAL
  9647:          lda     #CIA_ICR_B_TA
  9648:  LEF3B:  sta     CIA2 + CIA_O_ICR
  9649:          eor     lENABL
  9650:          ora     #CIA_ICR_BW_SET
  9651:          sta     lENABL
  9652:          sta     CIA2 + CIA_O_ICR
  9653:  .else
  9654:          lda     #$40
  9655:          sta     VIA1_IEC
  9656:  .endif
  9657:          rts
  9658:  
  9659:  ; get number of bits to transmit
  9660:  ;
  9661:  LEF4A:
  9662:          ldx     #$09
  9663:          lda     #$20
  9664:          bit     lM51CTR
  9665:          beq     @LEF54
  9666:          dex
  9667:  @LEF54:
  9668:          bvc     @LEF58
  9669:          dex
  9670:          dex
  9671:  @LEF58:
  9672:          rts
  9673:          ; ---------------
  9674:  
  9675:  LEF59:  ldx     zRINONE
  9676:          bne     LEF90
  9677:          dec     zBITC1
  9678:          beq     LEF97
  9679:          bmi     LEF70
  9680:          lda     zINBIT
  9681:          eor     zRIPRTY
  9682:          sta     zRIPRTY
  9683:          lsr     zINBIT
  9684:          ror     zRIDATA
  9685:  LEF6D:  rts
  9686:  
  9687:  LEF6E:  dec     zBITC1
  9688:  LEF70:  lda     zINBIT
  9689:          beq     LEFDB
  9690:          lda     lM51CTR
  9691:          asl     a
  9692:          lda     #$01
  9693:          adc     zBITC1
  9694:          bne     LEF6D
  9695:  LEF7E:
  9696:  .if CompileComputer >= C64_GENERAL
  9697:          lda     #CIA_ICR_B_FLAG | CIA_ICR_BW_SET
  9698:          sta     CIA2 + CIA_O_ICR
  9699:          ora     lENABL
  9700:          sta     lENABL
  9701:  .else
  9702:          lda     #$90
  9703:          sta     VIA1_IEC
  9704:  .endif
  9705:          sta     zRINONE
  9706:  .if CompileComputer >= C64_GENERAL
  9707:          lda     #$02
  9708:          jmp     LEF3B
  9709:  .else
  9710:          lda     #$20
  9711:          sta     VIA1_IEC
  9712:          rts
  9713:  .endif
  9714:  
  9715:  LEF90:  lda     zINBIT
  9716:          bne     LEF7E
  9717:  .if CompileComputer >= C64_03 .AND CompileComputer <> C64_4064
  9718:          jmp     LE4D3
  9719:  .else
  9720:          sta     zRINONE
  9721:          rts
  9722:  .endif
  9723:  
  9724:  LEF97:  ldy     lRIDBE
  9725:          iny
  9726:          cpy     lRIDBS
  9727:          beq     @LEFCA
  9728:          sty     lRIDBE
  9729:          dey
  9730:          lda     zRIDATA
  9731:          ldx     lBITNUM
  9732:  @LEFA9: cpx     #$09
  9733:          beq     @LEFB1
  9734:          lsr     a
  9735:          inx
  9736:          bne     @LEFA9
  9737:  @LEFB1: sta     (zRIBUF),y
  9738:          lda     #$20
  9739:          bit     lM51CDR
  9740:          beq     LEF6E
  9741:          bmi     LEF6D
  9742:          lda     zINBIT
  9743:          eor     zRIPRTY
  9744:          beq     @LEFC5
  9745:          bvs     LEF6D
  9746:          .byte   ASM_BIT3
  9747:  @LEFC5: bvc     LEF6D
  9748:          lda     #$01
  9749:          .byte   ASM_BIT3
  9750:  @LEFCA: lda     #$04
  9751:          .byte   ASM_BIT3
  9752:  LEFCD:  lda     #$80
  9753:          .byte   ASM_BIT3
  9754:  LEFD0:  lda     #$02
  9755:          ora     lRSSTAT
  9756:          sta     lRSSTAT
  9757:          jmp     LEF7E
  9758:  
  9759:  LEFDB:  lda     zRIDATA
  9760:          bne     LEFD0
  9761:          beq     LEFCD
  9762:  .if CompileComputer < C64_GENERAL
  9763:  Rs232ErrIllegalDeviceNumber:
  9764:          jmp     KErrIllegalDeviceNumber
  9765:  .endif
  9766:  
  9767:  RS232_CHKOUT:
  9768:          sta     zDFLTO
  9769:          lda     lM51CDR
  9770:          lsr     a
  9771:          bcc     LF012
  9772:          lda     #$02
  9773:          bit     RS232_REG_1
  9774:          bpl     LF00D
  9775:          bne     LF012
  9776:  
  9777:  @LEFF2:
  9778:  .if CompileComputer >= C64_GENERAL
  9779:          lda     lENABL
  9780:          and     #CIA_ICR_B_TB
  9781:  .else
  9782:          lda     VIA1_IEC
  9783:          and     #$30
  9784:  .endif
  9785:          bne     @LEFF2
  9786:  @LEFF9:
  9787:          bit     RS232_REG_1
  9788:          bvs     @LEFF9
  9789:          lda     RS232_REG_1
  9790:          ora     #$02
  9791:          sta     RS232_REG_1
  9792:  @LF006:
  9793:          bit     RS232_REG_1
  9794:          bvs     LF012
  9795:          bmi     @LF006
  9796:  
  9797:  LF00D:
  9798:  .if CompileComputer >= C64_GENERAL
  9799:          lda     #$40
  9800:          sta     lRSSTAT
  9801:  .else
  9802:          jsr     LF016
  9803:  .endif
  9804:  LF012:  clc
  9805:          rts
  9806:  
  9807:  
  9808:  LF014:
  9809:  
  9810:  .if CompileComputer >= C64_GENERAL
  9811:          jsr     LF028
  9812:  .endif
  9813:  
  9814:  ; Write a character to the RS232 output buffer
  9815:  ;
  9816:  ; The character is returned in A. If there is
  9817:  ; no character in the buffer, A will contain 0.
  9818:  ;
  9819:  ; For C64 and above, this function also
  9820:  ; sets lRSSTAT.3 (TODO: "buffer empty"?)
  9821:  ;
  9822:  RS232_PUTCHAR:
  9823:          ldy     lRODBE                  ; is the output buffer read pointer
  9824:          iny                             ; + 1
  9825:          cpy     lRODBS                  ; equal to the output buffer write pointer?
  9826:          beq     LF014                   ; yes -> ring buffer is full -> wait until it is empty again
  9827:  
  9828:          sty     lRODBE                  ; advance the output buffer write pointer, leaving room for the character to be written
  9829:  
  9830:          dey                             ; the location we reserved the space for is one before, thus, decrement Y again
  9831:  
  9832:  .if CompileComputer >= C64_GENERAL
  9833:          lda     zPTR1
  9834:  .endif
  9835:          sta     (zROBUF),y              ; store the output character into the output buffer
  9836:  
  9837:  .if CompileComputer >= C64_GENERAL
  9838:  LF028:  lda     lENABL
  9839:          lsr     a                       ; test CIA_ICR_B_TA
  9840:          bcs     @Rts
  9841:          lda     #CIA_CRA_B_FORCE_LOAD
  9842:          sta     CIA2 + CIA_O_CRA
  9843:  .else
  9844:          bit     VIA1_IEC
  9845:          bvc     @LF102
  9846:          rts
  9847:  @LF102:
  9848:  
  9849:  .endif
  9850:  
  9851:          lda     lBAUDOF
  9852:          sta     RS232_TIMER_LO
  9853:          lda     lBAUDOF + 1
  9854:          sta     RS232_TIMER_HI
  9855:  
  9856:  .if CompileComputer >= C64_GENERAL
  9857:          lda     #$81
  9858:          jsr     LEF3B
  9859:          jsr     LEF06
  9860:          lda     #$11
  9861:          sta     CIA2 + CIA_O_CRA
  9862:  @Rts:   rts
  9863:  .else
  9864:          lda     #$C0
  9865:          sta     VIA1_IEC
  9866:          jmp     LEF06
  9867:  .endif
  9868:  
  9869:  RS232_CHKIN:
  9870:          sta     zDFLTN                                  ; set default output device
  9871:          lda     lM51CDR
  9872:          lsr     a
  9873:          bcc     @LF07D
  9874:          and     #$08
  9875:          beq     @LF07D
  9876:          lda     #$02
  9877:          bit     RS232_REG_1
  9878:          bpl     LF00D
  9879:          beq     @ClcRts
  9880:  
  9881:  @LF062:
  9882:  .if CompileComputer >= C64_GENERAL
  9883:          lda     lENABL
  9884:          lsr     a                                       ; test CIA_ICR_B_TA
  9885:          bcs     @LF062
  9886:  .else
  9887:          bit     VIA1_IEC
  9888:          bvs     @LF062
  9889:  .endif
  9890:  
  9891:          lda     RS232_REG_1
  9892:          and     #~$02
  9893:          sta     RS232_REG_1
  9894:  @LF070:
  9895:          lda     RS232_REG_1
  9896:          and     #$04
  9897:          beq     @LF070
  9898:  @LF077: lda     #$90
  9899:  .if CompileComputer >= C64_GENERAL
  9900:          clc
  9901:          jmp     LEF3B
  9902:  .else
  9903:          sta     VIA1_IEC
  9904:  @ClcRts:
  9905:          clc
  9906:          rts
  9907:  .endif
  9908:  
  9909:  @LF07D:
  9910:  
  9911:  .if CompileComputer >= C64_GENERAL
  9912:          lda     lENABL
  9913:          and     #CIA_ICR_B_FLAG | CIA_ICR_B_TB
  9914:  .else
  9915:          lda     VIA1_IEC
  9916:          and     #$30
  9917:  .endif
  9918:          beq     @LF077
  9919:  
  9920:  .if CompileComputer >= C64_GENERAL
  9921:  @ClcRts:
  9922:  .endif
  9923:          clc
  9924:          rts
  9925:  
  9926:  ; Read a character from the RS232 input buffer
  9927:  ;
  9928:  ; The character is returned in A. If there is
  9929:  ; no character in the buffer, A will contain 0.
  9930:  ;
  9931:  ; For C64 and above, this function also
  9932:  ; sets lRSSTAT.3 (TODO: "buffer empty"?)
  9933:  ;
  9934:  RS232_GETCHAR:
  9935:  
  9936:  .if CompileComputer >= C64_GENERAL
  9937:          lda     lRSSTAT                         ; as we modifiy lRSSTAT, make its value available for both if() cases.
  9938:  .endif
  9939:  
  9940:          ldy     lRIDBS                          ; get read buffer into RS232 input buffer
  9941:          cpy     lRIDBE                          ; compare with write buffer
  9942:          beq     @BufferEmpty                    ; they are the same -> input buffer empty -> skip reading
  9943:  
  9944:  .if CompileComputer >= C64_GENERAL
  9945:          and     #~$08
  9946:          sta     lRSSTAT                         ; clear bit: buffer is not empty (TODO?)
  9947:  .endif
  9948:          lda     (zRIBUF),y                      ; get character from buffer
  9949:          inc     lRIDBS                          ; increment read pointer
  9950:          rts
  9951:          ; ---------------
  9952:  
  9953:  @BufferEmpty:
  9954:  
  9955:  .if CompileComputer >= C64_GENERAL
  9956:          ora     #$08
  9957:          sta     lRSSTAT                         ; set bit: buffer empty (TODO?)
  9958:  .endif
  9959:          lda     #$00                            ; return: no character in buffer
  9960:          rts
  9961:          ; ---------------
  9962:  
  9963:  
  9964:  LF0A4:
  9965:  
  9966:          pha
  9967:  .if CompileComputer >= C64_GENERAL
  9968:          lda     lENABL
  9969:  .else
  9970:          lda     VIA1_IEC
  9971:  .endif
  9972:          beq     @PlaRts
  9973:  
  9974:  @Wait:
  9975:  
  9976:  .if CompileComputer >= C64_GENERAL
  9977:          lda     lENABL
  9978:          and     #CIA_ICR_B_TA | CIA_ICR_B_TB
  9979:  .else
  9980:          lda     VIA1_IEC
  9981:          and     #VIA_IER_B_T1 | VIA_IER_B_T2
  9982:  .endif
  9983:          bne     @Wait
  9984:  
  9985:  .if CompileComputer >= C64_GENERAL
  9986:          lda     #CIA_ICR_B_FLAG
  9987:          sta     CIA2 + CIA_O_ICR
  9988:  .else
  9989:          lda     #VIA_IER_B_CB1
  9990:          sta     VIA1_IEC
  9991:  .endif
  9992:  
  9993:  .if CompileComputer >= C64_GENERAL
  9994:          lda     #$00
  9995:          sta     lENABL
  9996:  .endif
  9997:  
  9998:  @PlaRts:
  9999:          pla
 10000:          rts
 10001:  
 10002:  ;       .include "../kernal/message.a65"
 10003:  ; KERNAL system essages
 10004:  
 10005:  LMESSAGES:
 10006:  
 10007:  StrIoError:
 10008:          .byte   ASC_CR
 10009:          htasc   "I/O ERROR #"           ; used in case an I/O error occurs in a KERNAL routine, and zNSGFLG.6 is set
 10010:  
 10011:  StrSearching:
 10012:          .byte   ASC_CR
 10013:          htasc   "SEARCHING "            ; used when loading, and zNSGFLG.7 is set
 10014:  
 10015:  StrFor:
 10016:          htasc   "FOR "                  ; used when loading with a file name, and zNSGFLG.7 is set
 10017:  
 10018:  StrPlay:
 10019:  
 10020:  .ifdef JIFFY
 10021:  
 10022:  StrRecPlay = $F0EB
 10023:  
 10024:  JDLF0D8:
 10025:          lda     #$00
 10026:          sta     VIC + VICII_O_SprEnable
 10027:  @JDLF0DD:
 10028:          adc     #$01
 10029:          bne     @JDLF0DD
 10030:          rts
 10031:  
 10032:  JDLF0E2:
 10033:          lda     zPTR2
 10034:  JDLF0E4:
 10035:          pha
 10036:          jsr     kCLRCHN
 10037:          pla
 10038:          tax
 10039:          jmp     kCHKIN
 10040:  
 10041:  JDLF0ED:
 10042:          lda     #$00
 10043:          sta     zTSFCNT
 10044:          jmp     IecDataClear
 10045:  
 10046:  JDLF0F4:
 10047:          txa
 10048:          pha
 10049:          jsr     JDLF7A2
 10050:          pla
 10051:          tax
 10052:  @JDLF0FB:
 10053:          lda     JDLF398,x
 10054:          jsr     kCHROUT
 10055:          inx
 10056:          dey
 10057:          bne     @JDLF0FB
 10058:          rts
 10059:  
 10060:  .else
 10061:  
 10062:  .if CompileComputer = C64_SX64
 10063:  
 10064:          ; the SX64 does not have a tape, thus, "PRESS PLAY ON TAPE" is not needed there
 10065:          ; However, it redefines the Shift+Run/STOP message. This alternative message
 10066:          ; can be found here:
 10067:  
 10068:  TEXT_LOAD_8_RUN:
 10069:          .byte   "LOAD",'"',":*",'"',",8",ASC_CR
 10070:          .byte   "RUN",ASC_CR
 10071:  END_TEXT_LOAD_8_RUN:
 10072:  
 10073:  .else
 10074:          .byte   ASC_CR,"PRESS PLAY ON " ; used when loading from tape (on the 4064, zNSGFLG.7 has to be set, too)
 10075:  .endif
 10076:          htasc   "TAPE"                  ; remaining part of the "PRESS PLAY ON TAPE" message
 10077:  
 10078:  StrRecPlay:
 10079:          htasc   "PRESS RECORD & PLAY ON TAPE"   ; used when storing to tape (on the 4064, zNSGFLG.7 has to be set, too)
 10080:  
 10081:  .endif
 10082:  
 10083:  StrLoading:
 10084:          .byte   ASC_CR
 10085:          htasc   "LOADING"               ; used when KERNAL LOAD is executed, and zNSGFLG.7 is set
 10086:  
 10087:  StrSaving:
 10088:          .byte   ASC_CR
 10089:          htasc   "SAVING "               ; used when KERNAL SAVE is executed, and zNSGFLG.7 is set
 10090:  
 10091:  StrVerifying:
 10092:          .byte   ASC_CR
 10093:          htasc   "VERIFYING"             ; used when KERNAL VERIFY is executed, and zNSGFLG.7 is set
 10094:  
 10095:  StrFound:
 10096:          .byte   ASC_CR
 10097:          htasc   "FOUND "                ; used when loading from tape
 10098:  StrOk:
 10099:          .byte   ASC_CR,"OK",ASC_CR + $80        ; used when loading from or storing to tape (on the 4064, zNSGFLG.7 has to be set, too)
 10100:  
 10101:  
 10102:  OutputMessageIfAllowed:
 10103:          bit     zNSGFLG                 ; check KERNAL output policy
 10104:          bpl     OutputMessage_ClcRts    ; bit 7 unset -> policy forbids output -> branch, all done
 10105:  
 10106:  OutputMessage:
 10107:          lda     LMESSAGES,y             ; get character from message
 10108:          php                             ; remember status (especially N, which represents bit 7 of the message)
 10109:  
 10110:          and     #$7F                    ; delete bit 7 (which acts as an end marker)
 10111:          jsr     kCHROUT                 ; output the character
 10112:          iny                             ; proceed to next character
 10113:  
 10114:          plp                             ; get back N as indicator for bit 7 of the message
 10115:          bpl     OutputMessage           ; bit 7 was not set -> process to next character
 10116:  
 10117:  OutputMessage_ClcRts:
 10118:          clc                             ; mark: no error
 10119:          rts
 10120:          ; -------------------
 10121:  ;       .include "../kernal/fileio.a65"
 10122:  ;  B-11. Function Name: GETIN
 10123:  ;
 10124:  ;
 10125:  ;    Purpose: Get a character
 10126:  ;    Call address: $FFE4 (hex) 65508 (decimal)
 10127:  ;    Communication registers: A
 10128:  ;    Preparatory routines: CHKIN, OPEN
 10129:  ;    Error returns: See READST
 10130:  ;    Stack requirements: 7+
 10131:  ;    Registers affected: A (X, Y)
 10132:  ;
 10133:  ;    Description: If the channel is the keyboard, this subroutine removes
 10134:  ;  one character from the keyboard queue and returns it as an ASCII value in
 10135:  ;  the accumulator. If the queue is empty, the value returned in the
 10136:  ;  accumulator will be zero. Characters are put into the queue automatically
 10137:  ;  by an interrupt driven keyboard scan routine which calls the SCNKEY
 10138:  ;  routine. The keyboard buffer can hold up to ten characters. After the
 10139:  ;  buffer is filled, additional characters are ignored until at least one
 10140:  ;  character has been removed from the queue. If the channel is RS-232, then
 10141:  ;  only the A register is used and a single character is returned. See
 10142:  ;  READST to check validity. If the channel is serial, cassette, or screen,
 10143:  ;  call BASIN routine.
 10144:  ;
 10145:  ;
 10146:  ;  How to Use:
 10147:  ;
 10148:  ;    1) Call this routine using a JSR instruction.
 10149:  ;    2) Check for a zero in the accumulator (empty buffer).
 10150:  ;    3) Process the data.
 10151:  ;
 10152:  ;
 10153:  ;  EXAMPLE:
 10154:  ;
 10155:  ;         ;WAIT FOR A CHARACTER
 10156:  ;    WAIT JSR GETIN
 10157:  ;         CMP #0
 10158:  ;         BEQ WAIT
 10159:  ;
 10160:  
 10161:  KGETIN:
 10162:          lda     zDFLTN          ; get device address
 10163:          bne     @NoKeyboard     ; != 0 --> not the keyboard
 10164:          lda     zNDX            ; are there characters in the key buffer?
 10165:          beq     ClcRts1         ; no, next test
 10166:          sei                     ; protect the keyboard buffer
 10167:          jmp     GETIN_KEYB      ; get key from keyboard buffer
 10168:  
 10169:  @NoKeyboard:
 10170:          cmp     #FILE_RS232     ; device address = RS232 device?
 10171:          bne     LF166           ; no, next test
 10172:  
 10173:  KGETIN_RS232:
 10174:          sty     zTEMPX          ; save Y in order to leave it unchanged
 10175:          jsr     RS232_GETCHAR   ; get a character from RS232
 10176:          ldy     zTEMPX          ; restore Y
 10177:  
 10178:  .if CompileComputer >= C64_GENERAL
 10179:  ClcRts1:
 10180:  .endif
 10181:  
 10182:          clc
 10183:          rts
 10184:  
 10185:  ;  B-4. Function Name: CHRIN a.k.a. BASIN
 10186:  ;
 10187:  ;    Purpose: Get a character from the input channel
 10188:  ;    Call address: $FFCF (hex) 65487 (decimal)
 10189:  ;    Communication registers: A
 10190:  ;    Preparatory routines: (OPEN, CHKIN)
 10191:  ;    Error returns: 0 (See READST)
 10192:  ;    Stack requirements: 7+
 10193:  ;    Registers affected: A, X
 10194:  ;
 10195:  ;    Description: This routine gets a byte of data from a channel already
 10196:  ;  set up as the input channel by the KERNAL routine CHKIN. If the CHKIN has
 10197:  ;  NOT been used to define another input channel, then all your data is
 10198:  ;  expected from the keyboard. The data byte is returned in the accumulator.
 10199:  ;  The channel remains open after the call.
 10200:  ;    Input from the keyboard is handled in a special way. First, the cursor
 10201:  ;  is turned on, and blinks until a carriage return is typed on the
 10202:  ;  keyboard. All characters on the line (up to 88 characters) are stored in
 10203:  ;  the BASIC input buffer. These characters can be retrieved one at a time
 10204:  ;  by calling this routine once for each character. When the carriage return
 10205:  ;  is retrieved, the entire line has been processed. The next time this
 10206:  ;  routine is called, the whole process begins again, i.e., by flashing the
 10207:  ;  cursor.
 10208:  ;
 10209:  ;  How to Use:
 10210:  ;
 10211:  ;  FROM THE KEYBOARD
 10212:  ;
 10213:  ;    1) Retrieve a byte of data by calling this routine.
 10214:  ;    2) Store the data byte.
 10215:  ;    3) Check if it is the last data byte (is it a CR?)
 10216:  ;    4) If not, go to step 1.
 10217:  ;
 10218:  ;  EXAMPLE:
 10219:  ;
 10220:  ;       LDY $#00      ;PREPARE THE Y REGISTER TO STORE THE DATA
 10221:  ;   RD  JSR CHRIN
 10222:  ;       STA DATA,Y    ;STORE THE YTH DATA BYTE IN THE YTH
 10223:  ;                     ;LOCATION IN THE DATA AREA.
 10224:  ;       INY
 10225:  ;       CMP #CR       ;IS IT A CARRIAGE RETURN?
 10226:  ;       BNE RD        ;NO, GET ANOTHER DATA BYTE
 10227:  ;
 10228:  ;
 10229:  ;
 10230:  ;  EXAMPLE:
 10231:  ;
 10232:  ;    JSR CHRIN
 10233:  ;    STA DATA
 10234:  ;
 10235:  ;  FROM OTHER DEVICES
 10236:  ;
 10237:  ;    0) Use the KERNAL OPEN and CHKIN routines.
 10238:  ;    1) Call this routine (using a JSR instruction).
 10239:  ;    2) Store the data.
 10240:  ;
 10241:  ;  EXAMPLE:
 10242:  ;
 10243:  ;    JSR CHRIN
 10244:  ;    STA DATA
 10245:  ;
 10246:  ;
 10247:  KBASIN:
 10248:          lda     zDFLTN          ; get device address
 10249:  .ifdef JIFFY
 10250:          bne     JDLF1A9
 10251:  .else
 10252:          bne     LF166           ; not keyboard --> jump
 10253:  .endif
 10254:  
 10255:          ; TODO
 10256:          lda     zPNTR           ; remember zPNTR (current column on screen) in zTEMP_zPNTR
 10257:          sta     zTEMP_zPNTR     ; for later restoration
 10258:  
 10259:          lda     zTBLX           ; remember zTBLX (current row on screen) in zLXSP
 10260:          sta     zLXSP
 10261:  
 10262:          jmp     BASIN_KEYB      ; input character from the screen
 10263:          ; ---------------------
 10264:  
 10265:  LF166:  cmp     #FILE_SCREEN    ; device address == screen?
 10266:          bne     KBASIN_NoScreen ; no, next test
 10267:  
 10268:          ; TODO
 10269:  JDLF16A:
 10270:          sta     zCRSW           ; zCRSW := 3 --> mark that we do not wait for key pressed until CR has been pressed
 10271:  
 10272:          lda     zLNMX           ; logical line length of the current line
 10273:          sta     zINDX           ; is the number of characters in this line
 10274:  
 10275:          jmp     BASIN_KEYB      ; input character from the screen
 10276:          ; ---------------------
 10277:  
 10278:  KBASIN_NoScreen:
 10279:          bcs     KBASIN_TestIec  ; greater than screen (that is, IEC bus) --> jump
 10280:          cmp     #FILE_RS232     ; is it from RS232?
 10281:          beq     BASIN_RS232     ; Yes, process RS232
 10282:  
 10283:  .ifdef JIFFY
 10284:  JDLF179:
 10285:          jsr     JDLFBAA
 10286:          pha
 10287:          bit     zTSFCNT
 10288:          bvc     LF19C
 10289:          cpx     #$00
 10290:          bne     LF187
 10291:          lda     $C4
 10292:  LF187:  cmp     #$04
 10293:          bcc     LF19C
 10294:          ldy     #$00
 10295:          lda     (zFNADR),y
 10296:          cmp     #$24
 10297:          beq     LF19C
 10298:          inc     zSA
 10299:          jsr     JDLF38B
 10300:          dec     zSA
 10301:          asl     zTSFCNT
 10302:  LF19C:  pla
 10303:          rts
 10304:  LF19E:  lda     #$10
 10305:          jmp     SetStatus
 10306:  
 10307:  LF1A3:  .addr   PatchErrorOut
 10308:          .addr   IMAIN
 10309:          .addr   LA57C
 10310:  
 10311:  JDLF1A9:
 10312:          cmp     #$04
 10313:          bcc     LF166
 10314:  
 10315:  .else
 10316:          ; if we are here, we want to get input from TAPE
 10317:  
 10318:          stx     zTEMPX          ; remember X
 10319:          jsr     @GetNextTapeCharacterFromBuffer ; read in the next character from the tape buffer
 10320:          bcs     @Ret_No_PLA                     ; if an error occurred, stop here
 10321:  
 10322:          ; Find out if we can read even one more character, and that character is not 0.
 10323:          ; Note that we only test for it. The value will be disregarded, and the tape buffer pointer
 10324:          ; will be set backwards afterwards!
 10325:  
 10326:          pha                                     ; remember the read character
 10327:          jsr     @GetNextTapeCharacterFromBuffer ; read in the next character from the tape buffer
 10328:          bcs     @Ret_With_PLA                   ; if an error occurred, stop here, making sure to PLA the remembered character
 10329:  
 10330:          bne     @NoNulCharacter                 ; no NUL ($00) character -> branch, skip setting the status flag
 10331:  
 10332:          ; mark an end-of-file status
 10333:          lda     #STATUS_TAPE_EOF
 10334:          jsr     SetStatus
 10335:  
 10336:  @NoNulCharacter:
 10337:          dec     zBUFPNT                         ; put tape buffer pointer backwards, so we will read the same byte again in the next call
 10338:  
 10339:          ldx     zTEMPX                          ; get back (remembered) X
 10340:          pla                                     ; get back remembered character
 10341:          rts
 10342:          ; ----------------------
 10343:  
 10344:  @Ret_With_PLA:
 10345:          tax
 10346:          pla
 10347:          txa
 10348:  
 10349:  @Ret_No_PLA:
 10350:          ldx     zTEMPX                          ; get back (remembered) X
 10351:          rts
 10352:          ; ----------------------
 10353:  
 10354:  @GetNextTapeCharacterFromBuffer:
 10355:          jsr     TAPE_INCREMENT_WRITE_POINTER    ; increment the pointer into the tape buffer
 10356:          bne     @ReadTapeBuffer                 ; Z = 0 --> there are still bytes to read --> branch, read bytes
 10357:  
 10358:          ; we must read in the next tape buffer from tape
 10359:  
 10360:          jsr     TapeReadNextBuffer              ; read in the next tape buffer
 10361:          bcs     BASIN_RTS1                      ; C = 1 --> an error occurred -> branch, return with C = 1 indicating an error
 10362:  
 10363:          lda     #0                              ; set tape buffer pointer to 0 (will be incremented directly afterwards)
 10364:          sta     zBUFPNT                         ; this ensures we skip the tape buffer type marker at position 0.
 10365:  
 10366:          beq     @GetNextTapeCharacterFromBuffer ; (uncond. branch) retry reading the tape buffer
 10367:          ; ------------------
 10368:  
 10369:  @ReadTapeBuffer:
 10370:          lda     (zTAPE1),y
 10371:          clc
 10372:          rts
 10373:  .endif
 10374:  
 10375:  KBASIN_TestIec:
 10376:          ; Input from IEC bus
 10377:          lda     zSTATUS         ; current status
 10378:          beq     BASIN_IEC       ; == 0 --> jump, get byte from IEC bus
 10379:  
 10380:  ReturnCR:
 10381:          lda     #ASC_CR         ; an error or EOI occurred on the IEC bus, return CR
 10382:  
 10383:  .if CompileComputer < C64_GENERAL
 10384:  ClcRts1:
 10385:  .endif
 10386:  ClcRts2:
 10387:          clc
 10388:  .if CompileComputer >= C64_GENERAL
 10389:  BASIN_RTS2:
 10390:  .endif
 10391:  BASIN_RTS1:
 10392:          rts
 10393:  
 10394:  BASIN_IEC:
 10395:  .ifdef JIFFY
 10396:          jmp     JDLFBAA
 10397:  .else
 10398:          jmp     iACPTR
 10399:  .endif
 10400:  
 10401:  BASIN_RS232:
 10402:          ; get data from RS232
 10403:          jsr     KGETIN_RS232    ; get character from RS232, or 0 if empty
 10404:          bcs     BASIN_RTS2
 10405:  
 10406:          cmp     #0              ; did we read a 0 (buffer empty)?
 10407:  
 10408:  .if CompileComputer >= C64_GENERAL
 10409:          bne     ClcRts2         ; no -> return with the current character
 10410:  
 10411:          lda     lRSSTAT         ; check lRSSTAT (TODO)
 10412:          and     #$60            ; TODO: Meaning of the bits?
 10413:          bne     ReturnCR        ; bits are not null -> return with ASCII CR instead of waiting
 10414:          beq     BASIN_RS232     ; wait until there is a character received from RS232
 10415:          ; -------------------
 10416:  .else
 10417:          beq     BASIN_RS232     ; yes, wait until there is a character received from RS232
 10418:          clc                     ; return: No error
 10419:  
 10420:  BASIN_RTS2:
 10421:          rts
 10422:          ; --------------------
 10423:  .endif
 10424:          ; --------------------
 10425:  
 10426:  ;  B-5. Function Name: CHROUT a.k.a. BSOUT
 10427:  ;
 10428:  ;    Purpose: Output a character
 10429:  ;    Call address: $FFD2 (hex) 65490 (decimal)
 10430:  ;    Communication registers: A
 10431:  ;    Preparatory routines: (CHKOUT,OPEN)
 10432:  ;    Error returns: 0 (See READST)
 10433:  ;    Stack requirements: 8+
 10434:  ;    Registers affected: A
 10435:  ;
 10436:  ;    Description: This routine outputs a character to an already opened
 10437:  ;  channel. Use the KERNAL OPEN and CHKOUT routines to set up the output
 10438:  ;  channel before calling this routine, If this call is omitted, data is
 10439:  ;  sent to the default output device (number 3, the screen). The data byte
 10440:  ;  to be output is loaded into the accumulator, and this routine is called.
 10441:  ;  The data is then sent to the specified output device. The channel is left
 10442:  ;  open after the call.
 10443:  ;
 10444:  ;  +-----------------------------------------------------------------------+
 10445:  ;  | NOTE: Care must be taken when using this routine to send data to a    |
 10446:  ;  | specific serial device since data will be sent to all open output     |
 10447:  ;  | channels on the bus. Unless this is desired, all open output channels |
 10448:  ;  | on the serial bus other than the intended destination channel must be |
 10449:  ;  | closed by a call to the KERNAL CLRCHN routine.                        |
 10450:  ;  +-----------------------------------------------------------------------+
 10451:  ;
 10452:  ;
 10453:  ;
 10454:  ;  How to Use:
 10455:  ;
 10456:  ;    0) Use the CHKOUT KERNAL routine if needed, (see description above).
 10457:  ;    1) Load the data to be output into the accumulator.
 10458:  ;    2) Call this routine.
 10459:  ;
 10460:  ;  EXAMPLE:
 10461:  ;
 10462:  ;    ;DUPLICATE THE BASIC INSTRUCTION CMD 4,"A";
 10463:  ;    LDX #4          ;LOGICAL FILE #4
 10464:  ;    JSR CHKOUT      ;OPEN CHANNEL OUT
 10465:  ;    LDA #'A
 10466:  ;    JSR CHROUT      ;SEND CHARACTER
 10467:  ;
 10468:  ;
 10469:  KBSOUT:
 10470:          pha                             ; remember character to be output
 10471:          lda     zDFLTO                  ; get output device
 10472:          cmp     #FILE_SCREEN            ; is it the screen?
 10473:          bne     @NoScreen               ; no -> jump, test other devices
 10474:          pla                             ; get back the character to be output
 10475:          jmp     CHROUT_SCREEN           ; output to screen
 10476:          ; ----------------------
 10477:  
 10478:  @NoScreen:
 10479:          bcc     @NoIec                  ; device number is less than (or equal, but this cannot be here) than screen (3) -> jump, output is not on the IEC bus
 10480:          pla                             ; get back the character to be output
 10481:          jmp     iCIOUT                  ; output character to the IEC bus
 10482:  
 10483:  @NoIec:
 10484:  .if CompileComputer >= C64_GENERAL
 10485:          ; here, A can only contain 0, 1 or 2. "1" is tape, "2" is RS232.
 10486:          ; TODO: Can it contain 0 at all?
 10487:  
 10488:          lsr     a                       ; prepare comparison with RS232 device
 10489:          ; if C == 1, than output is to tape. If C == 0, then output is to console (0 - TODO) or RS232 (2).
 10490:  
 10491:  .else
 10492:          cmp     #FILE_RS232             ; output device = RS232?
 10493:          beq     KBSOUT_RS232            ; yes -> jump, output to RS232
 10494:  .endif
 10495:  
 10496:          pla                             ; get back the character to be output
 10497:  
 10498:  KBSOUT_TAPE:
 10499:  
 10500:          sta     zPTR1                   ; remember character to be output
 10501:  
 10502:  .if CompileComputer < C64_GENERAL
 10503:          pha                             ; remember character to be output on stack
 10504:  .endif
 10505:          txa                             ; remember X
 10506:          pha                             ; on stack
 10507:          tya                             ; remember Y
 10508:          pha                             ; on stack
 10509:  
 10510:  .if CompileComputer >= C64_GENERAL
 10511:          bcc     KBSOUT_RS232            ; we want to output onto RS232 (TODO: Or console (0)?) --> jump
 10512:  .endif
 10513:  
 10514:          ; if we reached here, it is BSOUT on tape
 10515:  
 10516:  .ifdef JIFFY
 10517:          jmp     JDLF3F1
 10518:  
 10519:  JDLF1E8:
 10520:          jsr     JDLF8BF
 10521:          jsr     JDLE4C6
 10522:          cmp     #$30
 10523:          rts
 10524:          jsr     bGTBYTC
 10525:          stx     zFA
 10526:          jsr     JDLF75C
 10527:          stx     zFSBLK
 10528:          rts
 10529:  
 10530:  .else
 10531:          jsr     TAPE_INCREMENT_WRITE_POINTER    ; increment pointer into tape buffer, and return it in Y
 10532:          bne     @BufferNotYetFull               ; buffer not yet full -> jump
 10533:  
 10534:          ; the tape buffer is full, write out the buffer and create a new one
 10535:          ;
 10536:          jsr     TapeWriteCompleteBuffer         ; write out the tape buffer to tape
 10537:          bcs     BSOUT_Quit                      ; C = 1 -> error -> quit
 10538:  
 10539:          lda     #TAPE_BUFFER_TYPE_CONTINUATION  ; mark the buffer: It is a continuation buffer
 10540:          ldy     #TAPE_BUFFER_OFFSET_TYPE        ; new pointer into the tape buffer
 10541:          sta     (zTAPE1),y                      ; store the mark for the buffer that it is a continuation buffer
 10542:          iny                                     ; advance buffer pointer
 10543:          sty     zBUFPNT                         ; and remember it
 10544:  
 10545:  @BufferNotYetFull:
 10546:          lda     zPTR1                           ; get character to be output
 10547:          sta     (zTAPE1),y                      ; put it into the tape buffer
 10548:  
 10549:  .endif
 10550:  
 10551:  BSOUT_QuitSuccess:
 10552:          clc                                     ; mark: We quit with success
 10553:  
 10554:  BSOUT_Quit:
 10555:          pla                                     ; restore Y from stack
 10556:          tay
 10557:          pla                                     ; restore X from stack
 10558:          tax
 10559:  .if CompileComputer >= C64_GENERAL
 10560:          lda     zPTR1                           ; restore A (character to be output)
 10561:  .else
 10562:          pla                                     ; restore A (character to be output) from stack
 10563:  .endif
 10564:  
 10565:          bcc     @Rts                            ; if routine was successfull, skip next instruction
 10566:          lda     #0                              ; set error number to 0 (TODO: why 0?)
 10567:  @Rts:   rts
 10568:  
 10569:  KBSOUT_RS232:
 10570:  
 10571:  .if CompileComputer < C64_GENERAL
 10572:          pla                             ; restore A (character to be output) from stack
 10573:          stx     zTEMPX                  ; remember X
 10574:          sty     zPTR1                   ; and Y
 10575:  .endif
 10576:  
 10577:          jsr     RS232_PUTCHAR           ; put character in A into RS232 output buffer
 10578:  
 10579:  .if CompileComputer >= C64_GENERAL
 10580:          jmp     BSOUT_QuitSuccess
 10581:          ; -----------------------
 10582:  .else
 10583:          ldx     zTEMPX                  ; restore X
 10584:          ldy     zPTR1                   ; and Y
 10585:          clc                             ; mark: success
 10586:          rts
 10587:          ; -----------------------
 10588:  .endif
 10589:          ; -----------------------
 10590:  
 10591:  ;  B-2. Function Name: CHKIN
 10592:  ;
 10593:  ;    Purpose: Open a channel for input
 10594:  ;    Call address: $FFC6 (hex) 65478 (decimal)
 10595:  ;    Communication registers: X
 10596:  ;    Preparatory routines: (OPEN)
 10597:  ;    Error returns:
 10598:  ;    Stack requirements: None
 10599:  ;    Registers affected: A, X
 10600:  ;
 10601:  ;
 10602:  ;    Description: Any logical file that has already been opened by the
 10603:  ;  KERNAL OPEN routine can be defined as an input channel by this routine.
 10604:  ;  Naturally, the device on the channel must be an input device. Otherwise
 10605:  ;  an error will occur, and the routine will abort.
 10606:  ;    If you are getting data from anywhere other than the keyboard, this
 10607:  ;  routine must be called before using either the CHRIN or the GETIN KERNAL
 10608:  ;  routines for data input. If you want to use the input from the keyboard,
 10609:  ;  and no other input channels are opened, then the calls to this routine,
 10610:  ;  and to the OPEN routine are not needed.
 10611:  ;    When this routine is used with a device on the serial bus, it auto-
 10612:  ;  matically sends the talk address (and the secondary address if one was
 10613:  ;  specified by the OPEN routine) over the bus.
 10614:  ;
 10615:  ;  How to Use:
 10616: