blog:pushbx:2026:0304_late_february_early_march_work_on_warplink
Late February (+ early March) work on WarpLink
2026-03-01
WarpLink
- Bugfix, read back the tempwllist structure after the innermost loop may have run, to update it with twlListUsed set to twlUsedListItem.
- Fix to preserve the ?collectfunction across the call to the innermost loop. This bug took me more than 60 minutes to properly diagnose.
- Fix repeated wllist entry crossing the boundary of a LEDATA block. The prior code assumed that the LEDATA boundary would always coincide with a tempwllist boundary, an oversight in the addition of repeated list items. The possibility of this bug occurred to me during a workday.
- Increment ecm release to r14.
- Fix a comment typo, wrote "tmpwllist" instead of "tempwllist".
- Split wllist errors into multiple error codes. Each one has a unique "problem" line while the "cause" and "solution" lines are shared across all of the wllist errors.
- Similarly, add more wlcalc errors, again with unique "problem" lines.
- Display internal error's error value as both hexadecimal and decimal. There were few errors above 9 so far, but the wlcalc and wllist internal errors I added all used decimal numbers in the sources.
- Comment on the GRP_ENT_STRUC structure, and add a label to it (ges_flags). The comments include a bug: Two instructions both write to the same field of the structure, with different contents.
- Optimise branches to wlcalc errors by chaining several jumps, so that many of them can be short.
- Allow wlcalc SEG operations to match a group name instead of a segment name.
- Make the get_grpdef and get_segdef functions more consistent in their return values.
- Hack mlerror.nas so it shows only a symbol for wlcalc errors. The problem that this was to solve was that the wrong filename would show up in the error messages, as the
filenamevariable at this point held the last object's name, not necessarily that of the object in which the wlcalc request originated. - Get the corresponding filename for wlcalc errors. This uses the file_mod_id field of the segment partiton ("spart") structure, then resets variables for and calls get_curr_obj repeatedly until the originating object filename is found.
- Undo most of the second to last changeset, so that wlcalc errors once again display a filename along with the offending symbol - now the correct filename.
- Add the twlObjIndex field to the tempwllist structure, and use it to recover the correct object filename that originated a wllist label. This re-uses .get_object_filename of the wlcalc code, adding in three push and three pop instructions to preserve the variables used by get_curr_obj. (These variables need to be preserved if the error were to be handled as a warning, to allow the remainder of pass 1 and all of pass 2 to access the correct object files.)
- Fix get_target_addr if a label isn't found, needs to pop es.
- Add the WRT clause for EXT operations. To simplify parsing, WRT is treated as an operation that comes first, followed by a segment or group name, then followed by the actual operation - which must be one of the EXT-related operations. To allow underscores in WRT segment names, an '@' sign can be used which is followed by a quote mark byte (usually a second @).
- Add a proper error code for the quote mark byte being a NUL in a WRT clause.
- Fix to copy the complete symbol name to name_field for every wlcalc error. This never does any harm, and fixes some cases that would incorrectly show a segment or extern name instead of the whole symbol name.
- After the preparation done by the prior changeset, no longer initially copy the wlcalc symbol name to the name_field. It wasn't ever used except to pass the symbol name to the error handler.
- Update protocol comments of the wlcalc get_segdef and get_grpdef functions.
- Improve protocol comments for the extern fixup wlcalc functions.
- Add a single-line update missing in the prior changeset.
- Change the extern fixup wlcalc functions to return an error code in ax (along with CY), to decouple them from the handle_wlcalc lframe context.
- Increment ecm release to r15.
- Update ecm readme with WRT clause.
- In ecm readme mention that SEG operations can also operate on group names.
- Fix the "total image size" in the .map file if the last section is empty.
- Fix the image_size variable if the last section is empty. This undoes the prior changeset. An empty section would leave the segment_stop variable equal to the segment's start, ie the total size of the image at this point. But the code expected segment_stop + 1 to yield a size, assuming that segment_stop pointed at the last byte, not past it. All users of image_size seem to assume it holds a size, not size+1, so this patch addresses the root cause of this assumption being wrong.
- Add the ITOA operation, which formats a number into text. As yet the input and output buffers are the same size, limiting the range of permissible numbers. The numeric base (assumed as 2 ⇐ base ⇐ 36) is passed in the constant given to the ITOA operation.
- Allow to enlarge the output buffer for ITOA, to up to 10 bytes. This trades off the slightly larger stack frame in handle_wlcalc (for all wlcalc operations) for the simplicity of expanding the output buffer for ITOA. Buffer size is passed in ch (ie, the second-least significant byte of the constant value).
- Add the ITOA flags for filling with zero digit text rather than blanks, and for shuffling the buffer so padding ends up at the end instead of the beginning. The shuffle operation was a little tricky to get right. First I reset bx within the innermost loop, causing it to run infinitely. Then I left the initial load of al in the innermost loop, overwriting everything with the padding. At some point I operated on the total buffer size rather than only the part populated according to ?size. Finally I had fixed the pointers but still counted down bx to the total buffer size (negative) rather than the used buffer size. I also found it difficult to track how the shuffling works, but the basic idea is sound.
- Explicitly check for ITOA bases 0 and 1, which would result in a divide exception and an unbounded loop respectively (though the overflow detection should eventually bail you out of the loop when the buffer is full of zeroes).
- Document ITOA operation in the ecm readme.
- Increment ecm release to r16, and 2026 March, in mlcredit.nas and in the ecm readme.
ETA 2026-03-04:
- Fix a fairly harmless bug: zero_mem_image would write to a final word rather than a byte if given an odd length.
- Add the /TZ switch to force use of a temporary file.
- Fix cutting the 256-byte prefix with /TZ /C switches. This error could occur in the original WarpLink revision, but only if the setup_exe_image function (in mlimage1.nas) found more than 20 KiB of free DOS memory but below what would be needed to hold the entire executable image. (Note that the progbits image size used to be limited to <= 64 KiB minus the 256 Bytes prefix.)
- Document the /TZ switch and the /TZ /C bugfix in ecm readme file.
- Rework several file write loops, and add a check of the .COM prefix contents. The check generates a warning if the /C switch is used (without /CZ), and the first 256 bytes of the image are neither all-zeroes nor all NOP instructions (value 90h bytes).
- Increment ecm release to r17.
- Add DOS error code -2 for "short read", and set it when detecting a short read in several spots. This doesn't fix all possible cases of short reads as yet. As the custom "solution" text states, a short read is likely to be an internal error of the linker.
- Add the /XCW switch, treat /XC wlcalc "unknown" errors as warnings. This is useful to enumerate multiple wlcalc errors at once, rather than having to fix them one by one to discover the next one. The wlcalc overflow errors are unaffected. This also adds an /XLW switch for wllist, though this is less useful.
- Fix to reset es after the _wlcalc_get_segdef_entry or _wlcalc_get_grpdef_entry functions. This seems to have caused some funny crashes. It now makes use of the fact that these functions leave ds => DGROUP.
- Fix: Do not zero the file_mod_id field of segpart structures. I don't know why this should be cleared here. According to the comment next to it, it was "overwriting [the] unneeded file_mod_id". I don't know whether "unneeded" means this was merely to tidy up loose ends and not really needed (I hope!) or whether there is more of a reason why this should be done. In any case, it foiled my attempt to use the segpart structure's object index to get the correct object filename for wlcalc errors. I didn't notice the failure before working on lDebug's _LINK option because the clearing would set the field to zero, which is a valid object index and would appear to point to the first object file.
- Document /XCW switch in the ecm readme file.
- Increment ecm release to r18.
- Add optional digit groups with separators to the ITOA wlcalc operation. This adds a rare use of an "inner" lframe, which re-uses the bp as set up by the outer frame (actually a non-emitting copy of the handle_wlcalc lframe here). By using lpar and lpar_return, the minimum amount of instructions (exactly 1) is used to modify sp in the function. In this case, access to the outer lframe isn't needed, but using the inner frame is still advantageous as compared to using a "nested" lframe because it uses fewer setup instructions. Also in this case, the outer frame could be used as is to add more lvar variables – but this is possible only once, whereas the inner lframe can be used for multiple functions with possibly different inner stack frames.
- Document ITOA digit groups in the ecm readme.
You could leave a comment if you were logged in.
blog/pushbx/2026/0304_late_february_early_march_work_on_warplink.txt · Last modified: by ecm
