.setcpu "6502" .include "apple2.inc" .include "../inc/apple2.inc" .include "../inc/prodos.inc" .include "../mgtk.inc" .include "../desktop.inc" .include "../macros.inc" ;;; ============================================================ .org $800 dummy1000 := $1000 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 COPY_BYTES sizeof_call_main_template+1, call_main_template, call_main_trampoline jmp call_init .endscope .proc call_main_template sta RAMRDOFF sta RAMWRTOFF jsr dummy1000 ; 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 io_buf := $0C00 default_buffer := $1200 read_length := $0100 DEFINE_OPEN_PARAMS open_params, pathbuf, io_buf DEFINE_READ_PARAMS read_params, default_buffer, read_length DEFINE_GET_EOF_PARAMS get_eof_params DEFINE_SET_MARK_PARAMS set_mark_params, 0 DEFINE_CLOSE_PARAMS close_params pathbuf: .res 65, 0 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 line_spacing := 10 right_const := 506 L095A: .byte $00 L095B: .word right_const .proc line_pos left: .word 0 base: .word 0 .endproc window_width: .word 0 window_height: .word 0 y_remaining: .word 0 unused: .byte 0 line_count: .word 0 L096A: .word 0 L096C: .word 0 track_scroll_delta: .byte $00 fixed_mode_flag: .byte $00 ; 0 = proportional, otherwise = fixed .proc event_params kind: .byte 0 ;;; if state is MGTK::EventKind::key_down key := * modifiers := *+1 ;;; otherwise coords := * mousex := * ; spills into target query mousey := *+2 .res 4 ; space for both .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 dummy1000 ; 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: viewloc: DEFINE_POINT default_left, default_top, viewloc mapbits: .addr MGTK::screen_mapbits mapwidth: .word MGTK::screen_mapwidth maprect: 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 pathbuf lda selected_file_count beq abort ; some file properties? lda path_index ; prefix index in table bne :+ abort: rts ;; Copy path (prefix) into pathbuf. : src := $06 dst := $08 asl a ; (since address table is 2 bytes wide) tax copy16 path_table,x, src ldy #0 lda (src),y tax inc src bne :+ inc src+1 : copy16 #pathbuf+1, dst jsr copy_pathbuf ; copy x bytes (src) to (dst) ;; Append separator. lda #'/' ldy #0 sta (dst),y inc pathbuf inc dst bne :+ inc dst+1 ;; Get file entry. : lda selected_file_list ; file index in table asl a ; (since table is 2 bytes wide) tax copy16 file_table,x, src ;; 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_pathbuf ; copy x bytes (src) to (dst) ;; Clear selection (why???) copy16 #JUMP_TABLE_CLEAR_SEL, call_main_addr jsr call_main_trampoline jmp open_file_and_init_window .proc copy_pathbuf ; copy x bytes from src to dst ldy #0 ; incrementing path length and dst loop: lda (src),y sta (dst),y iny inc pathbuf 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 DEFAULT_FONT + MGTK::Font::lastchar sta RAMWRTOFF loop: lda DEFAULT_FONT + MGTK::Font::charwidth - 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 #MGTK::EventKind::key_down ; key? beq on_key_down cmp #MGTK::EventKind::button_down ; 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 ;;; ============================================================ ;;; Key .proc on_key_down : lda event_params::modifiers beq no_mod ;; Modifiers lda event_params::key cmp #CHAR_DOWN ; Apple-Down = Page Down bne :+ jsr page_down jmp input_loop : cmp #CHAR_UP ; Apple-Up = Page Up bne :+ jsr page_up jmp input_loop : cmp #CHAR_LEFT ; Apple-Left = Home bne :+ jsr scroll_top jmp input_loop : cmp #CHAR_RIGHT ; Apple-Right = End bne :+ jsr scroll_bottom : jmp input_loop ;; No modifiers no_mod: lda event_params::key cmp #CHAR_ESCAPE bne :+ jmp do_close : cmp #CHAR_DOWN bne :+ jsr scroll_down jmp input_loop : cmp #CHAR_UP bne :+ jsr scroll_up : jmp input_loop .endproc ;;; ============================================================ ;;; Close Button .proc on_close_click MGTK_CALL MGTK::TrackGoAway, trackgoaway_params lda trackgoaway_params::goaway ; did click complete? bne do_close ; yes jmp input_loop ; no .endproc .proc do_close jsr close_file MGTK_CALL MGTK::CloseWindow, winfo DESKTOP_CALL DT_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 bne enable and #(<~MGTK::Scroll::option_active) ; disable scroll jmp :+ enable: ora #MGTK::Scroll::option_active ; enable scroll : sta winfo::hscroll val := $06 sec lda #max_width sbc window_width+1 sta val+1 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: jsr page_up jsr check_button_release bcc loop ; repeat while button down end: rts .endproc .proc page_up 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 end: rts .endproc .proc on_vscroll_up_click loop: jsr scroll_up jsr check_button_release bcc loop ; repeat while button down end: rts .endproc .proc scroll_up lda winfo::vthumbpos beq end sec sbc #1 sta updatethumb_params::thumbpos jsr update_scroll_pos end: rts .endproc .proc scroll_top lda winfo::vthumbpos beq end copy #0, updatethumb_params::thumbpos jsr update_scroll_pos end: rts .endproc vscroll_max := $FA .proc on_vscroll_below_click loop: jsr page_down jsr check_button_release bcc loop ; repeat while button down end: rts .endproc .proc page_down 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 end: rts .endproc .proc on_vscroll_down_click loop: jsr scroll_down jsr check_button_release bcc loop ; repeat while button down end: rts .endproc .proc scroll_down lda winfo::vthumbpos cmp #vscroll_max beq end clc adc #1 sta updatethumb_params::thumbpos jsr update_scroll_pos end: rts .endproc .proc scroll_bottom lda winfo::vthumbpos cmp #vscroll_max beq end copy #vscroll_max, updatethumb_params::thumbpos jsr update_scroll_pos end: rts .endproc .proc update_scroll_pos ; Returns with carry set if mouse released jsr update_voffset jsr update_vscroll jsr draw_content rts .endproc .proc check_button_release jsr was_button_released clc bne end sec end: rts .endproc .proc calc_track_scroll_delta lda window_height ; ceil(height / 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 res := $06 lda trackthumb_params::thumbpos jsr mul_by_16 copy16 res, winfo::maprect::x1 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 EventKind::drag .proc do_trackthumb copy16 event_params::mousex, trackthumb_params::mousex 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 res := $06 lda winfo::hthumbpos jsr mul_by_16 clc lda res sta winfo::maprect::x1 adc window_width sta winfo::maprect::x2 lda res+1 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 L096A+1 ldx updatethumb_params::thumbpos loop: beq end clc lda L096A adc #5 sta L096A bcc :+ inc L096A+1 : dex jmp loop end: rts .endproc .proc update_hscroll lda #2 sta updatethumb_params::which_ctl val := $06 copy16 winfo::maprect::x1, val 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 DT_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 ptr := $06 lda #0 sta L0949 jsr assign_fixed_font_width_table_if_needed jsr set_file_mark lda #default_buffer sta read_params::data_buffer+1 sta ptr+1 lda #0 sta L0945 sta L0946 sta L0947 sta line_pos::base+1 sta L096C sta L096C+1 sta L0948 lda #line_spacing sta line_pos::base jsr reset_line do_line: lda L096C+1 cmp L096A+1 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 L095B+1 jsr find_text_run bcs done clc lda drawtext_params::textlen adc ptr sta ptr bcc :+ inc ptr+1 : lda L095A bne do_line clc lda line_pos::base adc #line_spacing sta line_pos::base bcc :+ inc line_pos::base+1 : jsr reset_line lda L096C cmp line_count bne :+ lda L096C+1 cmp line_count+1 beq done : inc L096C bne :+ inc L096C+1 : jmp do_line done: jsr restore_proportional_font_table_if_needed rts .endproc ;;; ============================================================ .proc reset_line copy16 #right_const, L095B copy16 #3, line_pos::left sta L095A rts .endproc ;;; ============================================================ .proc find_text_run ptr := $06 lda #$FF sta L0F9B lda #0 sta run_width sta run_width+1 sta L095A sta drawtext_params::textlen copy16 ptr, drawtext_params::textptr loop: lda L0945 bne more lda L0947 beq :+ jsr draw_text_run sec rts : jsr ensure_page_buffered more: ldy drawtext_params::textlen lda (ptr),y and #CHAR_MASK sta (ptr),y inc L0945 cmp #CHAR_RETURN beq finish_text_run cmp #' ' bne :+ sty L0F9B pha lda L0945 sta L0946 pla : cmp #CHAR_TAB bne :+ jmp handle_tab : tay lda DEFAULT_FONT + MGTK::Font::charwidth,y clc adc run_width sta run_width bcc :+ inc run_width+1 : lda L095B+1 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 .proc finish_text_run ptr := $06 jsr draw_text_run ldy drawtext_params::textlen lda (ptr),y cmp #CHAR_TAB beq tab cmp #CHAR_RETURN bne :+ tab: inc drawtext_params::textlen : clc rts .endproc ;;; ============================================================ 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 : copy16 times70,x, line_pos::left 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 ptr := $06 lda drawtext_params::textptr+1 cmp #>default_buffer beq read ;; TODO: Where does $1300 come from ??? ;; 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 copy16 drawtext_params::textptr, ptr read: lda #0 sta L0945 jsr read_file_page lda read_params::data_buffer+1 cmp #>default_buffer bne :+ inc read_params::data_buffer+1 : rts .endproc ;;; ============================================================ .proc read_file_page copy16 read_params::data_buffer, @store_addr lda #' ' ; fill buffer with spaces ldx #0 sta RAMWRTOFF @store_addr := *+1 store: sta default_buffer,x ; self-modified inx bne store sta RAMWRTON ; read file chunk lda #0 sta L0947 jsr read_file pha ; copy read buffer main>aux lda #$00 sta STARTLO sta DESTINATIONLO lda #$FF sta ENDLO lda read_params::data_buffer+1 sta DESTINATIONHI sta STARTHI sta ENDHI sec ; main>aux jsr AUXMOVE pla beq end cmp #ERR_END_OF_FILE beq done brk ; crash on other error done: lda #1 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 copy16 winfo::maprect::y2, y_remaining lda #0 sta line_count sta line_count+1 loop: lda y_remaining+1 bne :+ lda y_remaining cmp #line_spacing bcc end : sec lda y_remaining sbc #line_spacing sta y_remaining bcs :+ dec y_remaining+1 : inc line_count bne loop inc line_count+1 jmp loop end: rts .endproc ;;; ============================================================ .proc div_by_16 ; input in $06/$07, output in a val := $06 ldx #4 loop: clc ror val+1 ror val dex bne loop lda val rts .endproc .proc mul_by_16 ; input in a, output in $06/$07 res := $06 sta res lda #0 sta res+1 ldx #4 loop: clc rol res rol res+1 dex bne loop rts .endproc .proc redraw_screen copy16 #JUMP_TABLE_REDRAW_ALL, call_main_addr 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 := DEFAULT_FONT + MGTK::Font::charwidth 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 DEFAULT_FONT + MGTK::Font::lastchar lda #7 ; 7 pixels/character loop: sta DEFAULT_FONT + MGTK::Font::charwidth - 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_mapinfo_viewloc_xcoord+1 bne :+ lda event_params::mousex cmp mode_mapinfo_viewloc_xcoord : 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_mapinfo ; bounding port for mode label viewloc: DEFINE_POINT 0, 0, viewloc mapbits: .word MGTK::screen_mapbits mapwidth: .byte MGTK::screen_mapwidth reserved: .byte 0 maprect: DEFINE_RECT 0, 0, 80, 10, maprect .endproc mode_mapinfo_viewloc_xcoord := mode_mapinfo::viewloc::xcoord .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_mapinfo::viewloc::ycoord 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_mapinfo::viewloc::xcoord+1 ;; fall through... .endproc .proc draw_mode MGTK_CALL MGTK::SetPortBits, mode_mapinfo 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: COPY_STRUCT MGTK::MapInfo, default_port, winfo::port MGTK_CALL MGTK::SetPortBits, winfo::port rts .endproc