; ; 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 MANPARML = $40 !addr MANPARMH = $41 !addr DOSBUFL = $42 !addr DOSBUFH = $43 !addr ADDRESSL = $44 !addr ADDRESSH = $45 !addr FILESIZEL = $46 !addr FILESIZEH = $47 !addr OPSRCL = $48 !addr OPSRCH = $49 !addr OPDSTL = $4a !addr OPDSTH = $4b !addr LINE = $4c !addr ANIMATE = $4d 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 MANPARML sta MANPARMH ;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 (MANPARML), 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 ;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 KeyRet jsr SwitchScreens jsr EditorMode jsr SwitchScreens beq GetKey ;always SwitchScreens 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 VirtScroll lda ANIMATE beq + ;animate it just for fun jsr Delay + dec LINE bne -- KeyRet rts ;scroll HEIGHT lines VirtScroll 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 -- 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 ;disable animation (was #$FF from above) jsr SwitchScreens jsr CreateWriteFile jsr SwitchScreens dec ANIMATE ;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 KeyRet cmp #ESC beq KeyRet 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 lda ROMIN 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 sta (MANPARML), y 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 FirstLine ;pre-screen line to catch scroll !fill WIDTH, $A0 ;we reserve one line for status !text "CTRL+(" !scrxor $40, IMPORTKEY !text ")MPORT (" !scrxor $40, SAVEKEY !text ")AVE" !text " " !scrxor $80, "4LIVE-1" ;not the full $400 to save memory !fill WIDTH * (HEIGHT - 2), $A0 LastLine !fill WIDTH, $A0 LoadSaveEnd