From 5fc6822af765fa317ba856bf37553b7951758228 Mon Sep 17 00:00:00 2001 From: Joshua Bell Date: Mon, 10 Feb 2025 16:07:22 -0700 Subject: [PATCH] MGTK: Add MulDiv, retire lib Since the routine is used so heavily, add `MulDiv` as a call to MGTK. While it is pure math and not even used by MGTK itself, so many files were including lib/muldiv.s that it was getting silly. This pushed MGTK past the space reserved for it ($4000...$8600) so the upper limit was bumped up by 2 pages to give more room for future growth. All clients are updated; most of them can use a dedicated param block with constants for either the number, numerator or denominator, which simplifies the call site. Some that use the routine from main memory continue to place params at $10... like lib/muldiv.s did. And some places share param blocks across calls, either because they're using the blocks at $10 or it was just not worth it to convert. Overall, this saves space... but it's hard to quantify since it moves things around a lot. For example, DeskTop still pays for the proc in aux, but no longer in main. Some param blocks move off the zero page so it's more bytes to populate each input, but can use constants so there are fewer inputs to populate. No functional changes. --- desk.acc/benchmark.s | 37 ++++++---- desk.acc/dos33.import.s | 56 ++++++++++----- desk.acc/map.s | 72 ++++++++++++------- desk.acc/neko.s | 35 ++++++---- desk.acc/show.text.file.s | 53 +++++++------- desktop/README.md | 2 +- desktop/desktop.inc | 2 +- desktop/main.s | 79 +++++++++++---------- desktop/res.s | 27 ++++++++ disk_copy/README.md | 2 +- disk_copy/auxlc.s | 30 ++++---- disk_copy/disk_copy.s | 2 +- disk_copy/main.s | 3 +- lib/muldiv.s | 115 ------------------------------- lib/option_picker.s | 40 ++++++----- mgtk/MGTK.md | 22 ++++++ mgtk/mgtk.inc | 7 ++ mgtk/mgtk.s | 141 +++++++++++++++++++++++++++++++++++++- selector/app.s | 1 - selector/ovl_file_copy.s | 18 +++-- selector/selector.s | 2 +- toolkits/lbtk.s | 43 +++++++----- 22 files changed, 476 insertions(+), 313 deletions(-) delete mode 100644 lib/muldiv.s diff --git a/desk.acc/benchmark.s b/desk.acc/benchmark.s index 641d60aa..6312f489 100644 --- a/desk.acc/benchmark.s +++ b/desk.acc/benchmark.s @@ -121,6 +121,22 @@ counter: .word 0 ; set by `ProbeSpeed` DEFINE_RECT_SZ meter_left, kMeterLeft, kMeterTop, kMeterWidth, kMeterHeight DEFINE_RECT_SZ meter_right, kMeterLeft, kMeterTop, kMeterWidth, kMeterHeight +.params ticks_muldiv_params +number: .word kMeterWidth ; (in) constant +numerator: .word 0 ; (in) populated dynamically +denominator: .word kSpeedMax ; (in) constant +result: .word 0 ; (out) +remainder: .word 0 ; (out) +.endparams + +.params progress_muldiv_params +number: .word kMeterWidth ; (in) constant +numerator: .word 0 ; (in) populated dynamically +denominator: .word 0 ; (in) populated dynamically +result: .word 0 ; (out) +remainder: .word 0 ; (out) +.endparams + pattern_left: .byte %01000100 .byte %00010001 @@ -163,12 +179,9 @@ pattern_right: lda #0 loop: pha - sta z:muldiv_numerator - copy #0, z:muldiv_numerator+1 - copy16 #kSpeedMax, z:muldiv_denominator - copy16 #kMeterWidth, z:muldiv_number - jsr MulDiv - add16 meter_left::x1, z:muldiv_result, pt_tick::xcoord + sta ticks_muldiv_params::numerator + MGTK_CALL MGTK::MulDiv, ticks_muldiv_params + add16 meter_left::x1, ticks_muldiv_params::result, pt_tick::xcoord MGTK_CALL MGTK::MoveTo, pt_tick MGTK_CALL MGTK::Line, pt_tickdelta pla @@ -338,17 +351,16 @@ done: jmp InputLoop .proc UpdateMeter jsr ProbeSpeed - copy16 counter, z:muldiv_numerator + copy16 counter, progress_muldiv_params::numerator bit radio_60hz_button::state IF_NS - copy16 #kSpeedMax * kSpeedDefault60Hz, z:muldiv_denominator + copy16 #kSpeedMax * kSpeedDefault60Hz, progress_muldiv_params::denominator ELSE - copy16 #kSpeedMax * kSpeedDefault50Hz, z:muldiv_denominator + copy16 #kSpeedMax * kSpeedDefault50Hz, progress_muldiv_params::denominator END_IF - copy16 #kMeterWidth, z:muldiv_number - jsr MulDiv - add16 meter_left::x1, z:muldiv_result, meter_left::x2 + MGTK_CALL MGTK::MulDiv, progress_muldiv_params + add16 meter_left::x1, progress_muldiv_params::result, meter_left::x2 add16 meter_left::x2, #1, meter_right::x1 MGTK_CALL MGTK::SetPenMode, pencopy @@ -502,7 +514,6 @@ loop2c: ;;; ============================================================ - .include "../lib/muldiv.s" .include "../lib/inttostring.s" .include "../lib/uppercase.s" diff --git a/desk.acc/dos33.import.s b/desk.acc/dos33.import.s index 9ca1aefd..656fbab7 100644 --- a/desk.acc/dos33.import.s +++ b/desk.acc/dos33.import.s @@ -472,6 +472,22 @@ port: .addr grafport_win DEFINE_LABEL disk_vol, res_string_disk_volume_prefix, 20, 18 +.params entry_muldiv_params +number: .word 0 ; (in) populated dynamically +numerator: .word .sizeof(CatalogEntry) ; (in) constant +denominator: .word 1 ; (in) constant +result: .word 0 ; (out) +remainder: .word 0 ; (out) +.endparams + +.params progress_muldiv_params +number: .word kProgressBarWidth ; (in) constant +numerator: .word 0 ; (in) populated dynamically +denominator: .word 0 ; (in) populated dynamically +result: .word 0 ; (out) +remainder: .word 0 ; (out) +.endparams + ;;; ============================================================ .proc Init @@ -664,12 +680,9 @@ done: rts ;; Calculate address of `CatalogEntry` ptr := $04 - sta z:muldiv_number - copy #0, z:muldiv_number+1 - copy16 #.sizeof(CatalogEntry), z:muldiv_numerator - copy16 #1, z:muldiv_denominator - jsr MulDiv - add16 z:muldiv_result, #EntryBuffer, ptr + sta entry_muldiv_params::number + MGTK_CALL MGTK::MulDiv, entry_muldiv_params + add16 entry_muldiv_params::result, #EntryBuffer, ptr kLockedX = 8 kTypeX = 20 @@ -749,11 +762,10 @@ ret: rts ;; ASSERT: Not obscured. MGTK_CALL MGTK::SetPort, grafport_win - copy16 control_block+ControlBlock::progress_num, z:muldiv_numerator - copy16 control_block+ControlBlock::progress_denom, z:muldiv_denominator - copy16 #kProgressBarWidth, z:muldiv_number - jsr MulDiv - add16 z:muldiv_result, progress_meter::x1, progress_meter::x2 + copy16 control_block+ControlBlock::progress_num, progress_muldiv_params::numerator + copy16 control_block+ControlBlock::progress_denom, progress_muldiv_params::denominator + MGTK_CALL MGTK::MulDiv, progress_muldiv_params + add16 progress_muldiv_params::result, progress_meter::x1, progress_meter::x2 MGTK_CALL MGTK::SetPattern, progress_pattern MGTK_CALL MGTK::SetPenMode, pencopy @@ -818,7 +830,6 @@ str_from_int: PASCAL_STRING "000000" ; filled in by IntToString .include "../lib/drawstring.s" .include "../lib/get_next_event.s" .include "../lib/doubleclick.s" - .include "../lib/muldiv.s" .include "../lib/inttostring.s" .assert * < EntryBuffer, error, "DA too large" @@ -1073,16 +1084,24 @@ control_block: set_eof_flag: .byte 0 tslist_offset: .byte 0 +PARAM_BLOCK muldiv_params, $10 +number .word ; (in) +numerator .word ; (in) +denominator .word ; (in) +result .word ; (out) +remainder .word ; (out) +END_PARAM_BLOCK + start: jsr FetchControlBlock ;; Fetch `CatalogEntry` - copy control_block+ControlBlock::selected_index, z:muldiv_number - copy #0, z:muldiv_number+1 - copy16 #.sizeof(aux::CatalogEntry), z:muldiv_numerator - copy16 #1, z:muldiv_denominator - jsr MulDiv - add16 z:muldiv_result, #aux::EntryBuffer, STARTLO + copy control_block+ControlBlock::selected_index, muldiv_params::number + copy #0, muldiv_params::number+1 + copy16 #.sizeof(aux::CatalogEntry), muldiv_params::numerator + copy16 #1, muldiv_params::denominator + JUMP_TABLE_MGTK_CALL MGTK::MulDiv, muldiv_params + add16 muldiv_params::result, #aux::EntryBuffer, STARTLO add16 STARTLO, #.sizeof(aux::CatalogEntry)-1, ENDLO copy16 #entry_buf, DESTINATIONLO clc ; aux>main @@ -1554,7 +1573,6 @@ RWTSWrite := RWTSImpl::Write ;;; ============================================================ .include "../lib/is_diskii.s" - .include "../lib/muldiv.s" ;;; ============================================================ diff --git a/desk.acc/map.s b/desk.acc/map.s index b2edd361..1e9b1479 100644 --- a/desk.acc/map.s +++ b/desk.acc/map.s @@ -29,6 +29,39 @@ kMapTop = 5 kMapWidth = 230 kMapHeight = 52 +.params y_to_lat +number: .word 180 ; (in) constant +numerator: .word 0 ; (in) populated dynamically +denominator: .word kMapHeight ; (in) constant +result: .word 0 ; (out) +remainder: .word 0 ; (out) +.endparams + +.params x_to_long +number: .word 360 ; (in) constant +numerator: .word 0 ; (in) populated dynamically +denominator: .word kMapWidth ; (in) constant +result: .word 0 ; (out) +remainder: .word 0 ; (out) +.endparams + +.params lat_to_y +number: .word kMapHeight ; (in) constant +numerator: .word 0 ; (in) populated dynamically +denominator: .word 180 ; (in) constant +result: .word 0 ; (out) +remainder: .word 0 ; (out) +.endparams + +.params long_to_x +number: .word kMapWidth ; (in) constant +numerator: .word 0 ; (in) populated dynamically +denominator: .word 360 ; (in) constant +result: .word 0 ; (out) +remainder: .word 0 ; (out) +.endparams + + pensize_normal: .byte 1, 1 pensize_frame: .byte 2, 1 @@ -465,22 +498,16 @@ index: .byte 0 END_IF ;; Compute new position - sub16 screentowindow_params::windowx, #kMapLeft+1, long - sub16 screentowindow_params::windowy, #kMapTop, lat ;; Map latitude to +90...-90 - copy16 lat, z:muldiv_numerator - copy16 #kMapHeight, z:muldiv_denominator - copy16 #180, z:muldiv_number - jsr MulDiv - sub16 #90, z:muldiv_result, lat + sub16 screentowindow_params::windowy, #kMapTop, y_to_lat::numerator + MGTK_CALL MGTK::MulDiv, y_to_lat + sub16 #90, y_to_lat::result, lat ;; Map longitude to -180...+180 - copy16 long, z:muldiv_numerator - copy16 #kMapWidth, z:muldiv_denominator - copy16 #360, z:muldiv_number - jsr MulDiv - sub16 z:muldiv_result, #180, long + sub16 screentowindow_params::windowx, #kMapLeft+1, x_to_long::numerator + MGTK_CALL MGTK::MulDiv, x_to_long + sub16 x_to_long::result, #180, long ;; Update display jsr SetPort @@ -680,21 +707,15 @@ blink_counter: .proc UpdateCoordsFromLatLong ;; Map latitude from +90...-90 - sub16 #90, lat, z:muldiv_numerator ; 90...-90 to 0...180 - copy16 #180, z:muldiv_denominator - copy16 #kMapHeight, z:muldiv_number - jsr MulDiv - copy16 z:muldiv_result, ycoord + sub16 #90, lat, lat_to_y::numerator ; 90...-90 to 0...180 + MGTK_CALL MGTK::MulDiv, lat_to_y + add16 lat_to_y::result, #kMapTop - (kPositionMarkerHeight/2), ycoord ;; Map longitude from -180...+180 - add16 long, #180, z:muldiv_numerator ; -180...180 to 0...360 - copy16 #360, z:muldiv_denominator - copy16 #kMapWidth, z:muldiv_number - jsr MulDiv - copy16 z:muldiv_result, xcoord - - add16 xcoord, #kMapLeft+1 - (kPositionMarkerWidth/2), xcoord - add16 ycoord, #kMapTop - (kPositionMarkerHeight/2), ycoord + add16 long, #180, long_to_x::numerator ; -180...180 to 0...360 + MGTK_CALL MGTK::MulDiv, long_to_x + add16 long_to_x::result, #kMapLeft+1 - (kPositionMarkerWidth/2), xcoord + rts .endproc ; UpdateCoordsFromLatLong @@ -702,7 +723,6 @@ blink_counter: .include "../lib/drawstring.s" .include "../lib/inttostring.s" - .include "../lib/muldiv.s" .include "../lib/get_next_event.s" ;;; ============================================================ diff --git a/desk.acc/neko.s b/desk.acc/neko.s index f7e0486c..a8569d9b 100644 --- a/desk.acc/neko.s +++ b/desk.acc/neko.s @@ -1011,14 +1011,22 @@ result: .byte 1 ;;; ============================================================ +PARAM_BLOCK muldiv_params, $10 +number .word ; (in) +numerator .word ; (in) +denominator .word ; (in) +result .word ; (out) +remainder .word ; (out) +END_PARAM_BLOCK + ;;; A,X = A,X * Y .proc Multiply_16_8_16 - stax z:muldiv_number - sty z:muldiv_numerator - copy #0, z:muldiv_numerator+1 - copy16 #1, z:muldiv_denominator - jsr MulDiv - ldax z:muldiv_result + stax muldiv_params::number + sty muldiv_params::numerator + copy #0, muldiv_params::numerator+1 + copy16 #1, muldiv_params::denominator + JUMP_TABLE_MGTK_CALL MGTK::MulDiv, muldiv_params + ldax muldiv_params::result rts .endproc ; Multiply_16_8_16 @@ -1026,20 +1034,19 @@ result: .byte 1 ;;; A,X = A,X / Y, Y = remainder .proc Divide_16_8_16 - stax z:muldiv_numerator - sty z:muldiv_denominator - copy #0, z:muldiv_denominator+1 - copy16 #1, z:muldiv_number - jsr MulDiv - ldax z:muldiv_result - ldy z:muldiv_remainder + stax muldiv_params::numerator + sty muldiv_params::denominator + copy #0, muldiv_params::denominator+1 + copy16 #1, muldiv_params::number + JUMP_TABLE_MGTK_CALL MGTK::MulDiv, muldiv_params + ldax muldiv_params::result + ldy muldiv_params::remainder rts .endproc ; Divide_16_8_16 ;;; ============================================================ .include "../lib/uppercase.s" - .include "../lib/muldiv.s" ;;; ============================================================ diff --git a/desk.acc/show.text.file.s b/desk.acc/show.text.file.s index 640985ee..05a44362 100644 --- a/desk.acc/show.text.file.s +++ b/desk.acc/show.text.file.s @@ -178,6 +178,14 @@ reserved: .byte 0 REF_MAPINFO_MEMBERS .endparams +.params muldiv_params +number: .word 0 ; (in) +numerator: .word 0 ; (in) +denominator: .word 0 ; (in) +result: .word 0 ; (out) +remainder: .word 0 ; (out) +.endparams + ;;; ============================================================ ;;; Open the file and create the DA window @@ -377,12 +385,12 @@ end: rts beq end ;; `first_visible_line` = `trackthumb_params::thumbpos` * `max_visible_line` / `kVScrollMax` - copy16 max_visible_line, z:muldiv_number - copy trackthumb_params::thumbpos, z:muldiv_numerator ; lo - copy #0, z:muldiv_numerator+1 ; hi - copy16 #kVScrollMax, z:muldiv_denominator - jsr MulDiv - copy16 z:muldiv_result, first_visible_line + copy16 max_visible_line, muldiv_params::number + copy trackthumb_params::thumbpos, muldiv_params::numerator ; lo + copy #0, muldiv_params::numerator+1 ; hi + copy16 #kVScrollMax, muldiv_params::denominator + MGTK_CALL MGTK::MulDiv, muldiv_params + copy16 muldiv_params::result, first_visible_line jsr UpdateScrollPos @@ -509,11 +517,11 @@ ForceScrollBottom := ScrollBottom::force .proc UpdateScrollPos ;; Update viewport - copy16 first_visible_line, z:muldiv_number - copy16 #kLineScrollDelta * kLineHeight, z:muldiv_numerator - copy16 #1, z:muldiv_denominator - jsr MulDiv - ldax z:muldiv_result + copy16 first_visible_line, muldiv_params::number + copy16 #kLineScrollDelta * kLineHeight, muldiv_params::numerator + copy16 #1, muldiv_params::denominator + MGTK_CALL MGTK::MulDiv, muldiv_params + ldax muldiv_params::result stax winfo::maprect::y1 addax #kDAHeight, winfo::maprect::y2 MGTK_CALL MGTK::SetPort, winfo::port @@ -521,15 +529,15 @@ ForceScrollBottom := ScrollBottom::force ;; Update thumb position ;; `updatethumb_params::thumbpos` = `first_visible_line` * `kVScrollMax` / `max_visible_line` - copy16 #kVScrollMax, z:muldiv_number - copy16 first_visible_line, z:muldiv_numerator - copy16 max_visible_line, z:muldiv_denominator - jsr MulDiv - lda z:muldiv_result+1 + copy16 #kVScrollMax, muldiv_params::number + copy16 first_visible_line, muldiv_params::numerator + copy16 max_visible_line, muldiv_params::denominator + MGTK_CALL MGTK::MulDiv, muldiv_params + lda muldiv_params::result+1 IF_NOT_ZERO lda #kVScrollMax ELSE - lda z:muldiv_result + lda muldiv_params::result END_IF sta updatethumb_params::thumbpos @@ -603,11 +611,11 @@ end: rts JSR_TO_MAIN SetFileMark ;; And adjust to the appropriate offset for that line in the viewport. - copy16 current_line, z:muldiv_number - copy16 #kLineHeight, z:muldiv_numerator - copy16 #1, z:muldiv_denominator - jsr MulDiv - copy16 z:muldiv_result, line_pos::base + copy16 current_line, muldiv_params::number + copy16 #kLineHeight, muldiv_params::numerator + copy16 #1, muldiv_params::denominator + MGTK_CALL MGTK::MulDiv, muldiv_params + copy16 muldiv_params::result, line_pos::base END_IF ;; Select appropriate font @@ -1056,7 +1064,6 @@ window_id: .byte kDAWindowId ;;; ============================================================ .include "../lib/uppercase.s" - .include "../lib/muldiv.s" ;;; ============================================================ diff --git a/desktop/README.md b/desktop/README.md index fb7320e2..f3725340 100644 --- a/desktop/README.md +++ b/desktop/README.md @@ -197,7 +197,7 @@ $BF00 +-------------+ | Utilities & | | | | | | | | | | | | Font | -$8600 | | +-------------+ +$8800 | | +-------------+ | | | MGTK | | | | | | | | | diff --git a/desktop/desktop.inc b/desktop/desktop.inc index 3cd31888..cda46a5f 100644 --- a/desktop/desktop.inc +++ b/desktop/desktop.inc @@ -27,7 +27,7 @@ DA_IO_BUFFER := $1C00 ; ...through $1FFF kDAMaxSize = DA_IO_BUFFER - DA_LOAD_ADDRESS ;;; Used by DAs for window definitions -DEFAULT_FONT := $8600 +DEFAULT_FONT := $8800 ;;; A 16k buffer that can be restored using overlays; load ;;; `kDynamicRoutineRestoreBuffer` and call `JUMP_TABLE_RESTORE_OVL` diff --git a/desktop/main.s b/desktop/main.s index 5a5017e6..76efc9a6 100644 --- a/desktop/main.s +++ b/desktop/main.s @@ -4661,6 +4661,8 @@ old .tag MGTK::Point ;;; Increment/decrement sizes (depends on view type) tick_h .byte tick_v .byte + +tmpw .word END_PARAM_BLOCK ;;; -------------------------------------------------- @@ -4780,29 +4782,28 @@ _Preamble: .proc TrackHThumb jsr _Preamble - sub16 ubox+MGTK::Rect::x2, ubox+MGTK::Rect::x1, z:muldiv_number - sub16 z:muldiv_number, width, z:muldiv_number + sub16 ubox+MGTK::Rect::x2, ubox+MGTK::Rect::x1, tmpw + sub16 tmpw, width, track_muldiv_params::number jsr _TrackMulDiv - add16 z:muldiv_result, ubox+MGTK::Rect::x1, viewport+MGTK::Rect::x1 + add16 track_muldiv_params::result, ubox+MGTK::Rect::x1, viewport+MGTK::Rect::x1 add16 viewport+MGTK::Rect::x1, width, viewport+MGTK::Rect::x2 jmp _MaybeUpdateHThumb .endproc ; TrackHThumb .proc TrackVThumb jsr _Preamble - sub16 ubox+MGTK::Rect::y2, ubox+MGTK::Rect::y1, z:muldiv_number - sub16 z:muldiv_number, height, z:muldiv_number + sub16 ubox+MGTK::Rect::y2, ubox+MGTK::Rect::y1, tmpw + sub16 tmpw, height, track_muldiv_params::number jsr _TrackMulDiv - add16 z:muldiv_result, ubox+MGTK::Rect::y1, viewport+MGTK::Rect::y1 + add16 track_muldiv_params::result, ubox+MGTK::Rect::y1, viewport+MGTK::Rect::y1 add16 viewport+MGTK::Rect::y1, height, viewport+MGTK::Rect::y2 jmp _MaybeUpdateVThumb .endproc ; TrackVThumb .proc _TrackMulDiv - copy trackthumb_params::thumbpos, z:muldiv_numerator - copy #0, z:muldiv_numerator+1 - copy16 #kScrollThumbMax, z:muldiv_denominator - jmp MulDiv + copy trackthumb_params::thumbpos, track_muldiv_params::numerator + MGTK_CALL MGTK::MulDiv, track_muldiv_params + rts .endproc ; _TrackMulDiv ;;; -------------------------------------------------- @@ -4906,24 +4907,22 @@ _Preamble: ;;; Set hthumb position relative to `maprect` and `ubox`. .proc _SetHThumbFromViewport - sub16 viewport+MGTK::Rect::x1, ubox+MGTK::Rect::x1, z:muldiv_number - copy16 #kScrollThumbMax, z:muldiv_numerator - sub16 ubox+MGTK::Rect::x2, ubox+MGTK::Rect::x1, z:muldiv_denominator - sub16 z:muldiv_denominator, width, z:muldiv_denominator - jsr MulDiv - lda z:muldiv_result + sub16 viewport+MGTK::Rect::x1, ubox+MGTK::Rect::x1, setthumb_muldiv_params::number + sub16 ubox+MGTK::Rect::x2, ubox+MGTK::Rect::x1, tmpw + sub16 tmpw, width, setthumb_muldiv_params::denominator + MGTK_CALL MGTK::MulDiv, setthumb_muldiv_params + lda setthumb_muldiv_params::result ldx #MGTK::Ctl::horizontal_scroll_bar jmp _UpdateThumb .endproc ; _SetHThumbFromViewport ;;; Set vthumb position relative to `maprect` and `ubox`. .proc _SetVThumbFromViewport - sub16 viewport+MGTK::Rect::y1, ubox+MGTK::Rect::y1, z:muldiv_number - copy16 #kScrollThumbMax, z:muldiv_numerator - sub16 ubox+MGTK::Rect::y2, ubox+MGTK::Rect::y1, z:muldiv_denominator - sub16 z:muldiv_denominator, height, z:muldiv_denominator - jsr MulDiv - lda z:muldiv_result + sub16 viewport+MGTK::Rect::y1, ubox+MGTK::Rect::y1, setthumb_muldiv_params::number + sub16 ubox+MGTK::Rect::y2, ubox+MGTK::Rect::y1, tmpw + sub16 tmpw, height, setthumb_muldiv_params::denominator + MGTK_CALL MGTK::MulDiv, setthumb_muldiv_params + lda setthumb_muldiv_params::result ldx #MGTK::Ctl::vertical_scroll_bar jmp _UpdateThumb .endproc ; _SetVThumbFromViewport @@ -11698,11 +11697,10 @@ UpdateDownloadDialogProgress := UpdateCopyDialogProgress param_call DrawString, str_2_spaces ;; Update progress bar - sub16 total_count, file_count, z:muldiv_numerator - copy16 total_count, z:muldiv_denominator - copy16 #kProgressBarWidth, z:muldiv_number - jsr MulDiv - add16 z:muldiv_result, progress_dialog_bar_meter::x1, progress_dialog_bar_meter::x2 + sub16 total_count, file_count, progress_muldiv_params::numerator + copy16 total_count, progress_muldiv_params::denominator + MGTK_CALL MGTK::MulDiv, progress_muldiv_params + add16 progress_muldiv_params::result, progress_dialog_bar_meter::x1, progress_dialog_bar_meter::x2 jsr SetPenModeCopy MGTK_CALL MGTK::SetPattern, progress_pattern MGTK_CALL MGTK::PaintRect, progress_dialog_bar_meter @@ -15093,12 +15091,20 @@ window_entry_table: .res ::kMaxIconCount+1, 0 ;;; A,X = A,X * Y .proc Multiply_16_8_16 - stax z:muldiv_number - sty z:muldiv_numerator - copy #0, z:muldiv_numerator+1 - copy16 #1, z:muldiv_denominator - jsr MulDiv - ldax z:muldiv_result +PARAM_BLOCK muldiv_params, $10 +number .word ; (in) +numerator .word ; (in) +denominator .word ; (in) +result .word ; (out) +remainder .word ; (out) +END_PARAM_BLOCK + + stax muldiv_params::number + sty muldiv_params::numerator + copy #0, muldiv_params::numerator+1 + copy16 #1, muldiv_params::denominator + MGTK_CALL MGTK::MulDiv, muldiv_params + ldax muldiv_params::result rts .endproc ; Multiply_16_8_16 @@ -15126,7 +15132,6 @@ window_entry_table: .res ::kMaxIconCount+1, 0 .include "../lib/reconnect_ram.s" .include "../lib/readwrite_settings.s" .include "../lib/get_next_event.s" - .include "../lib/muldiv.s" .include "../lib/monocolor.s" .include "../lib/speed.s" .include "../lib/bell.s" @@ -15516,12 +15521,6 @@ str_device_type_vdrive: DetectDoubleClick := main::DetectDoubleClick AdjustOnLineEntryCase := main::AdjustOnLineEntryCase AdjustFileEntryCase := main::AdjustFileEntryCase - MulDiv := main::MulDiv - muldiv_number := main::muldiv_number - muldiv_numerator := main::muldiv_numerator - muldiv_denominator := main::muldiv_denominator - muldiv_result := main::muldiv_result - muldiv_remainder := main::muldiv_remainder ;;; ============================================================ diff --git a/desktop/res.s b/desktop/res.s index cef409be..215f65df 100644 --- a/desktop/res.s +++ b/desktop/res.s @@ -299,6 +299,14 @@ progress_pattern: .byte %01000100 .byte %00010001 +.params progress_muldiv_params +number: .word kProgressBarWidth ; (in) constant +numerator: .word 0 ; (in) populated dynamically +denominator: .word 0 ; (in) populated dynamically +result: .word 0 ; (out) +remainder: .word 0 ; (out) +.endparams + ;;; ============================================================ ;;; "About Apple II DeskTop" Dialog @@ -923,6 +931,25 @@ result: .byte 0 fixed: .byte 0 .endparams +;;; ============================================================ +;;; Resources for scrollbar calculations + +.params track_muldiv_params +number: .word 0 ; (in) populated dynamically +numerator: .word 0 ; (in) populated dynamically +denominator: .word kScrollThumbMax ; (in) constant +result: .word 0 ; (out) +remainder: .word 0 ; (out) +.endparams + +.params setthumb_muldiv_params +number: .word 0 ; (in) populated dynamically +numerator: .word kScrollThumbMax ; (in) constant +denominator: .word 0 ; (in) populated dynamically +result: .word 0 ; (out) +remainder: .word 0 ; (out) +.endparams + ;;; ============================================================ active_window_id: diff --git a/disk_copy/README.md b/disk_copy/README.md index 87b25787..7d615976 100644 --- a/disk_copy/README.md +++ b/disk_copy/README.md @@ -54,7 +54,7 @@ $BF00 +-------------+ |#############| $9000 |#############| +-------------+ |#############| | | |#############| | Font | # = Copy Buffer -$8600 |#############| +-------------+ +$8800 |#############| +-------------+ |#############| | | |#############| | | |#############| | | diff --git a/disk_copy/auxlc.s b/disk_copy/auxlc.s index 2bff26e0..4f02a033 100644 --- a/disk_copy/auxlc.s +++ b/disk_copy/auxlc.s @@ -1788,31 +1788,38 @@ blocks_written: transfer_blocks: .word 0 +.params progress_muldiv_params +number: .word kProgressWidth ; (in) constant +numerator: .word 0 ; (in) populated dynamically +denominator: .word 0 ; (in) populated dynamically +result: .word 0 ; (out) +remainder: .word 0 ; (out) +.endparams + .proc DrawProgressBar MGTK_CALL MGTK::SetPenMode, notpencopy MGTK_CALL MGTK::FrameRect, progress_frame - copy16 transfer_blocks, z:muldiv_denominator + copy16 transfer_blocks, progress_muldiv_params::denominator ;; read+written will not fit in 16 bits if total is > $7FFF ;; so scale appropriately - tmp_read := muldiv_numerator - tmp_written := muldiv_number + tmp_read := progress_muldiv_params::numerator + tmp_written := progress_muldiv_params::number copy16 blocks_read, tmp_read copy16 blocks_written, tmp_written - bit z:muldiv_denominator+1 + bit progress_muldiv_params::denominator+1 IF_NC ;; Use (read + written) / total*2 - asl16 z:muldiv_denominator + asl16 progress_muldiv_params::denominator ELSE ;; Use ((read + written) / 2) / total - lsr16 z:tmp_read - lsr16 z:tmp_written + lsr16 tmp_read + lsr16 tmp_written END_IF - add16 z:tmp_read, z:tmp_written, z:muldiv_numerator + add16 tmp_read, tmp_written, progress_muldiv_params::numerator - copy16 #kProgressWidth, z:muldiv_number - jsr MulDiv - add16 progress_bar::x1, z:muldiv_result, progress_bar::x2 + MGTK_CALL MGTK::MulDiv, progress_muldiv_params + add16 progress_bar::x1, progress_muldiv_params::result, progress_bar::x2 MGTK_CALL MGTK::SetPenMode, pencopy MGTK_CALL MGTK::SetPattern, progress_pattern MGTK_CALL MGTK::PaintRect, progress_bar @@ -2365,7 +2372,6 @@ Alert := alert_dialog::Alert .endproc ; SystemTask .include "../lib/is_diskii.s" - .include "../lib/muldiv.s" .include "../lib/doubleclick.s" ;;; ============================================================ diff --git a/disk_copy/disk_copy.s b/disk_copy/disk_copy.s index e88047a0..377fbf12 100644 --- a/disk_copy/disk_copy.s +++ b/disk_copy/disk_copy.s @@ -21,7 +21,7 @@ MGTKAuxEntry := $4000 ;;; Font - left over in Aux by DeskTop -DEFAULT_FONT := $8600 +DEFAULT_FONT := $8800 ;;; ============================================================ ;;; File Structure diff --git a/disk_copy/main.s b/disk_copy/main.s index 8db1ff31..62d437b9 100644 --- a/disk_copy/main.s +++ b/disk_copy/main.s @@ -1013,7 +1013,7 @@ memory_bitmap: .byte %00000000 ; $50-$5F - MGTK code .byte %00000000 ; $60-$6F - MGTK code .byte %00000000 ; $70-$7F - MGTK code - .byte %00000011 ; $80-$8F - MGTK, font (but $8C-$8F free) + .byte %00000001 ; $80-$8F - MGTK, font (but $8E-$8F free) .byte %11111111 ; $90-$9F - free .byte %11111111 ; $A0-$AF - free .byte %11111111 ; $B0-$BF - free @@ -1026,6 +1026,7 @@ memory_bitmap: .byte %11111111 ; $D0-$DF - free kMemoryBitmapSize = * - memory_bitmap + .assert DEFAULT_FONT + 1283 < $8E00, error, "Update memory_bitmap if MGTK+font extends past $8E00" ;;; ============================================================ ;;; Inputs: A = unit num (DSSS0000), X,Y = driver address diff --git a/lib/muldiv.s b/lib/muldiv.s deleted file mode 100644 index 74a3d157..00000000 --- a/lib/muldiv.s +++ /dev/null @@ -1,115 +0,0 @@ -;;; ============================================================ -;;; Multiplies two 16-bit values and then divides the 32-bit result by -;;; a third 16-bit value, yielding a 16-bit value. -;;; Used for scaling e.g. scroll bar or progress bar position. - -;;; Callers should populate: -;;; * `z:muldiv_number`, `z:muldiv_numerator`, `z:muldiv_denominator` -;;; Result is in: -;;; * `z:muldiv_result`, `z:muldiv_remainder` - -;;; Uses $10...$19 - -.proc MulDiv - ACL := $10 ; $50 in original routines - ACH := $11 - XTNDL := $12 ; $52 in original routines - XTNDH := $13 - AUXL := $14 ; $54 in original routines - AUXH := $15 - AUX2L := $16 ; not in original routines - AUX2H := $17 - TMPL := $18 ; not in original routines - TMPH := $19 - - ;; Prepare, per "Apple II Monitors Peeled" pp.71 - - lda #0 - sta XTNDL - sta XTNDH - - ;; From MUL routine in Apple II Monitor, by Woz - ;; "Apple II Reference Manual" pp.162 - - ldy #16 ; Index for 16 bits -MUL2: lda ACL ; ACX * AUX + XTND - lsr ; to AC, XTND - bcc MUL4 ; If no carry, - clc ; no partial product. - ldx #AS_BYTE(-2) -MUL3: lda XTNDL+2,x ; Add multiplicand (AUX) - adc AUXL+2,x ; to partial product - sta XTNDL+2,x ; (XTND). - inx - bne MUL3 -MUL4: ldx #3 -MUL5: ror ACL,x - dex - bpl MUL5 - dey - bne MUL2 - - ;; Numerator: ACX,XTNDX - ;; Denominator: AUX2X - ;; Remainder: AUXX,TMPH - - lda #0 ; clear remainder - sta AUXL - sta AUXH - sta TMPL - sta TMPH - - ldy #32 ; bits remaining - -DIV2: asl ACL ; shift high bits of numerator... - rol ACH - rol XTNDL - rol XTNDH - - rol AUXL ; into remainder - rol AUXH - rol TMPL - rol TMPH - - sec ; is remainder > denominator? - - lda AUXL ; temp = remainder - denominator - sbc AUX2L - pha - lda AUXH - sbc AUX2H - pha - lda TMPL - sbc #0 - tax - lda TMPH - sbc #0 - - bcs DIV3 - - pla ; no, drop temp value - pla - - dey - bne DIV2 - rts - -DIV3: inc ACL ; yes - - sta TMPH ; remainder = temp - stx TMPL - pla - sta AUXH - pla - sta AUXL - - dey - bne DIV2 - rts -.endproc ; MulDiv - -muldiv_number := MulDiv::AUXL ; [16] -muldiv_numerator := MulDiv::ACL ; [16] -muldiv_denominator := MulDiv::AUX2L ; [16] -muldiv_result := MulDiv::ACL ; [16] -muldiv_remainder := MulDiv::AUXL ; [16] diff --git a/lib/option_picker.s b/lib/option_picker.s index 4b31ddc7..1ee4b4b6 100644 --- a/lib/option_picker.s +++ b/lib/option_picker.s @@ -8,8 +8,6 @@ ;;; * `HandleOptionPickerClick` - `screentowindow_params` must be mapped ;;; * `SetOptionPickerSelection` - A = selection ($FF to clear) ;;; -;;; Required includes: -;;; * lib/muldiv.s ;;; Requires `MGTK_CALL` macro to be functional. ;;; ;;; Required constants: @@ -27,7 +25,7 @@ ;;; Requires the following proc definitions: ;;; * `IsIndexValid` - proc, Z=1 if A is valid index, Z=0 otherwise ;;; Notes: -;;; * Routines dirty $20...$2F +;;; * Routines dirty $10...$2F ;;; ============================================================ .scope option_picker_impl @@ -95,7 +93,7 @@ ret: rts ;;; ============================================================ ;;; Get the coordinates of an option by index. -;;; Input: A = volume index +;;; Input: A = index ;;; Output: A,X = x coordinate, Y = y coordinate .proc _GetOptionPos ldx #0 ; hi @@ -331,14 +329,22 @@ loop: clc ;;; ============================================================ +PARAM_BLOCK muldiv_params, $10 +number .word ; (in) +numerator .word ; (in) +denominator .word ; (in) +result .word ; (out) +remainder .word ; (out) +END_PARAM_BLOCK + ;;; A,X = A,X * Y .proc _Multiply - stax z:muldiv_number - sty z:muldiv_numerator - copy #0, z:muldiv_numerator+1 - copy16 #1, z:muldiv_denominator - jsr MulDiv - ldax z:muldiv_result + stax muldiv_params::number + sty muldiv_params::numerator + copy #0, muldiv_params::numerator+1 + copy16 #1, muldiv_params::denominator + MGTK_CALL MGTK::MulDiv, muldiv_params + ldax muldiv_params::result rts .endproc ; _Multiply @@ -346,13 +352,13 @@ loop: clc ;;; A,X = A,X / Y, Y = remainder .proc _Divide - stax z:muldiv_numerator - sty z:muldiv_denominator - copy #0, z:muldiv_denominator+1 - copy16 #1, z:muldiv_number - jsr MulDiv - ldax z:muldiv_result - ldy z:muldiv_remainder + stax muldiv_params::numerator + sty muldiv_params::denominator + copy #0, muldiv_params::denominator+1 + copy16 #1, muldiv_params::number + MGTK_CALL MGTK::MulDiv, muldiv_params + ldax muldiv_params::result + ldy muldiv_params::remainder rts .endproc ; _Divide diff --git a/mgtk/MGTK.md b/mgtk/MGTK.md index 59e4c7e8..eaae3f65 100644 --- a/mgtk/MGTK.md +++ b/mgtk/MGTK.md @@ -1143,6 +1143,28 @@ Parameters: .addr rect2 Address of MGTK::Rect. Expanded if needed. ``` +#### MulDiv ($5A) +Multiplies two 16-bit values and then divides the 32-bit result by a +third 16-bit value, yielding a 16-bit result and a 16-bit remainder. + +Parameters: +``` +.word number (in) +.word numerator (in) +.word denominator (in) +.word result (out) +.word remainder (out) +``` + +This operation is commonly used for scaling, for example setting a +scroll bar thumb position based on the viewport offset or vice versa, +or calculating a progress bar's position. By using a denominator or +numerator of 1 this can be used for simple multiplication or division, +respectively. + +Note that if the result does not fit into 16 bits, the output is +undefined. + # Creating Applications and DeskTop Desk Accessories ### Application Use diff --git a/mgtk/mgtk.inc b/mgtk/mgtk.inc index a09902d8..0618afea 100644 --- a/mgtk/mgtk.inc +++ b/mgtk/mgtk.inc @@ -555,6 +555,13 @@ UnionRects = $59 ;;; .addr rect1 Address of MGTK::Rect ;;; .addr rect2 Address of MGTK::Rect +MulDiv = $5A +;;; .word number +;;; .word numerator +;;; .word denominator +;;; .word result +;;; .word remainder + ;;; ============================================================ ;;; Graphics Primitives Constants diff --git a/mgtk/mgtk.s b/mgtk/mgtk.s index 83c735fb..e3b75100 100644 --- a/mgtk/mgtk.s +++ b/mgtk/mgtk.s @@ -364,6 +364,7 @@ jump_table: .addr UpdateThumbImpl ; $4B UpdateThumb .addr ActivateCtlImpl ; $4C ActivateCtl + ;; ---------------------------------------- ;; Extra Calls .addr BitBltImpl ; $4D BitBlt .addr GetDeskPatImpl ; $4E GetDeskPat @@ -378,6 +379,7 @@ jump_table: .addr RestoreScreenRectImpl ; $57 RestoreScreenRect .addr InflateRectImpl ; $58 InflateRect .addr UnionRectsImpl ; $59 UnionRects + .addr MulDivImpl ; $5A MulDiv ;; Entry point param lengths ;; (length, ZP destination, hide cursor flag) @@ -505,7 +507,8 @@ param_lengths: PARAM_DEFN 8, $92, 1 ; $56 SaveScreenRect PARAM_DEFN 8, $92, 1 ; $57 RestoreScreenRect PARAM_DEFN 6, $82, 0 ; $58 InflateRect - PARAM_DEFN 4, $82, 0 ; $59 UnionRectsImpl + PARAM_DEFN 4, $82, 0 ; $59 UnionRects + PARAM_DEFN 6, $82, 0 ; $5A MulDiv ;;; ============================================================ ;;; Pre-Shift Tables @@ -10703,7 +10706,141 @@ assign: ;;; ============================================================ +.proc MulDivImpl + PARAM_BLOCK params, $82 +number .word ; (in) +numerator .word ; (in) +denominator .word ; (in) +result .word ; (out) +remainder .word ; (out) + END_PARAM_BLOCK + +AUXL := params::number ; $54 in original routines +AUXH := params::number+1 +ACL := params::numerator ; $50 in original routines +ACH := params::numerator+1 +AUX2L := params::denominator ; not in original routines +AUX2H := params::denominator+1 +XTNDL := $90 ; $52 in original routines +XTNDH := $91 +TMPL := $92 ; not in original routines +TMPH := $93 + + ;; Prepare, per "Apple II Monitors Peeled" pp.71 + + lda #0 + sta XTNDL + sta XTNDH + + ;; From MUL routine in Apple II Monitor, by Woz + ;; "Apple II Reference Manual" pp.162 + + ldy #16 ; Index for 16 bits +MUL2: lda ACL ; ACX * AUX + XTND + lsr ; to AC, XTND + bcc MUL4 ; If no carry, + clc ; no partial product. + ldx #AS_BYTE(-2) +MUL3: lda XTNDL+2,x ; Add multiplicand (AUX) + adc AUXL+2,x ; to partial product + sta XTNDL+2,x ; (XTND). + inx + bne MUL3 + +;;; Original has this which is one byte shorter but requires AC and +;;; XTND to be adjacent: +;;; +;;; MUL4: ldx #3 +;;; MUL5: ror ACL,x +;;; dex +;;; bpl MUL5 + +MUL4: ror XTNDH + ror XTNDL + ror ACH + ror ACL + + dey + bne MUL2 + + ;; Numerator: ACX,XTNDX + ;; Denominator: AUX2X + ;; Remainder: AUXX,TMPH + + lda #0 ; clear remainder + sta AUXL + sta AUXH + sta TMPL + sta TMPH + + ldy #32 ; bits remaining + +DIV2: asl ACL ; shift high bits of numerator... + rol ACH + rol XTNDL + rol XTNDH + + rol AUXL ; into remainder + rol AUXH + rol TMPL + rol TMPH + + sec ; is remainder > denominator? + + lda AUXL ; temp = remainder - denominator + sbc AUX2L + pha + lda AUXH + sbc AUX2H + pha + lda TMPL + sbc #0 + tax + lda TMPH + sbc #0 + + bcs DIV3 + + pla ; no, drop temp value + pla + jmp next + +DIV3: inc ACL ; yes + + sta TMPH ; remainder = temp + stx TMPL + pla + sta AUXH + pla + sta AUXL + +next: dey + bne DIV2 + FALL_THROUGH_TO finish + + ;; -------------------------------------------------- + ;; Update `result`/`remainder` in passed param block + +finish: + lda ACL ; result + ldy #(params::result - params) + sta (params_addr),y + iny + lda ACL+1 + sta (params_addr),y + iny + lda AUXL ; remainder + sta (params_addr),y + iny + lda AUXL+1 + sta (params_addr),y + + rts +.endproc ; MulDivImpl + +;;; ============================================================ + .endscope ; mgtk ;; Room for future expansion - PAD_TO $8600 + PAD_TO $8800 diff --git a/selector/app.s b/selector/app.s index 699be93a..29ddd4b5 100644 --- a/selector/app.s +++ b/selector/app.s @@ -1890,7 +1890,6 @@ loop_counter: .include "../lib/datetime.s" .include "../lib/doubleclick.s" .include "../lib/drawstring.s" - .include "../lib/muldiv.s" .include "../lib/speed.s" .include "../lib/bell.s" diff --git a/selector/ovl_file_copy.s b/selector/ovl_file_copy.s index 1fbd0d07..38123a00 100644 --- a/selector/ovl_file_copy.s +++ b/selector/ovl_file_copy.s @@ -980,6 +980,14 @@ progress_pattern: ;;; ============================================================ +.params progress_muldiv_params +number: .word kProgressBarWidth ; (in) constant +numerator: .word 0 ; (in) populated dynamically +denominator: .word 0 ; (in) populated dynamically +result: .word 0 ; (out) +remainder: .word 0 ; (out) +.endparams + .proc DrawWindowContent lda #winfo::kWindowId jsr app::GetWindowPort @@ -1011,11 +1019,10 @@ ep2: dec file_count param_call app::DrawString, str_from_int param_call app::DrawString, str_spaces - sub16 total_count, file_count, z:muldiv_numerator - copy16 total_count, z:muldiv_denominator - copy16 #kProgressBarWidth, z:muldiv_number - jsr MulDiv - add16 z:muldiv_result, progress_meter::x1, progress_meter::x2 + sub16 total_count, file_count, progress_muldiv_params::numerator + copy16 total_count, progress_muldiv_params::denominator + MGTK_CALL MGTK::MulDiv, progress_muldiv_params + add16 progress_muldiv_params::result, progress_meter::x1, progress_meter::x2 MGTK_CALL MGTK::SetPattern, progress_pattern MGTK_CALL MGTK::PaintRect, progress_meter @@ -1095,7 +1102,6 @@ ret: rts ;;; ============================================================ - .include "../lib/muldiv.s" ReadSetting := app::ReadSetting .include "../lib/inttostring.s" diff --git a/selector/selector.s b/selector/selector.s index 5b495a91..23a6d72c 100644 --- a/selector/selector.s +++ b/selector/selector.s @@ -48,7 +48,7 @@ basic_system_not_found = $FF INITSEG kLoaderOffset DEFSEG SegmentLoader, $2000, $0200 DEFSEG SegmentInvoker, INVOKER, $0160 - DEFSEG SegmentApp, $4000, $6900 + DEFSEG SegmentApp, $4000, $6A00 DEFSEG SegmentAlert, $D000, $0600 ;; Dynamically loaded overlays diff --git a/toolkits/lbtk.s b/toolkits/lbtk.s index 0b2292ae..36288c43 100644 --- a/toolkits/lbtk.s +++ b/toolkits/lbtk.s @@ -2,13 +2,11 @@ ;;; List Box ToolKit ;;; ============================================================ -;;; * Routines dirty $10...$19 and $50...$6F +;;; * Routines dirty $50...$6F .scope lbtk LBTKEntry := * - ;; `MulDiv` uses $10...$19 - kMaxCommandDataSize = 6 params_addr := $50 @@ -209,6 +207,14 @@ a_record .addr ;;; Output: Z=1/A=$00 on click on an item ;;; N=1/A=$FF otherwise +.params divide_params +number: .word 1 ; (in) constant +numerator: .word 0 ; (in) populated dynamically +denominator: .word kListItemHeight ; (in) constant +result: .word 0 ; (out) +remainder: .word 0 ; (out) +.endparams + .proc ClickImpl PARAM_BLOCK params, lbtk::command_data a_record .addr @@ -235,11 +241,9 @@ coords .tag MGTK::Point ldy #MGTK::Winfo::port+MGTK::GrafPort::maprect+MGTK::Rect::y1 add16in (winfo_ptr),y, screentowindow_params::windowy, screentowindow_params::windowy - copy16 screentowindow_params::windowy, z:muldiv_numerator - copy16 #kListItemHeight, z:muldiv_denominator - copy16 #1, z:muldiv_number - jsr MulDiv - lda z:muldiv_result + copy16 screentowindow_params::windowy, divide_params::numerator + MGTK_CALL MGTK::MulDiv, divide_params + lda divide_params::result ;; Validate cmp lbr_copy + LBTK::ListBoxRecord::num_items @@ -765,22 +769,23 @@ rows: .byte 0 ;;; ============================================================ +.params multiply_params +number: .word 0 ; (in) populated dynamically +numerator: .word 0 ; (in) populated dynamically +denominator: .word 1 ; (in) constant +result: .word 0 ; (out) +remainder: .word 0 ; (out) +.endparams + ;;; A,X = A,X * Y .proc _Multiply - stax z:muldiv_number - sty z:muldiv_numerator - ldy #0 - sty z:muldiv_numerator+1 - sty z:muldiv_denominator+1 - iny - sty z:muldiv_denominator - jsr MulDiv - ldax z:muldiv_result + stax multiply_params::number + sty multiply_params::numerator ; high byte remains 0 + MGTK_CALL MGTK::MulDiv, multiply_params + ldax multiply_params::result rts .endproc ; _Multiply - .include "../lib/muldiv.s" - ;;; ============================================================ .endscope ; lbtk