Repository navigation
m68kemu.library: pattern matching, returned pointers, 8-plane screens, call trace - #1902
Closed
terminills wants to merge 73 commits into
Closed
terminills wants to merge 73 commits into
terminills wants to merge 73 commits into
Conversation
…RELOCS) On a non-68k host LoadSeg() relocates a hunk file to the addresses of its own segments and nothing can run it there; an emulator copies the segments into its own memory and needs to relocate them again. Record every 32-bit relocation the loader applies (hunk, offset, target, kind) in the seglist's segdata node, in the same allocation, and hand the table out through a new GetSegListInfo() tag. A failed allocation marks the table lost rather than handing out a partial one.
A program that opens an optional library (LZX opens arp.library) made the loader try LIBS68K:name with requesters enabled; with no such assign dos put up "Please insert volume LIBS68K" and the program waited on it forever. Turn requesters off for the three probes, as programs do.
…dArgs results Three things a 68k program needs on a 64-bit host and did not get: LoadHunks copied the segments dos had relocated to their host addresses into containment without relocating them again, so every absolute pointer pointed at host memory; a program without relocations was the only kind that ran. Apply the list dos now keeps with the seglist (GSLI_68KRELOCS), the exact inverse of what the loader did. A native BPTR is a 64-bit pointer and the thunks moved it through 32-bit registers; with memory above 4 GB a file handle lost its top half and the first Write() took dos down. Hand the m68k side an index into a per-context table instead (same native BPTR, same handle), in the generator's bptr class and the manual dos thunks; Close/UnLock/FreeArgs release the slot. ReadArgs() filled the m68k array with native pointers: strings, /N longs and /M string arrays the program could not reach. Copy them into one containment block per call and free it in FreeArgs().
…d OpenResource Each manual table's count was a literal; an added entry fell off the end and the dispatcher took the generated thunk instead. OpenResource was one of those generated thunks and returned a native resource base, a 64-bit pointer the 68k side then called through. A resource the emulator does not thunk now reads as absent, as a missing library does.
…he native version A fake base was four bytes; a program reading lib_Version through it read whatever followed. AROS's own startup compares dos.library's version with the one the program was built against and exits with RETURN_FAIL, so every AROS-built 68k command but Echo stopped after a few instructions. Lay out a full struct Library behind the jump table and copy the native library's version and revision into it.
…ed libraries The lists in the fake ExecBase are empty. SysInfo looks expansion.library up with FindName(&SysBase->LibList, ...) instead of opening it, assumes the result and calls FindConfigDev() through it, so it jumped through zero. Answer a lookup in LibList with the thunked base, setting it up on demand as OpenLibrary() does; devices and resources still read as absent.
What a classic system-friendly program needs beyond library calls, found by running SysInfo until it stopped asking for things: - the fake graphics, intuition and dos bases carry their full m68k layout synced from the native library; OpenScreen/CloseScreen keep IntuitionBase.ActiveScreen/FirstScreen and GfxBase.ActiView pointing at the program's screen (SysInfo takes &ActiveScreen->ViewPort unchecked) - the child process gets NP_Arguments, so ReadArgs on the transparent path sees the command line - Supervisor() returns with the caller's own SR; a user stack exists - the interrupt mask is lowered after reset; INTB_VERTB servers run as a level 3 autovector at 50 Hz from timer.device's E clock through a stub in low memory - CIA-A and CIA-B are modelled from the same clock (ports, timers, TOD): SysInfo times its tests with CIA-A's TOD - vectors 2-47 default to a stub that stops the program with a message; a MOVEC on a control register the core lacks (68040 TT/MMU) reads 0 and is skipped by advancing the frame's PC before it is written - PrintIText, DrawImage and DrawBorder translate their structures, byte-swapping plane words and coordinates; FindDisplayInfo hands out an opaque handle and GetDisplayInfoData copies DISP/DIMS/NAME field-wise - GetVPModeID answers INVALID_ID for an unknown ViewPort; CloseDevice on a request the emulator did not create is ignored - a program's screen opens in the Workbench's own mode and size (the VESA driver has one mode) and is painted once, since the driver pushes damaged regions only - diagnostics (per-call trace, exception trail, instruction ring, vector-table write trap) stay in the code behind ctx->trace_calls SysInfo 4.4 (Aminet util/moni) now opens its screen, draws its panel and waits for input on pc-x86_64 SMP in QEMU.
…t as a word Classic programs draw their frames and logos straight into sc_BitMap. The screen shadow had no planes, so those writes went nowhere and the panel came up as text on grey. Give the shadow real planes of the size the program asked for and, on every byte or word the CPU writes into them, recompose the touched pixels from all planes and put them on the native screen with WriteChunkyPixels(); OS drawing and plane drawing then compose the way they do on one set of bitplanes. The window RastPort's rp_BitMap points at the same planes. LoadRGB4() takes its count in D0.W; an assembler caller leaves the high word dirty, the thunk read all of it and the palette never loaded. Diagnostics come on with ENV:M68KEMU_TRACE instead of a rebuild.
…ions Gadgets: AddGList/AddGadget handed the program's m68k-layout gadget list straight to intuition. Each gadget is now copied into a native one with its Image/Border renders, IntuiText and PropInfo; a map lets RefreshGList, RemoveGList, ModifyProp, On/OffGadget find the copy and makes an IntuiMessage's IAddress name the program's own gadget. Selected state and prop pots are copied back after each message. SysInfo's buttons render as bevels and its gadget-up messages arrive with the right gadget. Heap: FreeMem() of a pointer the heap never handed out (SysInfo frees two garbage pointers while tearing down a device request it never opened) became the head of the free list, so every later allocation came from the vector table. Frees outside the heap, with a bad header, or of a block already free are now ignored. FPU: Moira implements no FPU instructions; they throw a C++ exception that never unwinds here and the emulator thread hung inside the instruction. Run the core as a 68LC040, where F-line instructions take the Line-F trap, and report a 68040 without FPU in AttnFlags. Diagnostics: M68KEMU_TRACE=msg starts the trace at the first IntuiMessage; with tracing on, a watchdog process reports the emulated CPU's position every two seconds.
… ExecBase Both read 0, and SysInfo divides its speed-test tick count by VBlankFrequency: pressing SPEED stopped it with a divide by zero. The emulator's vertical blank runs at 50 Hz; say so.
…y hunk, StackSwap m68k libraries without a native replacement belong in LIBS68K:; when that assign is not set the loader uses SYS:Libs68k/. LIBS:m68k/ and LIBS: are still searched, but only a hunk file is taken from any of them: LIBS: also holds the native libraries, which were read and rejected one by one. The heap allocates top down, so a library's later hunks sit below its first one and the Resident scan upward from the first hunk missed a RomTag kept in the data hunk (AKCC's akccplus.library). Record the span each load occupies and scan all of it. exec StackSwap() exchanges the program's stack pointer with stk_Pointer. The loader's informational lines move behind M68KEMU_TRACE.
The emulator includes the protos of log.resource, diskfont, commodities, workbench and other libraries outside the kernel set; in a fresh build tree it could be compiled before they were generated and failed on proto/log.h.
…uiet failures Libraries for 68k programs: - mathffp, mathtrans, mathieeesingbas/trans, mathieeedoubbas/trans are computed natively (FFP converted, doubles in D0/D1), with the condition codes the callers branch on (Cmp, Tst) set after the call. - workbench.library: App* registration succeeds without AppMessages yet, OpenWorkbenchObjectA runs natively. - commodities.library: CxBroker and CreateCxObj translate their m68k arguments; the generated thunks passed the program's NewBroker as is and the native broker code faulted in strcmp. - intuition menus: SetMenuStrip/ResetMenuStrip/ClearMenuStrip translate the program's Menu/MenuItem strip, ItemAddress walks the program's own strip, MENUPICK copies Flags and NextSelect back; CloseWindow drops the strip. - exec SuperState/UserState (the program already runs in supervisor mode) and StackSwap. 68k libraries from LIBS68K: run their init function (as a tail call into 68k code when OpenLibrary returns), apply their InitStruct data, and read WORD-offset function tables; AKCC's akccplus.library works now. The emulator's process gets a CLI when started from a Shell, so programs checking pr_CLI see one. A failing program is reported in one line to the system log (LogDump), not as a register and instruction dump painted over the screen by the debug console; the full dump stays behind M68KEMU_TRACE.
…maphores, window shadow Native objects the program gets back (VisualInfo, CxObj, BOOPSI objects, devices' units) are pointers that do not fit in D0: they go out as handles from the BPTR handle table and are decoded on the way in, for generated and manual thunks alike. GadTools menus: CreateMenusA builds the strip natively and hands the program an m68k mirror, with the UserData slot after each Menu/MenuItem; LayoutMenus(Items)A lay out the native strip and copy the geometry back; FreeMenus frees both; SetMenuStrip attaches the native strip of a GadTools menu instead of translating it again. GT_GetIMsg/GT_ReplyIMsg go through GetMsg's message translation, so messages are not leaked. OpenWindowTagList translates every pointer-valued WA_ tag by type (PubScreen, CustomScreen, Gadgets, Checkmark, AmigaKey, Zoom, titles) and follows TAG_MORE/TAG_SKIP; WA_PubScreen was passed as an m68k address and the window never opened. The generic tag-list conversion resolves shadows and handles first and no longer treats small values or the IDCMP/flags tags as pointers. Device I/O: an m68k IORequest gets a native twin (timerequest, IOAudio or IOStdReq) kept in step around OpenDevice, CloseDevice, DoIO, SendIO, CheckIO, WaitIO and AbortIO; io_Device is an m68k device base whose BeginIO/AbortIO and timer.device functions are thunks; GetMsg hands back the program's own request when a device replies. A reply port the program built in its own memory gets a native twin on its signal bit. Devices whose request layout is not translated fail to open instead of receiving an m68k structure. AbortIO is passed on only for a request in flight. The rest of the semaphore family matches Init/Obtain/ReleaseSemaphore (the program is one emulated task): attempts succeed, list calls do nothing, AddSemaphore/FindSemaphore/RemSemaphore keep a name table. The Window shadow gains WLayer (and the RastPort's rp_Layer) as a layer shadow with its RastPort and bounds, the border widths and the GZZ size: a program locking its window's layer called LockLayer(NULL). QEMU, Aminet batch: AmigaEyes opens its window, Ameko and 7-Zip get past their libraries and devices, AKCC and SysInfo unchanged; no 68k program takes the emulator down.
Programs report their errors through EasyRequest, and the call stopped them instead. The arguments of the text and gadget formats are one m68k datastream; it is repacked for the native call, and the IDCMP flags are copied in and out. The intuition table also had dead second entries for -432 and -438 (lookup takes the first); removed with their no-op thunks.
Every LockPubScreen built a new Screen shadow and none was ever freed, so a program that locks the screen repeatedly filled the shadow table. A structure that already has a shadow of its type now gets that one back, brought up to date. A Screen shadow from the field tables had no shadows for its embedded ViewPort and RastPort and a NULL ViewPort.ColorMap (pointer fields without a layout are written as NULL): ObtainBestPen() on it faulted in graphics.library. Both screen paths now register the ViewPort and the RastPort and give the ColorMap a shadow of the native one.
Insert, AddHead, AddTail, Remove, RemHead, RemTail, Enqueue and FindName ran the native functions on lists in m68k memory, writing 64-bit little-endian links into 32-bit big-endian nodes. They now link m68k lists in m68k layout; a list that is a shadow of a native one still goes to the native function. The choice follows the list, since a program's nodes may be shadows themselves.
OpenLibrary of a .class, .gadget or .image opens the native class library behind an m68k base: GetClass, the label node functions of chooser, clicktab, radiobutton, speedbar and listbrowser, and RethinkLayout/PAGE_GetClass of layout.gadget. NewObjectA, DisposeObject, SetAttrsA, GetAttr, SetGadgetAttrsA and DoGadgetMethodA work on native objects. The program gets an m68k stand-in for each: an _Object header whose class is an m68k IClass, and a Gadget-sized body kept in step with the native gadget. The class's dispatcher hook points at a vector of a pseudo library, so amiga.lib DoMethod() runs the method on the native object: OM_SET, OM_GET, OM_DISPOSE and the window.class methods (WM_OPEN returns the window's shadow, WM_HANDLEINPUT writes the code back). Tags whose data is a structure in the program's layout are translated: WINDOW_NewMenu, LISTBROWSER_ColumnInfo, GA_TextAttr, label string arrays, and label lists - the program links the m68k stand-ins of the nodes into its own list, and a native copy is built when the list is passed. ~0 stays ~0. Read-back values that point at native data (STRINGA_TextVal, SPACE_AreaBox) are copied into memory of the object. DrawImage draws a BOOPSI image natively. The shadow table grows to 1024 entries and the library table to 64. QEMU: the ClassAct 2 68k example binaries (string, fuelgauge, glyph, page, clicktab, speedbar, SpeedTest) open their windows on the native classes; AmiLines opens its board.
The m68k MsgPort standing in for a window's UserPort was allocated and left unfilled. A program that waits with Wait(1 << UserPort->mp_SigBit) instead of WaitPort() waited on whatever bit the memory held and never woke. The shadow now has the native port's mp_SigBit and mp_Flags, its node type and an empty message list.
InitArea and InitTmpRas ran the native functions on the program's m68k structures, writing native layouts larger than the m68k ones into its memory, and the native RastPort never saw them. Both now set up native twins of the program's structures; AreaMove, AreaDraw, AreaEnd, AreaEllipse and Flood put the twins named by the program's RastPort on the native RastPort before drawing. QEMU: AmiLines draws its balls.
The generated Screen table leaves out everything before the ViewPort but the pointers: LeftEdge, TopEdge, Width, Height, Flags, BarHeight, the menu and window border sizes, and Font was written as NULL. A program sizing its window from WBorTop and the screen font (AmigaEyes) read whatever the shadow's memory held. The screen extras now fill them, with a TextAttr shadow for the font, and new shadows start zeroed instead of with stale heap contents.
…WindowTagList FindTask built a new Process-sized shadow on every call, and programs call FindTask(NULL) in their loops: AmigaEyes filled the shadow table with them. A task's existing shadow is now brought up to date and returned. OpenWindowTagList ignored a NewWindow passed with the tags. Its fields are now applied, with the tags taking precedence as on AmigaOS; the NewWindow translation is shared with OpenWindow. OpenWindow no longer changes the window's IDCMP when calls are traced, and a traced OpenWindowTagList lists its tags and the resulting borders. The table full report gives the full shadow types.
68k programs size their windows from the border widths of AmigaOS 3, and some count on them without reading them: AmigaEyes adds no bottom border at all, which costs 2 pixels there and 10 with the AROS decoration, cutting its eyes in half. Screens now show the program the classic hires borders (WBorTop 2, WBorLeft/Right 4, WBorBottom 2), and a window the program sizes from the outside (WA_Width/WA_Height or a NewWindow, not borderless) grows by what the screen's decoration adds to them. The window keeps its real Border* fields, so drawing lands inside. With M68KEMU_CLASSICBORDERS set to 0 the real borders are shown and windows open as asked. QEMU, AmigaEyes: with the decoration it now looks as it does without one; without the decoration nothing changes.
OpenFont took its TextAttr from A1 instead of A0 and always failed, and returned the native font, which the program cannot read tf_YSize or tf_Baseline from; it now returns a TextFont shadow. diskfont.library had no OpenDiskFont; it shares the TextAttr translation. The containment heap ignored MEMF_CLEAR, so a block that had been freed came back with its old contents; AllocVec dropped its requirements and memory pools had none. Allocations now clear when asked, AllocVec passes its flags, and CreatePool keeps the pool's flags for AllocPooled (DeletePool frees the header). GetScreenData copied the native Screen into the program's m68k Screen buffer; it now copies the screen's shadow, at most the size asked for. QEMU: Wordle gets past its fonts and opens its screen (it still stops later, in its own cleanup); SysInfo, AMines, AKCC, AmiLines, AmigaEyes and the ClassAct 68k examples unchanged.
Each segment was copied without the size and next-segment BPTR that LoadSeg() puts before it. A program that walks its own seglist to jump into a later hunk (AmigaTration's start-up) read the heap's bookkeeping there and jumped to 08000004. Segments are now copied as LoadSeg() lays them out, with the links pointing at the copies.
BltBitMap handed m68k struct BitMaps to graphics.library, which read their plane pointers as native ones and faulted. Between two bitmaps in the program's memory (its own images, the planes behind its screen) the blit is now done there, plane by plane with the minterm and mask; with a native bitmap on one side the m68k one is passed as a planar BitMap over its planes. A blit into the planes behind the program's screen is shown on the screen. QEMU: AmigaTration runs and shows its blitted title, board and panel.
The program's Task shadow had tc_SPLower and tc_SPUpper as NULL (pointer fields without a layout). Startup code that moves to a bigger stack copies from tc_SPReg up to tc_SPUpper: 7-Zip's copied through all of memory for billions of instructions. The program's own task now shows the emulated stack (lower, upper, register) wherever its shadow is made or refreshed.
Tag data the native ReAction classes take in the program's layout is now translated: a plain struct Image given as LABEL_Image, GA_Image, GA_SelectRender, GA_LabelImage or a node image (SBNA_, LBNCA_, CNA_, TNA_Image) becomes a native copy kept for the run; IA_Font is a TextAttr like GA_TextAttr; LABEL_Mapping is a UWORD pen array. RADIOBUTTON_Labels and SPEEDBAR_Buttons are node lists like the other label lists, and RADIOBUTTON_LabelArray is the string array. QEMU: ClassAct 2's 68k ClassActDemo runs through all its pages (logo, credits, buttons, GadTools replacements, new gadgets, listbrowser, ASL getters) on the native classes.
When calls are traced, NewObject logs its class, tags and result, WM_OPEN lists the screen's windows and the window's gadgets with their hit test, and generated thunks show D0.
AROS reads Image plane data as big-endian words on every port. The copy of a 68k struct Image converted each word to host order, so on x86 every plain image a 68k program handed to native code was drawn with the two bytes of each word swapped: pixels 0-7 and 8-15 traded places, and images wider than 16 pixels lost the pixels pushed past their edge. The ClassAct demo's speedbar icons in its ListBrowser showed this.
ex_EClockFrequency is now the rate ReadEClock() counts at; AROS leaves the field 0 on machines without a CIA, and programs that divide by it showed a 0 Hz E clock.
NextDosEntry() and FindDosEntry() returned native DosList pointers, so a program walking the list read zeros: every entry was named ':' with no task or startup message (xSysInfo found no drives). They now return an m68k copy of each entry, made once per native entry: type, task and lock as handles, the device, volume or assign fields, BSTR names, and for a filesystem device a copy of its FileSysStartupMsg and DosEnvec. The cursor a program passes back may be such a copy or the handle LockDosList() returned. Info() let dos write the InfoData in host order, so disk sizes and states came out byte-swapped; the nine longs are now written in 68k order, the volume node as a BPTR to its DosList copy.
The TextFont shadow passed tf_CharData, tf_CharLoc, tf_CharSpace and tf_CharKern through as native pointers. A program that renders text itself reads them (xSysInfo checks a font that way before using it and refused every font, so it could not open its window). Each font's glyph bitmap, locations, spacing and kerning are now copied once into m68k memory, in 68k byte order, and the shadow points at the copies.
The heap is two regions now, as on an AGA machine: 2 MB of Chip RAM above the library bases and Fast RAM above that, each with its own MemHeader in the 68k MemList (Fast first) and its own free list. MEMF_CHIP allocations come from Chip RAM only, MEMF_FAST ones from Fast RAM only, the rest prefer Fast RAM. AvailMem() answers per region and TypeOfMem() gives the region's attributes, 0 for the ROM and for addresses outside the program's memory. Programs that check for Chip RAM before they start (or want it for images and sound) found none.
A RastPort the program keeps in its own memory (InitRastPort on its own BitMap) went to graphics as a native one. It now gets a native twin, made once and refreshed from the program's fields (BitMap, pens, draw mode, font, pen position) on every call; the BitMap may be a native one, a screen's m68k view or planes in the program's memory. InitRastPort() and InitBitMap() fill the 68k layouts instead of letting graphics write its larger native ones over the program's memory, and ClipBlit(), BltTemplate(), AllocBitMap() (friend bitmap) and GetBitMapAttr() take all of these. After SetFont(), the pen and draw mode calls, Move(), Draw() and Text(), the window's or screen's RastPort shadow carries the new state, font included with its glyphs, so programs that read rp->TxHeight or draw text themselves see it. A window's RastPort shadow starts cleared, with the screen's bitmap even when the program never asked for the screen.
The generated IntuiMessage layout leaves out the comma-declared fields, so programs that hit-test clicks themselves (xSysInfo) or check double clicks read garbage. Fill in MouseX, MouseY, Seconds and Micros.
…tions gen_offset_extractor.py read one declarator per line, so every field the NDK declares as 'WORD MouseX, MouseY;' was missing from the shadow layouts: IntuiMessage MouseX/MouseY/Seconds/Micros, AnimOb positions and velocities, GelsInfo, NewWindow, Menu, Requester, ViewPort, MonitorInfo, BitScaleArgs and others. It now splits declarator lists, and takes the header root from NDK= and a struct list from ONLY= (to probe just the structs of an existing offset dump). The 227 fields are added to the existing layouts rather than the file regenerated. Without the NDK, their m68k offsets come from AROS's own headers compiled for m68k (clang --target=m68k, -fpack-struct=2 for the Amiga's 2-byte alignment), and only from structs whose size and shared fields match the NDK-derived dump exactly; the native offsets come from the same probe built with the x86_64 AROS compiler.
More calls whose arguments point at small structures or arrays in the program's memory were handed to native code as they are: - intuition CurrentTime() wrote both longs in host order - dos StrToLong() wrote its result in host order - utility Amiga2Date(), Date2Amiga() and CheckDate() read and wrote the ClockData words in host order - graphics PolyDraw() read the coordinate array in host order, and Or/And/Xor/ClearRectRegion() the Rectangle - intuition QueryOverscan() wrote the Rectangle in host order and DrawImageState() took a plain m68k Image as a native one - exec AllocEntry() and FreeEntry() took the m68k MemList as a native one; they now allocate and free its entries in the program's heap Checked with a hand-assembled 68k test calling each of the date and number functions, AvailMem() for both regions and TypeOfMem().
m68k_offsets.txt was generated from AROS's headers, which miss fields that only the Amiga NDK declares and declare a few differently. It is now generated from the 3.2 NDK headers compiled for 68000 with 2-byte packing. All 2995 offsets and every structure size the two sources have in common agree; the NDK adds 278 fields. 26 of them are added to the shadow layouts where the native offset is known and the existing fields of the structure agree: ClipRect bounds, RastPort cp_x/cp_y, Window position, limits, borders, offsets, parent and ports, RegionRectangle, Preferences and ExtSprite fields.
rexxsyslib.library, which Directory Opus 5.91 needs: argstrings and RexxMsgs are built in the program's memory in their 68k layout (new m68kemu_rexx.c).
pr_WindowPtr written by the program reaches the native process before each library call, and is restored at the end; FindTask(NULL) returns the program's own Process (ExecBase->ThisTask), not a second copy. Directory Opus 5.91 needs both.
68k libraries can be opened by path, and are loaded once: a later OpenLibrary calls the library's Open vector, and the first runs its init and then Open, as exec does; the caller's A6 is kept. Before, only init ran, with A6 = SysBase, and every OpenLibrary loaded the library again. Directory Opus 5.91 opens its own libraries this way.
The hunk loader clears hunks (BSS read stale heap before), puts MEMF_CHIP hunks in Chip RAM, and reads HUNK_RELOC32SHORT, HUNK_DREL32, HUNK_RELRELOC32, HUNK_SYMBOL, HUNK_DEBUG and HUNK_NAME instead of stopping at the first of them. A block type it does not know now fails the load instead of ending it silently.
exec's DeletePool is LVO -702; it was registered at -720, which is AttemptSemaphoreShared. Pools now track their allocations so DeletePool frees them. The semaphore thunks' comments name their right LVOs.
FreeDosObject of an AllocDosObject FileInfoBlock frees the native one and its 68k copy. StartNotify/EndNotify use a native request bound to the program's port or task, NotifyMessages arrive in 68k layout, and notifications left running end with the program.
The utility.library tag item functions work on the program's tag lists (NextTagItem had no entry at all); CallHookPkt enters a 68k hook (new m68kemu_tags.c).
DiskObjects come in 68k layout with their tool types, default tool, drawer data and images; the program's changes go back when the icon is written; FindToolType matches the whole name as documented (new m68kemu_icon.c).
intuition: OpenScreenTagList, sharing OpenScreen's code, with the tags that carry 68k data converted; GetScreenDrawInfo in 68k layout. graphics: AskFont, with the font name as a 68k string.
MakeClass gives an m68k IClass backed by a native class whose dispatcher runs the program's hook on a second CPU (M68KEmu_Call68k); a method passed on to the superclass reaches it as the native method it came from. AddClass, RemoveClass and FreeClass work on such classes. With the commits before this one, Directory Opus 5.91 (Aminet util/dopus/Dopus5_91_os3.lha), which stopped after eight library calls, now opens its screen and loads, about 10700 calls in. Checked with hand-assembled 68k tests (tags, a 68k BOOPSI class used by name through native intuition, a hunk library with a Chip hunk and short relocations, an icon round trip) and the full regression: SysInfo, xSysInfo, the Aminet batch, the 68k ReAction set, the ClassAct demo.
The program's own return address (the end sentinel) was 0x00DEAD00, inside the program's memory. Directory Opus 5.91's heap had grown over it, and reading a word of data there ended the program. Move it to 0xFFDEAD00, outside memory, next to the sentinel used for calls from native code.
FilePart, PathPart, FGets, IDtoStr, NextPubScreen and BumpRevision give back a pointer into the program's buffer. A pointer below 4 GB passed through unchanged and named nothing; one above was handed out as a handle. Give back its address in the program's memory instead. GetCatalogStr() and GetLocaleStr() return native strings, which are now returned as copies in the program's memory, made again if the native text has changed. Directory Opus 5.91 needs these.
The program's AnchorPath is in 68k layout and went to dos as a native one. Keep a native AnchorPath behind the program's 68k one: its settings go in before each call, the match, the full path and the current directory's AChain come back after. Matches left open end with the program, so their directory locks are released. Directory Opus 5.91 needs these. Checked with hand-assembled 68k tests: pattern matching in empty and missing directories, in Directory Opus's order and with a zero current directory.
BltBitMapRastPort() and BltMaskBitMapRastPort() now take BitMaps in the program's memory; the mask is a plane there. Directory Opus 5.91 uses them.
The Workbench DrawInfo and a program's screens now report at most 8 planes, matching the 8-plane view of the display. Directory Opus 5.91, given 24, filled 24 Planes[] into an 8-plane BitMap on its stack.
IconControlA() answered the chunky image and palette tags with 0. It now returns an icon's chunky images and palettes as copies in the program's memory, made once per icon and freed with it. Directory Opus 5.91 reads them.
M68KEMU_TRACE=end keeps the last 2048 library calls and prints them when the program ends, after 10 s inside one call, and at 60 s. A fault dump shows the instructions that led to a jump into low memory. Checked with the full regression: SysInfo, xSysInfo, the Aminet batch, the 68k ReAction set, the ClassAct demo, the argument replay check.
This was referenced Oct 28, 2026
Contributor
Author
|
Squashed into one pull request as asked: #1905. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Depends on #1855-#1859, #1897, #1898, #1899, #1900, #1901 (included; review the last 7 commits).
What Directory Opus 5.91 needed after reaching its screen:
QEMU: Directory Opus 5.91 loads and waits for input; pattern-matching tests in empty and missing directories pass; regression unchanged.