; ; 4LIVE ; a 4am & san inc hack ; !cpu 6502 *=$8000 ; !addr WNDLFT = $20 !addr WNDWDTH = $21 !addr WNDTOP = $22 !addr WNDBTM = $23 !addr CH = $24 !addr CV = $25 !addr GBASL = $26 !addr GBASH = $27 !addr BASL = $28 !addr BASH = $29 !addr BAS2L = $2A !addr BAS2H = $2B !addr KSWL = $38 !addr KSWH = $39 !addr GETIOB = $3E3 !addr RECONNECTDOS = $3EA !addr WARMDOS = $3D0 !addr DOSBASE = $3D2 !addr FILEMAN = $3D6 !addr GETPARM = $3DC !addr KBD = $C000 !addr STROBE = $C010 !addr ROMIN = $C081 !addr LCBANK2 = $C083 !addr GBASCALC = $F847 !addr BASCALC = $FBC1 !addr SCROLL = $FC70 !addr WAIT = $FCA8 !addr KEYIN = $FD1B !addr COUT = $FDED ;private arbitrary addresses !addr LINE = $40 !addr ZMANPARML = $40 !addr ZMANPARMH = $41 !addr DOSBUFL = $42 !addr DOSBUFH = $43 !addr OPSRCL = $44 !addr OPSRCH = $45 !addr OPDSTL = $46 !addr OPDSTH = $47 HOTKEY = $80 ; CTRL-@ IMPORTKEY = $89 ; CTRL-I SAVEKEY = $93 ; CTRL-S ;constants LTARROW = $88 UPARROW = $8B RETURN = $8D RTARROW = $95 ESC = $9B WIDTH = 40 HEIGHT = 24 IOBSLOT = 1 IOBDRIVE = 2 NEXTFILE = 36 PARMRANGE = 6 PARMFILE = 8 PARMWORK = 12 NAMELEN = 30 CREATEFILE = 0 OPENEXISTING = 1 SPECIAL = 8 CMDOPEN = 1 CMDCLOSE = 2 CMDREAD = 3 CMDWRITE = 4 READRANGE = 2 ; Install ;find a free DOS buffer ldy #0 sty DOSBUFL lda DOSBASE ;check for DiversiDOS cmp #$BF bne + lda LCBANK2 lda LCBANK2 lda #$DD ;back to regular DOS + sta DOSBUFH !byte $2C ;mask LDY - ldy #NEXTFILE lda (DOSBUFL), y tax iny lda (DOSBUFL), y stx DOSBUFL sta DOSBUFH ;set filename pointer in MLI request packet stx FileName sta FileName + 1 ;check for empty filename (indicates free buffer) ldy #0 lda (DOSBUFL), y bne - ;get file manager parameter list jsr GETPARM sty ZMANPARML sta ZMANPARMH sty MANPARM + 1 sta MANPARM + 2 ;copy DOS buffer pointers to file manager parameter list lda #NAMELEN sta OPDSTL lda #PARMWORK sta OPDSTH ldx #(6 - 1) - ldy OPDSTL lda (DOSBUFL), y ldy OPDSTH sta (ZMANPARML), y inc OPDSTL inc OPDSTH dex bpl - ;set input name ldy #(NAMELEN - 1) lda #$A0 - cpy #(FileName_e - FileName_b) bcs + lda FileName_b, y + sta (DOSBUFL), y dey bpl - sty ANIMATE + 1 ;enable visible screen-swapping via #$FF ;open source file and read it if available jsr OpenReadFile lda SaveCH sta MyCH lda SaveCV sta MyCV ;switch to write mode for future accesses inc ReadWriteCmd ;lda WRITECMD / sta ReadWriteCmd lda ROMIN ;display the welcome message, now that we're finally done ldy #0 beq + - jsr COUT + iny lda _WelcomeMessage-1,y bne - lda #GlobalKeyboardHook sta KSWH jsr RECONNECTDOS jmp WARMDOS _WelcomeMessage !scrxor $80, $8D, "4LIVE READY. PRESS CTRL-", HOTKEY + $40, " TO ACTIVATE.", $8D, 0 ;support enhanced flashing cursor while waiting for key, if available ;it works by passing to the routine the character under the cursor ;the ROM toggles between that character and the Delete character GetKey ldy CH lda (BASL), y GlobalKeyboardHook ;let DOS handle initial cursor jsr KEYIN cmp #HOTKEY bne ReusableRTS1 jsr ScrollEditScreenIn jsr EditorMode jsr ScrollEditScreenOut beq GetKey ;always ScrollEditScreenIn lda #HEIGHT sta LINE -- ldy #(WIDTH - 1) - lda $7D0, y sta LastLine, y dey bpl - jsr ScrollTextScreenDown ldy #(WIDTH - 1) - lda FirstLine, y sta $400, y dey bpl - jsr Delay dec LINE bne -- ReusableRTS1 rts ScrollEditScreenOut jsr SwapCoords ;copy first line of physical screen to first line of virtual screen lda #HEIGHT sta LINE -- ldy #(WIDTH - 1) - lda $400, y sta FirstLine, y dey bpl - ;scroll up physical screen jsr SCROLL ;append line from virtual screen ldy #(WIDTH - 1) - lda LastLine, y sta $7D0, y dey bpl - ;scroll down virtual screen jsr VirtScrollDown ANIMATE lda "Q" ;self-modified beq + ;animate it just for fun jsr Delay + dec LINE bne -- rts ScrollTextScreenDown ldx #$16 - lda TextCalcLo, x sta _a+1 lda TextCalcLo+1, x sta _b+1 lda TextCalcHi, x sta _a+2 lda TextCalcHi+1, x sta _b+2 ldy #$27 _a lda $FFFF, y ; self-modified, above _b sta $FFFF, y ; self-modified, above dey bpl _a dex bpl - rts ;scroll HEIGHT lines VirtScrollDown lda #<(LastLine - WIDTH) sta GBASL lda #>(LastLine - WIDTH) sta GBASH lda #LastLine sta BAS2H ldx #HEIGHT -- ldy #(WIDTH - 1) - lda (GBASL), y sta (BAS2L), y dey bpl - sec lda GBASL sbc #WIDTH sta GBASL bcs + dec GBASH sec + lda BAS2L sbc #WIDTH sta BAS2L bcs + dec BAS2H + dex bne -- ReusableRTS2 rts Delay lda #1 jmp WAIT ;swap real X/Y with virtual X/Y ;and recalculate screen position SwapCoords ldx #(6 - 1) - ldy WNDLFT, x lda MyWNDLFT, x sta WNDLFT, x tya sta MyWNDLFT, x dex bpl - jmp BASCALC ;restore temporarily the original screen ;so that notes are stored together SaveFile lda CH sta SaveCH lda CV sta SaveCV inc ANIMATE + 1 ;disable animation (was #$FF from above) jsr ScrollEditScreenOut jsr CreateWriteFile jsr ScrollEditScreenOut dec ANIMATE + 1 ;re-enable animation ;print anything that isn't a special key ;wrap around screen position when we hit edges EditorMode ldy CH lda (BASL), y jsr KEYIN cmp #HOTKEY beq ReusableRTS2 cmp #ESC beq ReusableRTS2 cmp #SAVEKEY beq SaveFile cmp #IMPORTKEY beq ImportScreen cmp #LTARROW beq LineLeft cmp #UPARROW beq LineUp cmp #RTARROW beq LineRight OutChar jsr COUT lda CV eor #(HEIGHT - 1) ;zero on match bne EditorMode SetRow sta CV SetRow1 lda CV jsr BASCALC bcc EditorMode ;always LineLeft dec CH bpl SetRow1 lda #(WIDTH - 1) SetColumn sta CH bpl SetRow1 ;always LineUp dec CV bpl SetRow1 lda #(HEIGHT - 2) bne SetRow ;always LineRight inc CH lda CH eor #WIDTH ;zero on match bne SetRow1 beq SetColumn ;always ImportScreen lda #<(FirstLine + WIDTH) sta OPSRCL lda #>(FirstLine + WIDTH) sta OPSRCH ldx #(HEIGHT - 2) ;use graphics function to not disturb text state -- txa jsr GBASCALC ldy #(WIDTH - 1) - lda (OPSRCL), y sta (GBASL), y dey bpl - lda OPSRCL clc adc #WIDTH sta OPSRCL bcc + inc OPSRCH + dex bpl -- bmi EditorMode OpenReadFile lda LCBANK2 lda LCBANK2 ;support DiversiDOS jsr GETIOB sty OPSRCL sta OPSRCH ldy #IOBSLOT lda (OPSRCL), y lsr lsr lsr lsr sta FileSlot iny ;ldy #IOBDRIVE lda (OPSRCL), y sta FileDrive ldx #OPENEXISTING jsr OpenCommon bcs OpenRet ReadFile WriteFile jsr DOSMLI !byte ReadMLI_e - ReadMLI_b ReadMLI_b ReadWriteCmd !byte CMDREAD !byte READRANGE !word 0 ;record number !word 0 ;offset WriteSize !word -1 ;number of bytes !word LoadSaveStart ;buffer ReadMLI_e CloseFile jsr DOSMLI !byte CloseMLI_e - CloseMLI_b CloseMLI_b !byte CMDCLOSE CloseMLI_e OpenRet rts OpenCommon jsr DOSMLI !byte OpenMLI_e - OpenMLI_b OpenMLI_b !byte CMDOPEN !byte 0 ;unused !word 0 ;variable records !byte 0 ;any volume FileDrive !text "Q" ;self-modified FileSlot !text "Q" ;self-modified !byte SPECIAL ;file type for when we save FileName !text "4s" ;self-modified OpenMLI_e rts CreateWriteFile ldx #CREATEFILE jsr OpenCommon bcs OpenRet lda #<(LoadSaveEnd - LoadSaveStart) sta WriteSize lda #>(LoadSaveEnd - LoadSaveStart) sta WriteSize + 1 bcc WriteFile ;always ;first byte fetched is number of byte to follow, ;copy parameters to file manager parameter list, ;and then dispatch the request DOSMLI pla tay pla sta OPSRCH iny sty OPSRCL bne + inc OPSRCH + ldy #0 lda (OPSRCL), y tay - lda (OPSRCL), y dey MANPARM sta $34f3, y ;self-modified bne - lda (OPSRCL), y clc adc OPSRCL tay lda OPSRCH adc #0 pha tya pha jmp FILEMAN FileName_b !scrxor $80, $DF, "4LIVE DATA" FileName_e MyWNDLFT !byte 0 MyWNDWDTH !byte WIDTH MyWNDTOP !byte 0 MyWNDBTM !byte HEIGHT MyCH !byte 0 MyCV !byte 0 LoadSaveStart SaveCH !byte 0 ;loaded from file if exists SaveCV !byte 0 ;loaded from file if exists TextCalcHi !byte $04, $04, $05, $05, $06, $06, $07, $07 !byte $04, $04, $05, $05, $06, $06, $07, $07 !byte $04, $04, $05, $05, $06, $06, $07, $07 TextCalcLo !byte $00, $80, $00, $80, $00, $80, $00, $80 !byte $28, $A8, $28, $A8, $28, $A8, $28, $A8 !byte $50, $D0, $50, $D0, $50, $D0, $50, $D0 FirstLine ;pre-screen line to catch scroll !fill WIDTH, $A0 ;we reserve one line for status !scrxor $40, "CTRL" !text "+(" !scrxor $40, IMPORTKEY !text ")" !scrxor $40, "MPORT" !text " (" !scrxor $40, SAVEKEY !text ")" !scrxor $40, "AVE" !text " " !scrxor $80, "4LIVE-1" ;not the full $400 to save memory !fill WIDTH * (HEIGHT - 2), $A0 LastLine !fill WIDTH, $A0 LoadSaveEnd