.setcpu "6502" .include "apple2.inc" .include "../inc/ascii.inc" .include "../inc/prodos.inc" .include "../inc/auxmem.inc" .include "../mgtk.inc" .include "../desktop.inc" ; get/clear selection, font .org $800 start: jmp copy2aux save_stack:.byte 0 ;;; Copy $800 through $13FF (the DA) to aux .proc copy2aux tsx stx save_stack sta RAMWRTON ldy #0 src: lda start,y ; self-modified dst: sta start,y ; self-modified dey bne src sta RAMWRTOFF inc src+2 inc dst+2 sta RAMWRTON lda dst+2 cmp #$14 bne src .endproc call_main_trampoline := $20 ; installed on ZP, turns off auxmem and calls... call_main_addr := call_main_trampoline+7 ; address patched in here ;;; Copy the following "call_main_template" routine to $20 .scope sta RAMWRTON sta RAMRDON ldx #sizeof_call_main_template loop: lda call_main_template,x sta call_main_trampoline,x dex bpl loop jmp call_init .endscope .proc call_main_template sta RAMRDOFF sta RAMWRTOFF jsr $1000 ; overwritten (in zp version) sta RAMRDON sta RAMWRTON rts .endproc sizeof_call_main_template := * - call_main_template .proc call_init ;; run the DA jsr init ;; tear down/exit sta ALTZPON lda LCBANK1 lda LCBANK1 sta RAMRDOFF sta RAMWRTOFF ldx save_stack txs rts .endproc ;;; ================================================== ;;; ProDOS MLI calls .proc open_file jsr copy_params_aux_to_main sta ALTZPOFF MLI_CALL OPEN, open_params sta ALTZPON jsr copy_params_main_to_aux rts .endproc .proc read_file jsr copy_params_aux_to_main sta ALTZPOFF MLI_CALL READ, read_params sta ALTZPON jsr copy_params_main_to_aux rts .endproc .proc get_file_eof jsr copy_params_aux_to_main sta ALTZPOFF MLI_CALL GET_EOF, get_eof_params sta ALTZPON jsr copy_params_main_to_aux rts .endproc .proc set_file_mark jsr copy_params_aux_to_main sta ALTZPOFF MLI_CALL SET_MARK, set_mark_params sta ALTZPON jsr copy_params_main_to_aux rts .endproc .proc close_file jsr copy_params_aux_to_main sta ALTZPOFF MLI_CALL CLOSE, close_params sta ALTZPON jsr copy_params_main_to_aux rts .endproc ;;; ================================================== ;;; Copies param blocks from Aux to Main .proc copy_params_aux_to_main ldy #(params_end - params_start + 1) sta RAMWRTOFF loop: lda params_start - 1,y sta params_start - 1,y dey bne loop sta RAMRDOFF rts .endproc ;;; Copies param blocks from Main to Aux .proc copy_params_main_to_aux pha php sta RAMWRTON ldy #(params_end - params_start + 1) loop: lda params_start - 1,y sta params_start - 1,y dey bne loop sta RAMRDON plp pla rts .endproc ;;; ---------------------------------------- params_start: ;;; This block gets copied between main/aux ;;; ProDOS MLI param blocks .proc open_params .byte 3 ; param_count .addr pathname ; pathname .addr $0C00 ; io_buffer ref_num:.byte 0 ; ref_num .endproc default_buffer := $1200 .proc read_params .byte 4 ; param_count ref_num:.byte 0 ; ref_num buffer: .addr default_buffer ; data_buffer .word $100 ; request_count .word 0 ; trans_count .endproc .proc get_eof_params .byte 2 ; param_count ref_num:.byte 0 ; ref_num .byte 0,0,0 ; EOF (lo, mid, hi) .endproc .proc set_mark_params .byte 2 ; param_count ref_num:.byte 0 ; ref_num .faraddr 0 ; position (lo, mid, hi) .endproc .proc close_params .byte 1 ; param_count ref_num:.byte 0 ; ref_num .endproc .proc pathname ; 1st byte is length, rest is full path length: .byte $00 data: .res 64, $00 .endproc L0945: .byte $00 L0946: .byte $00 L0947: .byte $00 L0948: .byte $00 L0949: .byte $00 params_end := * + 4 ; bug in original? (harmless as this is static) ;;; ---------------------------------------- black_pattern: .res 8, $00 white_pattern: .res $8, $FF da_window_id := 100 L095A: .byte $00 L095B: .byte $FA L095C: .byte $01 .proc line_pos left: .word 0 base: .word 0 .endproc window_width: .word 0 window_height: .word 0 L0965: .byte $00 L0966: .byte $00,$00 L0968: .byte $00 L0969: .byte $00 L096A: .byte $00 L096B: .byte $00 L096C: .byte $00 L096D: .byte $00 track_scroll_delta: .byte $00 fixed_mode_flag: .byte $00 ; 0 = proportional, otherwise = fixed .proc event_params kind: .byte 0 coords: ; spills into target query mousex: .word 0 mousey: .word 0 .endproc .proc findwindow_params which_area: .byte 0 window_id: .byte 0 .endproc .proc growwindow_params window_id: .byte da_window_id mousex: .word 0 mousey: .word 0 it_grew: .byte 0 .endproc .proc trackgoaway_params ; queried after close clicked to see if aborted/finished goaway: .byte 0 ; 0 = aborted, 1 = clicked .endproc .byte 0,0 ; ??? .proc findcontrol_params ; queried after a client click to identify target mousex: .word 0 mousey: .word 0 which_ctl: .byte 0 ; 0 = client, 1 = vscroll, 2 = hscroll which_part: .byte 0 ; 1 = up, 2 = down, 3 = above, 4 = below, 5 = thumb .endproc ;; param block used in dead code (resize?) .proc setctlmax_params which_ctl: .byte 0 ctlmax: .byte 0 ;; needs one more byte? .endproc .proc updatethumb_params ; called to update scroll bar position which_ctl: .byte 0 ; 1 = vscroll, 2 = hscroll thumbpos: .byte 0 ; new position .endproc ;;; Used when dragging vscroll thumb .proc trackthumb_params which_ctl: .byte 0 ; 1 = vscroll, 2 = hscroll mousex: .word 0 mousey: .word 0 thumbpos: .byte 0 ; position thumbmoved: .byte 0 ; 0 if not moved, 1 if moved .endproc .proc drawtext_params textptr: .addr 0 ; address textlen: .byte 0 ; length .endproc default_width := 512 default_height := 150 default_left := 10 default_top := 28 .proc winfo window_id: .byte da_window_id ; window identifier options: .byte MGTK::option_go_away_box; window flags (2=include close port) title: .addr $1000 ; overwritten to point at filename hscroll:.byte MGTK::scroll_option_none vscroll:.byte MGTK::scroll_option_normal hthumbmax: .byte 32 hthumbpos: .byte 0 vthumbmax: .byte 255 vthumbpos: .byte 0 status: .byte 0 reserved: .byte 0 mincontwidth: .word 200 mincontlength: .word 51 maxcontwidth: .word default_width maxcontlength: .word default_height port: DEFINE_POINT default_left, default_top, viewloc mapbits: .addr MGTK::screen_mapbits mapwidth: .word MGTK::screen_mapwidth DEFINE_RECT 0, 0, default_width, default_height, maprect pattern:.res 8, $00 colormasks: .byte MGTK::colormask_and, MGTK::colormask_or penloc: DEFINE_POINT 0, 0 penwidth: .byte 1 penheight: .byte 1 penmode: .byte 0 textback: .byte $7F textfont: .addr DEFAULT_FONT nextwinfo: .addr 0 .endproc ;; gets copied over winfo::port after mode is drawn .proc default_port viewloc: DEFINE_POINT default_left, default_top mapbits: .word MGTK::screen_mapbits mapwidth: .word MGTK::screen_mapwidth maprect: DEFINE_RECT 0, 0, default_width, default_height .endproc .proc init sta ALTZPON lda LCBANK1 lda LCBANK1 ;; Get filename by checking DeskTop selected window/icon ;; Check that an icon is selected lda #0 sta pathname::length lda file_selected beq abort ; some file properties? lda path_index ; prefix index in table bne :+ abort: rts ;; Copy path (prefix) into pathname buffer. : src := $06 dst := $08 asl a ; (since address table is 2 bytes wide) tax lda path_table,x ; pathname ??? sta src lda path_table+1,x sta src+1 ldy #0 lda (src),y tax inc src bne :+ inc src+1 : lda #<(pathname::data) sta dst lda #>(pathname::data) sta dst+1 jsr copy_pathname ; copy x bytes (src) to (dst) ;; Append separator. lda #'/' ldy #0 sta (dst),y inc pathname::length inc dst bne :+ inc dst+1 ;; Get file entry. : lda file_index ; file index in table asl a ; (since table is 2 bytes wide) tax lda file_table,x sta src lda file_table+1,x sta src+1 ;; Exit if a directory. ldy #2 ; 2nd byte of entry lda (src),y and #$70 ; check that one of bits 4,5,6 is set ??? ;; some vague patterns, but unclear ;; basic = $32,$33, text = $52, sys = $11,$14,??, bin = $23,$24,$33 ;; dir = $01 (so not shown) bne :+ rts ; abort ??? ;; Set window title to point at filename (9th byte of entry) ;; (title includes the spaces before/after from the icon) : clc lda src ; name is 9 bytes into entry adc #9 sta winfo::title lda src+1 adc #0 sta winfo::title+1 ;; Append filename to path. ldy #9 lda (src),y ; grab length tax ; name has spaces before/after dex ; so subtract 2 to get actual length dex clc lda src adc #11 ; 9 = length, 10 = space, 11 = name sta src bcc :+ inc src+1 : jsr copy_pathname ; copy x bytes (src) to (dst) ;; Clear selection (why???) lda #JUMP_TABLE_CLEAR_SEL sta call_main_addr+1 jsr call_main_trampoline jmp open_file_and_init_window .proc copy_pathname ; copy x bytes from src to dst ldy #0 ; incrementing path length and dst loop: lda (src),y sta (dst),y iny inc pathname::length dex bne loop tya clc adc dst sta dst bcc end inc dst+1 end: rts .endproc .endproc font_width_backup := $1100 .proc open_file_and_init_window lda #0 sta fixed_mode_flag ;; make backup of font width table; overwritten if fixed ldx font_size_count sta RAMWRTOFF loop: lda font_width_table - 1,x sta font_width_backup - 1,x dex bne loop sta RAMWRTON ;; open file, get length jsr open_file lda open_params::ref_num sta read_params::ref_num sta set_mark_params::ref_num sta get_eof_params::ref_num sta close_params::ref_num jsr get_file_eof ;; create window MGTK_CALL MGTK::OpenWindow, winfo MGTK_CALL MGTK::SetPort, winfo::port jsr calc_window_size jsr calc_and_draw_mode jsr draw_content MGTK_CALL MGTK::FlushEvents ;; fall through .endproc ;;; ================================================== ;;; Main Input Loop input_loop: MGTK_CALL MGTK::GetEvent, event_params lda event_params cmp #1 ; was clicked? bne input_loop ; nope, keep waiting MGTK_CALL MGTK::FindWindow, event_params::coords lda findwindow_params::window_id ; in our window? cmp #da_window_id bne input_loop ;; which part of the window? lda findwindow_params::which_area cmp #MGTK::area_close_box beq on_close_click ;; title and resize clicks need mouse location ldx event_params::mousex stx growwindow_params::mousex stx findcontrol_params::mousex ldx event_params::mousex+1 stx growwindow_params::mousex+1 stx findcontrol_params::mousex+1 ldx event_params::mousey stx growwindow_params::mousey stx findcontrol_params::mousey cmp #MGTK::area_dragbar beq title cmp #MGTK::area_grow_box ; not enabled, so this will never match beq input_loop jsr on_client_click jmp input_loop title: jsr on_title_bar_click jmp input_loop ;;; ================================================== ;;; Close Button .proc on_close_click MGTK_CALL MGTK::TrackGoAway, trackgoaway_params lda trackgoaway_params::goaway ; did click complete? beq input_loop ; nope jsr close_file MGTK_CALL MGTK::CloseWindow, winfo DESKTOP_CALL DESKTOP_REDRAW_ICONS rts ; exits input loop .endproc ;;; ================================================== ;;; Resize Handle ;;; This is dead code (no resize handle!) and may be buggy .proc on_resize_click MGTK_CALL MGTK::GrowWindow, growwindow_params jsr redraw_screen jsr calc_window_size max_width := default_width lda #>max_width cmp winfo::maprect::x2+1 bne :+ lda #max_width sta winfo::maprect::x2+1 sec lda winfo::maprect::x2 sbc window_width sta winfo::maprect::x1 lda winfo::maprect::x2+1 sbc window_width+1 sta winfo::maprect::x1+1 wider: lda winfo::hscroll ldx window_width cpx #max_width bne enable and #(<~MGTK::scroll_option_active) ; disable scroll jmp :+ enable: ora #MGTK::scroll_option_active ; enable scroll : sta winfo::hscroll sec lda #max_width sbc window_width+1 sta $07 jsr div_by_16 sta setctlmax_params::ctlmax lda #MGTK::ctl_horizontal_scroll_bar sta setctlmax_params::which_ctl MGTK_CALL MGTK::SetCtlMax, setctlmax_params ; change to clamped size ??? jsr calc_and_draw_mode jmp finish_resize .endproc ;;; ================================================== ;;; Client Area ;;; Non-title (client) area clicked .proc on_client_click ;; On one of the scroll bars? MGTK_CALL MGTK::FindControl, findcontrol_params lda findcontrol_params::which_ctl cmp #MGTK::ctl_vertical_scroll_bar beq on_vscroll_click cmp #MGTK::ctl_horizontal_scroll_bar bne end jmp on_hscroll_click end: rts .endproc ;;; ================================================== ;;; Vertical Scroll Bar .proc on_vscroll_click lda #MGTK::ctl_vertical_scroll_bar sta trackthumb_params::which_ctl sta updatethumb_params::which_ctl lda findcontrol_params::which_part cmp #MGTK::part_thumb beq on_vscroll_thumb_click cmp #MGTK::part_page_down beq on_vscroll_below_click cmp #MGTK::part_page_up beq on_vscroll_above_click cmp #MGTK::part_up_arrow beq on_vscroll_up_click cmp #MGTK::part_down_arrow bne end jmp on_vscroll_down_click end: rts .endproc .proc on_vscroll_thumb_click jsr do_trackthumb lda trackthumb_params::thumbmoved beq end lda trackthumb_params::thumbpos sta updatethumb_params::thumbpos jsr update_voffset jsr update_vscroll jsr draw_content lda L0947 beq end lda L0949 bne end jsr clear_window end: rts .endproc .proc on_vscroll_above_click loop: lda winfo::vthumbpos beq end jsr calc_track_scroll_delta sec lda winfo::vthumbpos sbc track_scroll_delta bcs store lda #0 ; underflow store: sta updatethumb_params::thumbpos jsr update_scroll_pos bcc loop ; repeat while button down end: rts .endproc .proc on_vscroll_up_click loop : lda winfo::vthumbpos beq end sec sbc #1 sta updatethumb_params::thumbpos jsr update_scroll_pos bcc loop ; repeat while button down end: rts .endproc vscroll_max := $FA .proc on_vscroll_below_click loop: lda winfo::vthumbpos cmp #vscroll_max ; pos == max ? beq end jsr calc_track_scroll_delta clc lda winfo::vthumbpos adc track_scroll_delta ; pos + delta bcs overflow cmp #vscroll_max+1 ; > max ? bcc store ; nope, it's good overflow: lda #vscroll_max ; set to max store: sta updatethumb_params::thumbpos jsr update_scroll_pos bcc loop ; repeat while button down end: rts .endproc .proc on_vscroll_down_click loop: lda winfo::vthumbpos cmp #vscroll_max beq end clc adc #1 sta updatethumb_params::thumbpos jsr update_scroll_pos bcc loop ; repeat while button down end: rts .endproc .proc update_scroll_pos ; Returns with carry set if mouse released jsr update_voffset jsr update_vscroll jsr draw_content jsr was_button_released clc bne end sec end: rts .endproc .proc calc_track_scroll_delta lda window_height ; ceil(??? / 50) ldx #0 loop: inx sec sbc #50 cmp #50 bcs loop stx track_scroll_delta rts .endproc ;;; ================================================== ;;; Horizontal Scroll Bar ;;; (Unused in STF DA, so most of this is speculation) .proc on_hscroll_click lda #MGTK::ctl_horizontal_scroll_bar sta trackthumb_params::which_ctl sta updatethumb_params::which_ctl lda findcontrol_params::which_part cmp #MGTK::part_thumb beq on_hscroll_thumb_click cmp #MGTK::part_page_right beq on_hscroll_after_click cmp #MGTK::part_page_left beq on_hscroll_before_click cmp #MGTK::part_left_arrow beq on_hscroll_left_click cmp #MGTK::part_right_arrow beq on_hscroll_right_click rts .endproc .proc on_hscroll_thumb_click jsr do_trackthumb lda trackthumb_params::thumbmoved beq end lda trackthumb_params::thumbpos jsr mul_by_16 lda $06 sta winfo::maprect::x1 lda $07 sta winfo::maprect::x1+1 clc lda winfo::maprect::x1 adc window_width sta winfo::maprect::x2 lda winfo::maprect::x1+1 adc window_width+1 sta winfo::maprect::x2+1 jsr update_hscroll jsr draw_content end: rts .endproc .proc on_hscroll_after_click ldx #2 lda winfo::hthumbmax jmp hscroll_common .endproc .proc on_hscroll_before_click ldx #254 lda #0 jmp hscroll_common .endproc .proc on_hscroll_right_click ldx #1 lda winfo::hthumbmax jmp hscroll_common .endproc .proc on_hscroll_left_click ldx #255 lda #0 ;; fall through .endproc .proc hscroll_common sta compare+1 stx delta+1 loop: lda winfo::hthumbpos compare:cmp #$0A ; self-modified bne continue rts continue: clc lda winfo::hthumbpos delta: adc #1 ; self-modified bmi overflow cmp winfo::hthumbmax beq store bcc store lda winfo::hthumbmax jmp store overflow: lda #0 store: sta winfo::hthumbpos jsr adjust_box_width jsr update_hscroll jsr draw_content jsr was_button_released bne loop rts .endproc ;;; ================================================== ;;; UI Helpers ;; Used at start of thumb drag .proc do_trackthumb lda event_params::mousex sta trackthumb_params::mousex lda event_params::mousex+1 sta trackthumb_params::mousex+1 lda event_params::mousey sta trackthumb_params::mousey MGTK_CALL MGTK::TrackThumb, trackthumb_params rts .endproc ;;; Checks button state; z clear if button was released, set otherwise .proc was_button_released MGTK_CALL MGTK::GetEvent, event_params lda event_params cmp #2 rts .endproc ;;; only used from hscroll code? .proc adjust_box_width lda winfo::hthumbpos jsr mul_by_16 clc lda $06 sta winfo::maprect::x1 adc window_width sta winfo::maprect::x2 lda $07 sta winfo::maprect::x1+1 adc window_width+1 sta winfo::maprect::x2+1 rts .endproc .proc update_voffset lda #0 sta winfo::maprect::y1 sta winfo::maprect::y1+1 ldx updatethumb_params::thumbpos loop: beq adjust_box_height clc lda winfo::maprect::y1 adc #50 sta winfo::maprect::y1 bcc :+ inc winfo::maprect::y1+1 : dex jmp loop .endproc .proc adjust_box_height clc lda winfo::maprect::y1 adc window_height sta winfo::maprect::y2 lda winfo::maprect::y1+1 adc window_height+1 sta winfo::maprect::y2+1 jsr calc_line_position lda #0 sta L096A sta L096B ldx updatethumb_params::thumbpos loop: beq end clc lda L096A adc #5 sta L096A bcc :+ inc L096B : dex jmp loop end: rts .endproc .proc update_hscroll lda #2 sta updatethumb_params::which_ctl lda winfo::maprect::x1 sta $06 lda winfo::maprect::x1+1 sta $07 jsr div_by_16 sta updatethumb_params::thumbpos MGTK_CALL MGTK::UpdateThumb, updatethumb_params rts .endproc .proc update_vscroll ; updatethumb_params::thumbpos set by caller lda #1 sta updatethumb_params::which_ctl MGTK_CALL MGTK::UpdateThumb, updatethumb_params rts .endproc .proc finish_resize ; only called from dead code DESKTOP_CALL DESKTOP_REDRAW_ICONS MGTK_CALL MGTK::SetPort, winfo::port lda winfo::hscroll ror a ; check if low bit (track enabled) is set bcc :+ jsr update_hscroll : lda winfo::vthumbpos sta updatethumb_params::thumbpos jsr update_vscroll jsr draw_content jmp input_loop .endproc .proc clear_window MGTK_CALL MGTK::SetPattern, white_pattern MGTK_CALL MGTK::PaintRect, winfo::maprect::x1 MGTK_CALL MGTK::SetPattern, black_pattern rts .endproc ;;; ================================================== ;;; Content Rendering .proc draw_content lda #0 sta L0949 jsr assign_fixed_font_width_table_if_needed jsr set_file_mark lda #default_buffer sta read_params::buffer+1 sta $07 lda #0 sta L0945 sta L0946 sta L0947 sta line_pos::base+1 sta L096C sta L096D sta L0948 lda #$0A ; line spacing = 10 sta line_pos::base jsr L0EDB do_line: lda L096D cmp L096B bne :+ lda L096C cmp L096A bne :+ jsr clear_window inc L0948 : MGTK_CALL MGTK::MoveTo, line_pos sec lda #250 sbc line_pos::left sta L095B lda #1 sbc line_pos::left+1 sta L095C jsr find_text_run bcs L0ED7 clc lda drawtext_params::textlen adc $06 sta $06 bcc :+ inc $07 : lda L095A bne do_line clc lda line_pos::base adc #$0A ; line spacing = 10 sta line_pos::base bcc :+ inc line_pos::base+1 : jsr L0EDB lda L096C cmp L0968 bne :+ lda L096D cmp L0969 beq L0ED7 : inc L096C bne :+ inc L096D : jmp do_line L0ED7: jsr restore_proportional_font_table_if_needed rts .endproc ;;; ================================================== .proc L0EDB ; ??? lda #250 sta L095B lda #1 sta L095C lda #3 sta line_pos::left lda #0 sta line_pos::left+1 sta L095A rts .endproc ;;; ================================================== .proc find_text_run lda #$FF sta L0F9B lda #0 sta run_width sta run_width+1 sta L095A sta drawtext_params::textlen lda $06 sta drawtext_params::textptr lda $07 sta drawtext_params::textptr+1 loop: lda L0945 bne more lda L0947 beq :+ jsr draw_text_run sec rts : jsr ensure_page_buffered more: ldy drawtext_params::textlen lda ($06),y and #$7F ; clear high bit sta ($06),y inc L0945 cmp #ASCII_RETURN beq finish_text_run cmp #' ' ; space character bne :+ sty L0F9B pha lda L0945 sta L0946 pla : cmp #ASCII_TAB bne :+ jmp handle_tab : tay lda font_width_table,y clc adc run_width sta run_width bcc :+ inc run_width+1 : lda L095C cmp run_width+1 bne :+ lda L095B cmp run_width : bcc :+ inc drawtext_params::textlen jmp loop : lda #0 sta L095A lda L0F9B cmp #$FF beq :+ sta drawtext_params::textlen lda L0946 sta L0945 : inc drawtext_params::textlen ;; fall through .endproc finish_text_run: jsr draw_text_run ldy drawtext_params::textlen lda ($06),y cmp #ASCII_TAB beq tab cmp #ASCII_RETURN bne :+ tab: inc drawtext_params::textlen : clc rts ;;; ================================================== L0F9B: .byte 0 run_width: .word 0 .proc handle_tab lda #1 sta L095A clc lda run_width adc line_pos::left sta line_pos::left lda run_width+1 adc line_pos::left+1 sta line_pos::left+1 ldx #0 loop: lda times70+1,x cmp line_pos::left+1 bne :+ lda times70,x cmp line_pos::left : bcs :+ inx inx cpx #14 beq done jmp loop : lda times70,x sta line_pos::left lda times70+1,x sta line_pos::left+1 jmp finish_text_run done: lda #0 sta L095A jmp finish_text_run times70:.word 70 .word 140 .word 210 .word 280 .word 350 .word 420 .word 490 .endproc ;;; ================================================== ;;; Draw a line of content .proc draw_text_run lda L0948 beq end lda drawtext_params::textlen beq end MGTK_CALL MGTK::DrawText, drawtext_params lda #1 sta L0949 end: rts .endproc ;;; ================================================== .proc ensure_page_buffered lda drawtext_params::textptr+1 cmp #>default_buffer beq read ;; copy a page of characters from $1300 to the buffer ldy #0 loop: lda $1300,y sta default_buffer,y iny bne loop dec drawtext_params::textptr+1 lda drawtext_params::textptr sta $06 lda drawtext_params::textptr+1 sta $07 read: lda #0 sta L0945 jsr read_file_page lda read_params::buffer+1 cmp #>default_buffer bne :+ inc read_params::buffer+1 : rts .endproc ;;; ================================================== .proc read_file_page lda read_params::buffer sta store+1 lda read_params::buffer+1 sta store+2 lda #' ' ; fill buffer with spaces ldx #0 sta RAMWRTOFF store: sta default_buffer,x ; self-modified inx bne store sta RAMWRTON ; read file chunk lda #$00 sta L0947 jsr read_file pha ; copy read buffer main>aux lda #$00 sta STARTLO sta DESTINATIONLO lda #$FF sta ENDLO lda read_params::buffer+1 sta DESTINATIONHI sta STARTHI sta ENDHI sec ; main>aux jsr AUXMOVE pla beq end cmp #$4C ; ??? beq done brk ; ???? done: lda #$01 sta L0947 end: rts .endproc .proc calc_window_size sec lda winfo::maprect::x2 sbc winfo::maprect::x1 sta window_width lda winfo::maprect::x2+1 sbc winfo::maprect::x1+1 sta window_width+1 sec lda winfo::maprect::y2 sbc winfo::maprect::y1 sta window_height ;; fall through .endproc ;;; ================================================== .proc calc_line_position lda winfo::maprect::y2 sta L0965 lda winfo::maprect::y2+1 sta L0966 lda #0 sta L0968 sta L0969 loop: lda L0966 bne :+ lda L0965 cmp #$0A ; line spacing = 10 bcc end : sec lda L0965 sbc #$0A ; line spacing = 10 sta L0965 bcs :+ dec L0966 : inc L0968 bne loop inc L0969 jmp loop end: rts .endproc ;;; ================================================== .proc div_by_16 ; input in $06/$07, output in a ldx #4 loop: clc ror $07 ror $06 dex bne loop lda $06 rts .endproc .proc mul_by_16 ; input in a, output in $06/$07 sta $06 lda #0 sta $07 ldx #4 loop: clc rol $06 rol $07 dex bne loop rts .endproc .proc redraw_screen lda #JUMP_TABLE_REDRAW_ALL sta call_main_addr+1 jsr call_main_trampoline rts .endproc ;;; ================================================== ;;; Restore the font glyph width table when switching ;;; back to proportional mode. .proc restore_proportional_font_table_if_needed lda fixed_mode_flag ; if not fixed (i.e. proportional) beq done ; then exit start := font_width_backup end := font_width_backup + $7E dest := font_width_table lda #start sta STARTHI sta ENDHI lda #>dest sta DESTINATIONHI lda #aux jsr AUXMOVE done: rts .endproc ;;; ================================================== ;;; Overwrite the font glyph width table (with 7s) ;;; when switching to fixed width mode. .proc assign_fixed_font_width_table_if_needed lda fixed_mode_flag ; if not fixed (i.e. proportional) beq end ; then exit ldx font_size_count lda #7 ; 7 pixels/character loop: sta font_width_table - 1,x dex bne loop end: rts .endproc ;;; ================================================== ;;; Title Bar (Proportional/Fixed mode button) .proc on_title_bar_click lda event_params::mousex+1 ; mouse x high byte? cmp mode_box_left+1 bne :+ lda event_params::mousex cmp mode_box_left : bcc ignore ;; Toggle the state and redraw lda fixed_mode_flag beq set_flag dec fixed_mode_flag ; clear flag (mode = proportional) jsr restore_proportional_font_table_if_needed jmp redraw set_flag: inc fixed_mode_flag ; set flag (mode = fixed) redraw: jsr draw_mode jsr draw_content sec ; Click consumed rts ignore: clc ; Click ignored rts .endproc fixed_str: DEFINE_STRING "Fixed " prop_str: DEFINE_STRING "Proportional" label_width := 50 title_bar_height := 12 .proc mode_box ; bounding port for mode label left: .word 0 top: .word 0 mapbits: .word MGTK::screen_mapbits mapwidth: .word MGTK::screen_mapwidth hoff: .word 0 voff: .word 0 width: .word 80 height: .word 10 .endproc mode_box_left := mode_box::left ; forward refs to mode_box::left don't work? ;; https://github.com/cc65/cc65/issues/479 .proc mode_pos left: .word 0 ; horizontal text offset base: .word 10 ; vertical text offset (to baseline) .endproc .proc calc_and_draw_mode sec lda winfo::viewloc::ycoord sbc #title_bar_height sta mode_box::top clc lda winfo::viewloc::xcoord adc window_width pha lda winfo::viewloc::xcoord+1 adc window_width+1 tax sec pla sbc #label_width sta mode_box::left+1 ;; fall through... .endproc .proc draw_mode MGTK_CALL MGTK::SetPortBits, mode_box MGTK_CALL MGTK::MoveTo, mode_pos lda fixed_mode_flag beq else ; is proportional? MGTK_CALL MGTK::DrawText, fixed_str jmp endif else: MGTK_CALL MGTK::DrawText, prop_str endif: ldx #$0F loop: lda default_port,x sta winfo::port,x dex bpl loop MGTK_CALL MGTK::SetPortBits, winfo::port rts .endproc