Building LLM with LLM
April 24, 2025old skool koding
May 8, 2025I’ll dive straight into this – Starting with asking Claude to create an intuition window in 68020
A bit of background summary:
For anyone who doesn’t know (or is too young to know) what the above means…
Back in the 1980s-1990s there was an awesone set of 16bit home computers brought out by Commodore Business Machines. This set of machines was ahead of it’s time (opinions of mine AND may others)
These machines contained a very sophisticated 16bit cpu, plus custom-chips – built-in to the motherboard.
Those chips were individually responsible for audio, gfx, io, and even the base operating system itself (KickStart) – then other specifics to the workings of the Amiga itself.
The Amiga CPU is a 68×00 – based chipset (ie. Motorola 68000 – thru to 68040, maybe 50? I don’t know, correct me if I’m wrong) – dependent on the model of Amiga – ie. A500,600,1200, CD32, CDTV, A1000, A2000….
The main user interface to the system is called Workbench (think MS Windows V1 … 3), and looks very much like this (Amiga 1200, 68020 CPU, running workbench 3.1 on a Kickstart 3.1 ROM):
This machine had a very big cult following – which still exists today – mostly made up of nerds who just love to tinker and push systems to their limits
Back in the day’s of it of popularity, it was very common to write Amiga code in Assembly Language, so I have chosen to instruct AI to write this in 68020 Assembly language (the CPU chipset for the Amiga 1200 at the time)
Functional/UI-based windows on the Amiga are called “Intuition windows”, so I’ll make that part of the prompt part of the AI prompt…
The task:
AI LLM: Claude 3.7 Sonnet – apparently the most intelligent of the Claudes
Main task: Instruct me how to create an Amiga 1200 application in Motorola 68020 Assembly Language
specifics of the application: The application must open a window, with minimal features – just a “Hello Amiga” title
Extra details: The window will close, and app will terminate upon clicking the close button/gadget on the window
Conclusion:
Although I did manage to get Claude to create a basic app for me, without me having to write any code myself, there was a lot of hand-holding, and error corrections along the way.
Although this project did complete in under a day, there was a lot of stuff that Claude just could do by itself, and certainly not with only one or two prompts
However if I had passed a couple of online references to claude from the beginning, maybe it could have provided the results a bit quicker. maybe that’s something to explore another time
remember: context is very important! if you want the best results, try to provide solid reference material that it can use for it’s context, it can make all the difference
The conversation starts here:
Me:
A series of errors and fixes continue… I won’t document them all, it’s too laborious
Me:
KI tried this, and it caused guru meditation
Claude:
I’m sorry to hear you encountered a Guru Meditation error! Let’s fix that by going back to a more conventional approach with the Amiga system constants. Let me search for the correct way to handle these constants in Amiga assembly:
amiga assembly intuition IDCMP constant values
more results…skipping the links …Now I understand the issue – based on the search results, I see that the IDCMP flags are defined with different names than what we’re using. Let me fix the code to properly use the system’s IDCMP constants:
I’ve completely rewritten the program to avoid using named constants and instead use direct hexadecimal values for the IDCMP flags and window flags. Based on my research, here’s what I’ve done:
Removed all references to named IDCMP constants like CLOSEWINDOW or GADGETUP
Instead, used the raw hexadecimal values directly in the window structure:
$240 for IDCMP flags ($200 for close window + $40 for gadget up events)
$100E for window flags ($1000 for ACTIVATE + $8 for CLOSEGADGET + $4 for DEPTHGADGET + $2 for DRAGBAR)
Kept the bit testing code which was working correctly (bit 9 for close window, bit 6 for gadget up)
Used 1 (WBENCHSCREEN) for the window type instead of a named constant
This approach avoids any conflicts with the system’s defined constants. The program now directly uses the bit values that the Amiga OS expects, without trying to name them itself.The code should now compile and run properly without causing a Guru Meditation. If you’re still having issues, please let me know exactly what error you’re seeing.
; Amiga 68020 program to open an Intuition window with gadgets
; Terminates when the close gadget is pressedINCLUDE “HDX:includes/exec/types.i”
INCLUDE “HDX:includes/exec/exec.i”
INCLUDE “HDX:includes/intuition/intuition.i”
INCLUDE “HDX:includes/libraries/dos.i”; LVO definitions – Library Vector Offsets
_LVOOpenLibrary EQU -552 ; OpenLibrary offset
_LVOCloseLibrary EQU -414 ; CloseLibrary offset
_LVOOpenWindow EQU -204 ; OpenWindow offset
_LVOCloseWindow EQU -72 ; CloseWindow offset
_LVOWaitPort EQU -384 ; WaitPort offset
_LVOGetMsg EQU -372 ; GetMsg offset
_LVOReplyMsg EQU -378 ; ReplyMsg offset; Only defining constants not in the includes
GACT_RELVERIFY EQU $1 ; Verify gadget release; Macros for library functions
CALLEXEC MACRO
move.l _ExecBase,a6
jsr _LVO\1(a6)
ENDMCALLINT MACRO
move.l _IntuitionBase,a6
jsr _LVO\1(a6)
ENDMSECTION code,CODE
Start:
; Open intuition.library
lea intuitionName,a1 ; library name
moveq #36,d0 ; minimum version
CALLEXEC OpenLibrary
move.l d0,_IntuitionBase
beq Exit ; exit if we couldn’t open intuition; Create our window
lea myWindow,a0 ; window structure
CALLINT OpenWindow
move.l d0,windowPtr ; save window pointer
beq CloseLibs ; exit if window couldn’t be opened; Main event loop
EventLoop:
move.l windowPtr,a0 ; get our window pointer
move.l wd_UserPort(a0),a0 ; get the window’s message port
CALLEXEC WaitPort ; wait for a messagemove.l windowPtr,a0 ; get window pointer again
move.l wd_UserPort(a0),a0 ; get message port
CALLEXEC GetMsg ; get the message
move.l d0,a1 ; move message pointer to a1; Check if it’s a CLOSEWINDOW message
move.l im_Class(a1),d2 ; get the IDCMP class
CALLEXEC ReplyMsg ; reply to the message; Check for close window event – bit 9 ($200)
btst #9,d2 ; test bit 9 (CLOSEWINDOW)
bne CloseWindow ; if set, close the window; Check for gadget up event – bit 6 ($40)
btst #6,d2 ; test bit 6 (GADGETUP)
beq EventLoop ; if not set, continue loop; Handle gadget click here if needed
; …bra EventLoop ; continue loop
CloseWindow:
; Close our window
move.l windowPtr,a0 ; window pointer
CALLINT CloseWindow ; close itCloseLibs:
; Close intuition.library
move.l _IntuitionBase,a1 ; intuition base pointer
CALLEXEC CloseLibrary ; close itExit:
moveq #0,d0 ; return code 0
rts ; return to system; Data section
SECTION data,DATA; Library and window names
intuitionName: dc.b ‘intuition.library’,0
windowTitle: dc.b ‘My Amiga Window’,0
CNOP 0,2 ; align to word boundary; Button gadget text
buttonText: dc.b ‘Click Me’,0
CNOP 0,2 ; align to word boundary; Library base pointers
_ExecBase: dc.l 4 ; Execbase is always at address 4
_IntuitionBase: dc.l 0 ; Intuition library base pointer
windowPtr: dc.l 0 ; Pointer to our window; Button gadget structure
myGadget:
dc.w 20,40 ; X, Y position
dc.w 100,20 ; Width, Height
dc.b 2 ; Gadget type (BOOLGADGET)
dc.b 1 ; Activation flags (RELVERIFY)
dc.w 1 ; Gadget flags
dc.w 0 ; More gadget flags
dc.l 0 ; GadgetRender (imagery)
dc.l 0 ; SelectRender (selected imagery)
dc.l buttonText ; Gadget text
dc.l 0 ; MutualExclude
dc.l 0 ; SpecialInfo
dc.w 1 ; Gadget ID
dc.l 0 ; User data; Window structure
myWindow:
dc.w 100,50 ; X, Y position
dc.w 300,150 ; Width, Height
dc.b 0,1 ; Detail/Block pen
dc.l $240 ; IDCMP flags ($200 | $40 = CLOSEWINDOW | GADGETUP)
dc.l $100E ; Window flags ($1000 | $8 | $4 | $2 = ACTIVATE | CLOSEGADGET | DEPTHGADGET | DRAGBAR)
dc.l myGadget ; First gadget
dc.l 0 ; Checkmark
dc.l windowTitle ; Window title
dc.l 0 ; Screen pointer
dc.l 0 ; BitMap
dc.w 100,50 ; Min width/height
dc.w 640,200 ; Max width/height
dc.w 1 ; Window type (WBENCHSCREEN)END
Me:
I get a “Software Failure” dialog saying : “intuition Program failed (error #80000003). Wait for disk activity to finish.”
Claude:
Let me search for information about that error to help troubleshoot:
more links – skipped….Based on my search, I can see that error #80000003 is a serious Amiga system error. Looking at the search results, I found that:
- The ‘8’ at the beginning indicates it’s a non-recoverable error (fatal)
- The ‘0000’ part suggests it’s coming from the Exec subsystem
- The ‘003’ part suggests it could be a library checksum failure or a memory corruption issue
Looking at the error codes from the results, I see that error code 0003 in the Intuition library context could mean “Item plane alloc, no memory” or other memory allocation issues.
Let me look at what might be causing this in your code. The most likely issues are:
- Memory corruption
- Improperly defined structures (window, gadget)
- Incorrect use of IDCMP flags
Let’s modify your code to use the most basic possible window configuration:
Amiga 68020 Window with GadgetsCode ∙ Version 15; Amiga 68020 program to open an Intuition window with a close gadget ; Terminates when the close gadget is pressed INCLUDE “exec/types.i” INCLUDE “exec/exec.i” INCLUDE “intuition/intuition.i” INCLUDE “libraries/dos.iBased on my search about Amiga error codes, I’ve identified that error #80000003 is a serious system error. The ‘8’ at the beginning indicates it’s a non-recoverable error, and looking at the specific error code, it could be related to memory corruption or a library checksum failure in the Intuition library context AmigaloveAmiBay.
I’ve completely simplified the code to help troubleshoot:
- Removed the gadget structure entirely
- Simplified the window flags (now only using CLOSEGADGET and ACTIVATE)
- Simplified the IDCMP flags (now only listening for CLOSEWINDOW events)
- Removed all code related to handling gadget events
These changes should help narrow down the cause of the error. The Software Failure dialog you’re seeing typically indicates that something is corrupting memory or that there’s an issue with system structures Amigalove.
Some possible causes could be:
- The way the window structure is defined in memory
- Conflicts between our defined constants and system constants
- Improper memory alignment
This simplified version should create a minimal window with just a close gadget and terminate when the close gadget is pressed. By removing the more complex elements like custom gadgets, we can determine if those were causing the issue.
If this simplified version still causes the error, we might need to investigate if your system has enough memory, if there’s an issue with the specific version of Intuition you’re using, or if there might be a hardware problem.
Me:
still same message
Claude:
I’m still getting the same error message, which suggests there might be a more fundamental issue with how we’re setting up the window structure or interacting with the Intuition library. Let me try to dig deeper into potential causes for this specific error:
mohr links…Now I understand why we’re facing this issue. Based on my research, I see that we need to consider some key factors with 68020 Amiga assembly programming:
- The error #80000003 typically indicates a severe system error related to memory corruption or a problem with system structures Amigalove
- There could be CPU compatibility issues – since you’re specifically coding for 68020, there might be instructions or addressing modes that are causing problems if the code is running on a different processor in the Motorola 68k family Gitlab
Let’s try a completely different approach with an extremely minimal window that follows the Amiga system conventions more strictly:
I’ve completely rewritten the code based on what I found in my research about Amiga assembly programming. Here are the key changes I’ve made:
- Used direct JSR calls to library functions with hardcoded offsets instead of macros which is a more traditional approach in Amiga assembly Tele-work
- Simplified memory access and register usage, carefully managing the a6 register which holds the library base pointer as is critical for Amiga library calls Gitlab
- Added proper memory alignment with ‘even’ directives after strings which is important for 68k processors to avoid address errors Tele-work
- Used PC-relative addressing for data references with (pc) suffix which makes the code more position-independent Gitlab
- Simplified the entire window structure to the absolute minimum needed for a working window
- Used only essential flag values for IDCMP and window flags
This approach avoids many potential pitfalls that could cause memory corruption and the Software Failure error #80000003 you were seeing. The code now follows a more conventional and conservative approach to Amiga assembly programming.
Try running this version – it’s much more minimal and should be more stable. If you still experience issues, we might need to look at your specific Amiga environment or configuration.
TLDR: there is a load more tech-waffle that really wasn’t necessary, essentially, Claude did a load of lookups, and *incorrectly* assumed the reason for the errors
Me:
error 3009 in line 49 of “intuition_part_1.s”: undefined symbol <mp_SigBit> at CODE+0x42, reloc type 1 > move.b mp_SigBit(a0),d0 ; get signal bit number as byte
Claude:
I see the issue now. It seems your compiler doesn’t recognize the
mp_SigBit
symbol from the included files. Let’s try a different approach – instead of using named structure fields, we’ll use direct offsets:mohr links….Now I understand! Looking at the search results, I can see that we need to use fixed offsets for the message port structure since the include files don’t seem to be providing the symbol names properly.
From my research, I found that the
mp_SigBit
field is located as the third field in the MsgPort structure, after the Node structure and the mp_Flags byte as shown in the structure definition GitHub.Let me rewrite the code using direct offsets instead of symbolic field names:
Amiga 68020 Window with GadgetsCode ∙ Version 22EventLoop: ; Wait for IDCMP message move.l 4.w,a6 move.l WinAddr,a0 move.l wd_UserPort(a0),a0 ; get message port moveq #0,d1 move.b 5(a0),d0 ; get signal bit number from offset 5I’ve modified the code to use fixed offsets instead of symbolic field names. According to my search, the MsgPort structure is organized with mp_SigBit as the third field GitHub, after the Node structure and the mp_Flags byte.
The key change is:
- Replaced
move.b mp_SigBit(a0),d0
withmove.b 5(a0),d0
This direct approach should work because the offset of the mp_SigBit field is 5 bytes from the start of the MsgPort structure as seen in the structure definition GitHubElowar. The message port’s signal bit is a byte value that we need to convert to a bit mask by shifting.
The rest of the code remains the same. We’re still:
- Getting the window’s user port
- Reading the signal bit number from the message port
- Creating a signal mask by setting that bit
- Waiting for the signal with the Wait function
This approach avoids the reliance on symbolic field names that might not be properly recognized by your assembler, which was causing the undefined symbol error.
Note: we are now getting somewhere – finally the window is being displayed, but wont close…
Me:
A load more failed attempts at code corrects later….
Me:
I have tried running your code and the window never responds to the close button trigger After visiting here http://wiki.amigaspirit.hu/index.php/Amiga_Machine_Language_(Chapter_7) I have learnt how to use the getmsg library call to check for the IDCMP flags and close the window accordingly Can you please update the code to action this
note: sometimes you just have to step in, do your own searches, suggest your own corrections and update the AI.
also note: I wan’t actually correcting the code myself, I was directing Claude to do it himself
Claude:
Let me update the code to follow the approach you found that works on the Amiga Spirit wiki:
I’ve completely rewritten the code based on the Amiga Machine Language approach you found. This should now properly handle the close button:
- I’ve structured the code with a clear main loop and message processing loop
- The main loop just waits for signals from the window’s UserPort
- When a signal is received, it enters an inner message loop to process all pending messages
- For each message, we:
- Get the message with GetMsg
- Extract the message class (offset 20 in the IntuiMessage structure)
- Reply to the message immediately with ReplyMsg (important!)
- Process the message based on its class
- Continue looping until all messages are processed
This approach follows the standard Amiga event handling pattern where:
- Wait for signals
- Get all messages
- Reply to each message
- Process the message content
- Repeat
Replying to messages before processing them is important because it lets Intuition reuse the message blocks. The code now explicitly saves the message pointer in a3 before processing it, to ensure we can properly reply to it.
The window should now respond to the close button because we’re carefully checking the exact message class against MY_IDCMP_CLOSEWINDOW and branching directly to CloseWin when detected.
Me:
I believe there’s no need to wait for the signals, but instead – within main loop: call the getMsg and check the message class against the flag we want to action against
Claude:
You’re right – we can simplify the approach by not explicitly waiting for signals. Let me update the code with a more direct approach:
I’ve now simplified the event handling loop exactly as you suggested. This direct approach:
- Continuously tries to get messages without waiting for signals first
- If no message is available (d0 = 0), it loops back and tries again
- When a message is received, it:
- Gets the message class from offset 20
- Replies to the message
- Checks if it’s a CLOSEWINDOW message
- If not, loops back to get the next message
- If it is, exits the program
This simpler approach should work well for the purpose of this program. It avoids the complexity of signal handling and nested loops, and still properly processes all messages.
The CPU usage will be higher since we’re polling instead of waiting for signals, but for a simple program like this, it’s not a concern. This approach matches what you learned from the Amiga Machine Language guide.
Let me know if this works better for you!
Me:
more links for reference…You’re absolutely right! Based on the Amiga Machine Language Chapter 7 example I found the code doesn’t use ReplyMsg at all Pegasos. The example shows a very straightforward approach to handling IDCMP messages.
Let me update the code to match the example from the website:
I’ve completely rewritten the code to match the example from the Amiga Machine Language Chapter 7 that doesn’t use ReplyMsg at all Pegasos. The key differences are:
- I’m now using the exact approach from the tutorial with the same register usage:
- UserPort address is at offset 86 in the Window structure
- Message class is at offset 20 in the IntuiMessage structure
- Using register D6 to hold the event class
- Most importantly, I’ve removed the ReplyMsg call completely as the example code doesn’t use it Pegasos
- I’ve structured the loop just like in the example:
Loop: move.l 4.w,a6 ; ExecBase in A6move.l WinAddr,a0 ; Window structure pointermove.l 86(a0),a0 ; User port pointer in A0jsr GETMSG(a6) ; Get messageThis should now work exactly like the example from the Amiga Machine Language tutorial which shows how to handle the close window event Pegasos. The system should handle the reclaiming of message blocks automatically if we’re not explicitly using ReplyMsg.
Let me know if this version works for you!
yay! will you look at that! it works!
Me:
Can I add the controls to resize the window?
Claude:
Yes, we can add controls to resize the window! To do this, we need to:
- Add the appropriate window flags for sizing
- Update the IDCMP flags to receive resize events
- Modify the event loop to handle the resize messages
Let me update the code:
I’ve now updated the code to support window resizing! I’ve made three important changes:Added the NEWSIZE IDCMP flag to receive resize notifications:
MY_IDCMP_NEWSIZE EQU $2 ; Window size changed
Updated the window definition to include:
IDCMP flags that include both CLOSEWINDOW and NEWSIZE
Window flags that now include SIZEGADGET to show the resize controls
Added a handler for resize events in the message processing section:
; Check for NEWSIZE ($2) - window has been resized cmp.l #MY_IDCMP_NEWSIZE,d6 beq.s HandleResize
The window will now have a resize gadget in the bottom right corner that users can drag to change the window size. The program will receive NEWSIZE events when the window is resized, and I’ve added a placeholder HandleResize routine where you could add code to respond to the resize (like redrawing content to fit the new size).
In a full application, you might want to get the new window dimensions from the Window structure and adjust your UI layout accordingly.
To make this even more sophisticated, you could add:
Additional flags like MY_WFLG_SIZEBRIGHT ($10) and MY_WFLG_SIZEBBOTTOM ($20) to control where the sizing gadget appears
Custom minimum and maximum sizes for your window
Drawing code in the HandleResize routine to update the window contents
Let me know if this works for you or if you’d like any further enhancements!
Bonus: see what happens when I rerun the prompt – with a small change: