diff --git a/src/WeeGUI_MLI.s b/src/WeeGUI_MLI.s new file mode 100644 index 0000000..5009e7c --- /dev/null +++ b/src/WeeGUI_MLI.s @@ -0,0 +1,71 @@ +; +; WeeGUI_MLI.s +; Machine Language API for WeeGUI +; +; Created by Quinn Dunki on 8/15/14. +; Copyright (c) 2014 One Girl, One Laptop Productions. All rights reserved. +; + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Reserved zero page locations +; +PARAM0 = $06 +PARAM1 = $07 +PARAM2 = $08 +PARAM3 = $09 + + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; WeeGUI entry point +; Set up your call, then do a JSR to this address. +; +WeeGUI = $4004 ; Offset of WGDispatch from 4000 + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; API call names, to be passed to WeeGUI via X register +; e.g. +; ldx #WGDesktop +; jsr WeeGUI +; +WGClearScreen = 0 +WGDesktop = 2 +WGSetCursor = 4 +WGSetGlobalCursor = 6 +WGSyncGlobalCursor = 8 +WGPlot = 10 +WGPrint = 12 +WGFillRect = 14 +WGStrokeRect = 16 +WGFancyRect = 18 +WGPaintView = 20 +WGViewPaintAll = 22 +WGEraseViewContents = 24 +WGCreateView = 26 +WGCreateCheckbox = 28 +WGCreateButton = 30 +WGViewSetTitle = 32 +WGViewSetAction = 34 +WGSelectView = 36 +WGViewFromPoint = 38 +WGViewFocus = 40 +WGViewUnfocus = 42 +WGViewFocusNext = 44 +WGViewFocusPrev = 46 +WGViewFocusAction = 48 +WGPendingViewAction = 50 +WGPendingView = 52 +WGScrollX = 54 +WGScrollXBy = 56 +WGScrollY = 58 +WGScrollYBy = 60 +WGEnableMouse = 62 +WGDisableMouse = 64 +WGDeleteView = 66 +WGEraseView = 68 +WGExit = 70 +WGCreateProgress = 72 +WGSetState = 74 +WGViewSetRawTitle = 76 diff --git a/src/pitchdark.a b/src/pitchdark.a new file mode 100644 index 0000000..04f0dee --- /dev/null +++ b/src/pitchdark.a @@ -0,0 +1,33 @@ +;license:BSD-3-Clause +;(c) 2018 by 4am + +!cpu 65c02 +!to "pitch.system#FF2000",plain +*=$2000 + + jmp Init + + !source "WeeGUI_MLI.s" + !source "prodos.a" + +Init + lda MACHID + and #$30 + cmp #$30 ; 128K? + beq + ; yes, continue + jmp QuitToProDOS ++ + jsr LoadFile1Shot + !word WGFILE + !word $4000 + !word $2000 + !word $1C00 + + jsr $4000 + ldx #WGClearScreen + jsr WeeGUI + rts + +WGFILE !byte wg_e-wg_b +wg_b !text "WEEGUI" +wg_e diff --git a/src/prodos.a b/src/prodos.a new file mode 100644 index 0000000..39dada7 --- /dev/null +++ b/src/prodos.a @@ -0,0 +1,512 @@ +; MLI command codes +CMD_QUIT = $65 ; quit to ProDOS +CMD_CREATE = $C0 ; create new file +CMD_DESTROY = $C1 ; delete a file +CMD_GETFILEINFO = $C4 ; get file (or volume) info +CMD_ONLINE = $C5 ; check online volume(s) +CMD_SETPREFIX = $C6 ; change default pathname prefix +CMD_OPEN = $C8 ; open a file +CMD_NEWLINE = $C9 ; set line-by-line read mode +CMD_READ = $CA ; read an open file +CMD_WRITE = $CB ; write to an open file +CMD_CLOSE = $CC ; close an open file +CMD_SETMARK = $CE ; change position in an open file +CMD_SETEOF = $D0 ; set file size + +; MLI parameter counts +PC_QUIT = $04 +PC_CREATE = $07 +PC_DESTROY = $01 +PC_GETFILEINFO = $0A +PC_ONLINE = $02 +PC_SETPREFIX = $01 +PC_OPEN = $03 +PC_NEWLINE = $03 +PC_READ = $04 +PC_WRITE = $04 +PC_CLOSE = $01 +PC_SETMARK = $02 +PC_SETEOF = $02 + +PRODOSMLI = $BF00 ; [callable] MLI entry point +MACHID = $BF98 + +; MLI error codes +ERR_FNF = $46 +ERR_EOF = $4C + +;------------------------------- +; SaveFile1Shot +; save a file to disk all at once, +; using ProDOS MLI calls +; +; in: stack contains 11 ($0B) bytes of parameters: +; +1 address of pathname +; +3 [byte] file type +; +4 [word] aux file type +; +6 address of data buffer +; +8 [word] length of data buffer +; +A address of ProDOS file buffer +; out: if C set, save failed and A contains error code +; from open or write +; if C clear, save succeeded +; all other flags clobbered +; all registers clobbered +; stack set to next instruction after parameters +;------------------------------- +!zone { +SaveFile1Shot + pla + sta $00 + pla + sta $01 + tax + lda #$0B + clc + adc $00 + bcc .noinc + inx +.noinc + tay + txa + pha + tya + pha + + ldy #$01 + lda ($00),y ; lo byte of pathname + sta mliparam+1 + iny + lda ($00),y ; hi byte of pathname + sta mliparam+2 + jsr DeleteFile ; don't care if this fails + ldy #$03 + lda ($00),y ; file type + sta mliparam+4 + iny + lda ($00),y ; lo byte of aux file type + sta mliparam+5 + iny + lda ($00),y ; hi byte of aux file type + sta mliparam+6 + jsr CreateFile + bcs .savefile1s + + ldy #$0A + lda ($00),y ; lo byte of ProDOS file buffer + sta mliparam+3 + iny + lda ($00),y ; hi byte of ProDOS file buffer + sta mliparam+4 + jsr OpenFile + bcs .savefile1s + + pha ; push file reference number + ldy #$06 + lda ($00),y ; lo address of data buffer + sta mliparam+2 + iny + lda ($00),y ; hi address of data buffer + sta mliparam+3 + iny + lda ($00),y ; lo data length + sta mliparam+4 + iny + lda ($00),y ; hi data length + sta mliparam+5 + pla ; pull file reference number + jsr WriteFile + php ; save flags from writefile + pha + jsr CloseFile ; always close whether write worked or not + pla + plp ; restore flags from write + ; (so caller gets codes from write attempt, + ; not close) + +.savefile1s + rts +} + +;------------------------------- +; LoadFile1Shot +; load a file into memory all at once, +; using ProDOS MLI calls +; +; in: stack contains 8 bytes of parameters: +; +1 address of pathname +; +3 address of data buffer (to receive file contents) +; +5 [word] maximum length of data to read +; +7 address of ProDOS file buffer +; out: if C set, load failed and A contains error code +; from open or read +; if C clear, load succeeded and ($02) contains +; data loaded from file +; all other flags clobbered +; all registers clobbered +; stack set to next instruction after parameters +;------------------------------- +!zone { +LoadFile1Shot + pla + sta $00 + pla + sta $01 + tax + lda #$08 + clc + adc $00 + bcc .noinc + inx +.noinc + tay + txa + pha + tya + pha + + ldy #$01 + lda ($00),y ; lo byte of pathname + sta mliparam+1 + iny + lda ($00),y ; hi byte of pathname + sta mliparam+2 + ldy #$07 + lda ($00),y ; lo byte of ProDOS file buffer + sta mliparam+3 + iny + lda ($00),y ; hi byte of ProDOS file buffer + sta mliparam+4 + + jsr OpenFile + bcs .loadfile1s ; C set on error + + pha ; push file reference number + ldy #$03 + lda ($00),y ; lo address of data buffer + sta mliparam+2 + iny + lda ($00),y ; hi address of data buffer + sta mliparam+3 + iny + lda ($00),y ; lo data length + sta mliparam+4 + iny + lda ($00),y ; hi data length + sta mliparam+5 + pla ; pull file reference number + jsr ReadFile + php ; save flags from readfile + pha + jsr CloseFile ; always close whether read worked or not + pla + plp ; restore flags from readfile + ; (so caller gets codes from read attempt, + ; not close) +.loadfile1s + rts +} + +;------------------------------- +; open file via ProDOS MLI +; +; in: caller has filled @mliparam with address of +; pathname, address of data buffer, and maximum +; data length +; out: if C set, open failed and A contains error code +; if C clear, open succeeded and A contains +; file reference number +;------------------------------- +!zone { +OpenFile + lda #CMD_OPEN ; MLI command + ldy #PC_OPEN ; number of parameters for 'open' command + jsr mli + bcs .openfile + lda refnum ; caller should save file reference number + ; as this memory location may be + ; overwritten by later MLI calls +.openfile + rts +} + +;------------------------------- +; set line-by-line mode via ProDOS MLI +; +; in: A = file reference number +; out: if C set, set failed and A contains error code +; if S clear, set succeeded and A contains the same +; file reference number that was passed in +;------------------------------- +lbl_mask = $7F +lbl_cr = $0D + +!zone { +SetLineByLine + sta mliparam+1 ; store file reference number + lda #lbl_mask ; accept high bit set or clear + sta mliparam+2 + lda #lbl_cr ; carriage return character + sta mliparam+3 + lda #CMD_NEWLINE ; MLI 'newline' command to set read mode + ldy #PC_NEWLINE ; number of parameters for 'newline' command + jsr mli + bcs .setlinebylin + lda mliparam+1 ; if no error, return file reference number +.setlinebylin + rts +} + +;------------------------------- +; read an open file via ProDOS MLI +; +; in: A = file reference number +; caller has filled @mliparam with address of +; data buffer and maximum data length +; out: if C set, read failed and A contains error code +; if C clear, read succeeded and A contains the same +; file reference number that was passed in +;------------------------------- +!zone { +ReadFile + sta mliparam+1 ; store file reference number + lda #CMD_READ ; MLI read command + ldy #PC_READ ; number of parameters for 'read' command + jsr mli + bcs .readfile + lda mliparam+1 ; if no error, return file reference number +.readfile + rts +} + +;------------------------------- +; change file position in an open file via ProDOS MLI +; +; in: A = file reference number +; caller has filled @mliparam+2/+3/+4 with +; new file position +; out: if C set, set_mark call failed and A contains error code +; if C clear, set_mark call succeeded and A contains +; the same file reference number that was passed in +;------------------------------- +!zone { +SetMark + sta mliparam+1 ; store file reference number + lda #CMD_SETMARK ; MLI set_mark command + ldy #PC_SETMARK ; number of params for 'set_mark' cmd + jsr mli + bcs .exit + lda mliparam+1 ; if no error, return file refnum +.exit rts +} + +;------------------------------- +; write to an open file via ProDOS MLI +; +; in: A = file reference number +; caller has filled @mliparam with address of +; data buffer and data length +; out: if C set, write failed and A contains error code +; if C clear, write succeeded and A contains the same +; file reference number that was passed in +;------------------------------- +!zone { +WriteFile + sta mliparam+1 ; store file reference number + lda #CMD_WRITE ; MLI write command + ldy #PC_WRITE ; number of parameters for 'write' command + jsr mli + bcs .writefile + lda mliparam+1 ; if no error, return file reference number +.writefile + rts +} + +;------------------------------- +; set file size in an open file via ProDOS MLI +; +; in: A = file reference number +; caller has filled @mliparam+2/+3/+4 with +; new file size +; out: if C set, set_eof call failed and A contains error code +; if C clear, set_eof call succeeded and A contains +; the same file reference number that was passed in +;------------------------------- +!zone { +SetEOF + sta mliparam+1 ; store file reference number + lda #CMD_SETEOF ; MLI set_eof command + ldy #PC_SETEOF ; number of params for 'set_eof' cmd + jsr mli + bcs .exit + lda mliparam+1 ; if no error, return file refnum +.exit rts +} + +;------------------------------- +; close an open file +; in: A = file reference number +; out: if error, C set and A contains error code +; if success, C clear +;------------------------------- +CloseFile + sta mliparam+1 ; store file reference number + lda #CMD_CLOSE ; MLI close command + ldy #PC_CLOSE ; number of parameters for 'close' command + jsr mli + rts + +;------------------------------- +; create a file via ProDOS MLI +; always sets access bits to $C3 (full access) +; always sets creation to 0 (current date/time) +; always sets storage type to 1 (file) +; in: caller has filled @mliparam +; with address of pathname, +; file type, aux file type +; out: if error, C set and A contains error code +; if success, C clear +;------------------------------- +accessbits = $C3 ; full access + +CreateFile + lda #accessbits + sta mliparam+3 ; access bits (full access) + ldy #1 + sty mliparam+7 ; storage type (file) + dey + sty mliparam+8 ; creation date (current) + sty mliparam+9 + sty mliparam+10 ; creation time (current) + sty mliparam+11 + lda #CMD_CREATE ; MLI create command + ldy #PC_CREATE ; number of parameters for 'create' command + jsr mli + rts + +;------------------------------- +; delete a file using ProDOS MLI +; in: caller has filled @mliparam +; with address of pathname +; out: if error, C set and A contains error code +; if success, C clear +;------------------------------- +DeleteFile + lda #CMD_DESTROY ; MLI destroy command + ldy #PC_DESTROY ; number of parameters for 'destroy' command + jsr mli + rts + +;------------------------------- +; change current directory (set prefix) +; using ProDOS MLI +; in: caller has filled @mliparam +; with address of pathname +; out: if error, C set and A contains error code +; if success, C clear +;------------------------------- +SetPrefix + lda #CMD_SETPREFIX + ldy #PC_SETPREFIX + jsr mli + rts + +;------------------------------- +; get volume name of disk in specific slot+drive +; in: A = unit number (DSSS0000) +; out: if no disk in drive or any MLI error, C set and A contains error code +; if disk found, C clear and @VolumeName contains volume name +; (length byte + up to 14 character name, no leading slash) +;------------------------------- +!zone { +GetVolumeName + sta mliparam+1 + lda #OnlineReturn + sta mliparam+3 + jsr Online + rts +OnlineReturn + !byte $FF +VolumeName + !byte $FF,$FF,$FF,$FF,$FF,$FF,$FF + !byte $FF,$FF,$FF,$FF,$FF,$FF,$FF,$FF +} + +;------------------------------- +; check if volume is online +; using ProDOS MLI +; in: caller has filled @mliparam +; with unit number +; out: if error, C set and A contains error code +; if success, C clear +;------------------------------- +Online + lda #CMD_ONLINE + ldy #PC_ONLINE + jsr mli + rts + +;------------------------------- +; query volume information +; using ProDOS MLI +; in: nothing (queries last fetched volume) +; out: if error, C set and A contains error code +; if success, C clear and MLI buffer is filled +; (access, file type, block count, dates and times) +;------------------------------- +GetVolumeInfo + lda OnlineReturn + and #$0F + tax + inx + stx OnlineReturn + tay +- lda OnlineReturn,y + sta VolumeName,y + dey + bne - + lda #$2F ;'/' + sta VolumeName + lda #OnlineReturn + sta mliparam+2 + lda #CMD_GETFILEINFO + ldy #PC_GETFILEINFO + jsr mli + rts + +QuitToProDOS + lda CMD_QUIT + ldy PC_QUIT +; execution falls through here + +;------------------------------- +; low-level MLI wrapper +; in: A = MLI command code +; Y = number of MLI parameters +; caller has filled @mliparam +; with all relevant parameters +; out: returns immediately after +; calling MLI, so whatever +; state the MLI routine sets, +; the caller will see it +; verbatim +;------------------------------- +mli sta mlicmd ; store command code + sty mliparam ; number of parameters + jsr PRODOSMLI ; call ProDOS +mlicmd !byte 00 ; command number + !word mliparam ; address of parameter table + rts +mliparam !byte $FE,$FE,$FE,$FE +filetype !byte $FE ; file type (set by MLI get_file_info) +auxtype ; auxiliary file type (2 bytes, set by MLI get_file_info) +refnum !byte $FE ; file refnum (set by MLI open) +mlilen !byte $FE,$FE ; file length (set by MLI read) +blocks !byte $FE,$FE ; blocks used (set by getvolumeinfo) + ; member is also used by createfile + !byte $FE,$FE,$FE,$FE,$FE,$FE,$FE,$FE + ; used by get_file_info