Latenite - 1.0.6.1 Update [Monday 20/08/2007]

One suite to code them all. An complete IDE and assembler for all your z80 projects!

Moderators: benryves, kv83

Post Reply
User avatar
benryves
Maxcoderz Staff
Posts: 3080
Joined: Thu 16 Dec, 2004 10:06 pm
Location: Croydon, England
Contact:

Post by benryves »

Nothing. It was intended to be a way to jump to label declarations quickly, but it never got that far.

I really should have removed it, I suppose.
User avatar
benryves
Maxcoderz Staff
Posts: 3080
Joined: Thu 16 Dec, 2004 10:06 pm
Location: Croydon, England
Contact:

Post by benryves »

Latenite 1.0.6.1

Just overwrite the old EXE with this one.

Bug Fixes:
  • Help pane works if you click on a link (rather than go to lnh_xyz).
  • Unmanaged memory leak with help pane cleaned up (new instances of WebBrowser weren't being disposed).
  • Hidden or system files or directories are no longer displayed in the project browser (irritating if you use SVN).
Removed:
  • Useless combo box at top of source files.
  • Useless "Toggle Breakpoint" option (F9).
King Harold
Calc King
Posts: 1513
Joined: Sat 05 Aug, 2006 7:22 am

Post by King Harold »

I found a bug*
System.NullReferenceException: Object reference not set to an instance of an object.
at Latenite.LateniteIDE.HelpItemCombo_SelectedIndexChanged(Object sender, EventArgs e)
at Latenite.LateniteIDE.ProjectAndHelpTabs_SelectedIndexChanged_1(Object sender, EventArgs e)
at System.Windows.Forms.TabControl.OnSelectedIndexChanged(EventArgs e)
at System.Windows.Forms.TabControl.WmSelChange()
at System.Windows.Forms.TabControl.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
*: occurs when switching from help to project tab when the help file is incomplete/broken, but still (no offense but it should be handled, shouldn't it?)
edit: why does tab changing change the selected index anyway?
User avatar
benryves
Maxcoderz Staff
Posts: 3080
Joined: Thu 16 Dec, 2004 10:06 pm
Location: Croydon, England
Contact:

Post by benryves »

Cheers. I'll look into it.
King Harold wrote:edit: why does tab changing change the selected index anyway?
IIRC it's in an attempt to fix a bug with the ActiveX IE wrapper, where it would mysteriously undock itself from the application window and appear at (0,0) on the user's desktop. It removes and recreates the control when switching tabs.
User avatar
Timendus
Calc King
Posts: 1729
Joined: Sun 23 Jan, 2005 12:37 am
Location: Netherlands
Contact:

Post by Timendus »

Oh, yeah, that was fun :)
http://clap.timendus.com/ - The Calculator Link Alternative Protocol
http://api.timendus.com/ - Make your life easier, leave the coding to the API
http://vera.timendus.com/ - The calc lover's OS
Spencer
Extreme Poster
Posts: 346
Joined: Mon 17 Jan, 2005 8:56 am
Location: Indiana

Post by Spencer »

I thought you might be interested in an interface to wabbitemu I built into a DLL. Call calc_draw(calc, HDC) and it will draw you a color calc screen with the nice pixel filter applied. Cool! Currently you can also send it files and press keys.

Besides the obvious calc_mem_read and calc_mem_write functions an interesting question is what's the best way to communicate the state of the calc. I am thinking filling simple dummy structs with the information requested will be the best way.

This should give us an easy way to create VB or C# front ends to a C calculator core.
User avatar
benryves
Maxcoderz Staff
Posts: 3080
Joined: Thu 16 Dec, 2004 10:06 pm
Location: Croydon, England
Contact:

Post by benryves »

Sounds very cool to me! :)

How might you intend on dealing with, say, breakpoints? I suppose a callback could be triggered by the emulator, which would be handled by the front-end.

If you will indeed expose methods to retrieve and alter the emulator state, it would make sense to swap out PindurTI from the current Brass 3 debugger (which itself is very badly written - my front end, not PindurTI!)
Spencer
Extreme Poster
Posts: 346
Joined: Mon 17 Jan, 2005 8:56 am
Location: Indiana

Post by Spencer »

Alright, let's give this a try. Instead of a DLL I'm going to make it an out of process COM object that you should be able to access when Wabbitemu is open. I'll create a startup mode for Wabbitemu where it won't create a gui. It implements the IWabbitemu interface, which you can use to control the emulator and draw the screen.

The interface:

Code: Select all

	INHERITS_IUNKNOWN;
	STDMETHOD(ShowMessage)(THIS) PURE;
	STDMETHOD(GetState)(THIS_ ULONG, Z80State_t *) PURE;
	STDMETHOD(SetState)(THIS_ ULONG, Z80State_t *) PURE;
	STDMETHOD(KeyPress)(THIS_ ULONG, DWORD) PURE;
	STDMETHOD(KeyRelease)(THIS_ ULONG, DWORD) PURE;
	STDMETHOD_(BYTE, ReadMem)(THIS_ ULONG, WORD) PURE;
	STDMETHOD(WriteMem)(THIS_ ULONG, WORD, BYTE) PURE;
	STDMETHOD(DrawScreen)(THIS_ ULONG, HDC) PURE;
	STDMETHOD(SetBreakpoint)(THIS_ ULONG, WORD, BRKCALLBACK) PURE;
	STDMETHOD(ClearBreakpoint)(THIS_ ULONG, WORD) PURE;
Structures:

Code: Select all

typedef struct {
	WORD AF, BC, HL, DE, IX, IY, PC, SP;
	BYTE I, R, Bus, IFF1, IFF2;
	
	BYTE IMode;
	DOUBLE SecondsElapsed;
} Z80State_t;

typedef DWORD (*BRKCALLBACK)(WORD);
I'm not sure about the C# types you'll use, but I figured using WINAPI types would make it easy to correlate.

Here's the code I used in C to connect to this COM object:

Code: Select all

	CLSID IID_IWabbitemu, CLSID_Wabbitemu;
	
	CLSIDFromString((LPOLESTR) L"{8cc953bc-a879-492b-ad22-a2f4dfcd0e19}", &CLSID_Wabbitemu);
	CLSIDFromString((LPOLESTR) L"{13b5c004-4377-4c94-a8f9-efc1fdaeb31c}", &IID_IWabbitemu);
	
	WB_IClassFactory *pClassFactory;
	CoGetClassObject(&CLSID_Wabbitemu, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void**) &pClassFactory);
	
	WB_IWabbitemu *pWabbitemu;
	pClassFactory->icf.lpVtbl->CreateInstance(pClassFactory, NULL, &IID_IWabbitemu, (void**) &pWabbitemu);
	
	((WB_IWabbitemuVtbl *)pWabbitemu->unk.lpVtbl)->ShowMessage(pWabbitemu);
You will at least need the GUIDs to connect. So the process should be: Launch wabbitemu in silent mode, connect to the object, run commands, release the object, and close wabbitemu.

I might start up a VB project and give it a try out-of-process here pretty soon, but I wanted to give you a heads up. I'll be loitering around tcpa for a while yet tonight, as my sleeping schedule is almost entirely reversed.
User avatar
benryves
Maxcoderz Staff
Posts: 3080
Joined: Thu 16 Dec, 2004 10:06 pm
Location: Croydon, England
Contact:

Post by benryves »

Looks good. :)

Is there a build for the new version of WabbitEmu featuring the COM interface?
User avatar
benryves
Maxcoderz Staff
Posts: 3080
Joined: Thu 16 Dec, 2004 10:06 pm
Location: Croydon, England
Contact:

Post by benryves »

A couple of problems;

Attempting to DrawImage throws an AccessViolationException. I've tried passing an array to your code in a number of different ways, but can't get it to work.

Getting or setting the state seems to ignore PC and SP. All the other registers work fine.

Cheers!

PS: LayoutKind.Sequential would have worked on the Z80State_t struct had I remembered the Pack member and set it to 1.
Spencer
Extreme Poster
Posts: 346
Joined: Mon 17 Jan, 2005 8:56 am
Location: Indiana

Post by Spencer »

Good I'm glad the state stuff is working out. I fixed SP and PC, I simply had forgotten them in GetState.

Here's the code I use to draw in my client app:

Code: Select all

		BYTE screen[128*64];
		
		hdc = BeginPaint(hWnd, &ps);

		pWabbitemu->DrawScreen(0, screen);
		
		StretchDIBits(
			hdc,
			0, 0, 96*2, 64*2,
			0, 0, 96, 64,
			screen,
			bi,
			DIB_RGB_COLORS,
			SRCCOPY);

		EndPaint(hWnd, &ps);
bi is just a BITMAPINFO structure describing the palette (greenish shades from light to dark). A flat array might give you usable results. I'll put up the newer Wabbitemu and DLL either way, it might help.

Image
User avatar
benryves
Maxcoderz Staff
Posts: 3080
Joined: Thu 16 Dec, 2004 10:06 pm
Location: Croydon, England
Contact:

Post by benryves »

That seems to have done the trick, thanks. :)

Edit: Here's the current C# project, if you're intereseted -- WabbitemuFrontEnd.zip
Spencer
Extreme Poster
Posts: 346
Joined: Mon 17 Jan, 2005 8:56 am
Location: Indiana

Post by Spencer »

Haha it looks just like my client app. Let me see if I can get my breakpoint window message working.
Spencer
Extreme Poster
Posts: 346
Joined: Mon 17 Jan, 2005 8:56 am
Location: Indiana

Post by Spencer »

Alright a couple updates. Here's the new functions:

Code: Select all

typedef struct {
	char name[12];
	DWORD page, page_count;
} APPENTRY;

typedef struct {
	DWORD TypeID;
	char name[12];
	DWORD page;
	DWORD address;
} SYMENTRY;

Code: Select all

	HRESULT SetBreakpoint( [in] ULONG uSlot, [in] HWND hwndCallback, [in] BOOL IsRam, [in] BYTE Page, [in] WORD Address );
	HRESULT ClearBreakpoint( [in] ULONG uSlot, [in] BOOL IsRam, [in] BYTE Page, [in] WORD Address );
	HRESULT GetAppList( [in] ULONG uSlot, [out] APPENTRY AppList[96], [out] DWORD *Count );
	HRESULT GetSymList( [in] ULONG uSlot, [out] SYMENTRY SymList[256], [out] DWORD *Count );
I haven't implemented the actual message system for the breakpoints yet, but AppList and SymList work as you'd expect. You do have to have arrays that size, DCOM will write the whole thing.

Here's how I see it happening: You build, send to wabbitemu using another instance, get a symlist to see its address/page, set breakpoints, then use keypresses to remotely run it. You could set breakpoints dynamically to step through the source.

TypeID holds symbol types as defined in TI's include files

Code: Select all

#define RealObj         0x00
#define ListObj         0x01
#define MatObj          0x02
#define EquObj          0x03
...
Edit: You can now use SetBreakpoint to get control during a breakpoint. When wabbitemu hits a breakpoint, it sends a WM_USER (0x0400) message to the HWND you provide. If it looks like C# is using these messages in this range we can use a function called "RegisterWindowMessage" to find a unique message we both can use.

HIWORD(wParam) = IsRAM
LOWORD(wParam) = Page
HIWORD(lParam) = Current Instruction Size (yes I disassemble for you, aren't I nice)
LOWORD(lParam) = Address

After you are finished processing the breakpoint, you call ClearBreakpoint. For now any ClearBreakpoint call will resume the calculator so make sure you call all of the SetBreakpoints you want first (such as stopping it on the next command).

Here's an example in my client app for sending Zelda, setting a breakpoint at Zelda's gameloop, then pausing the calc for 5 seconds.

Code: Select all

	case WM_RBUTTONDOWN:
	{
		APPENTRY AppList[96];
		DWORD Count, i;
		
		ShellExecute(NULL, L"open", L"wabbitemu.exe", L"zelda.8xk", NULL, SW_HIDE);
		Sleep(1000);
		pWabbitemu->GetAppList(0, AppList, &Count);
		
		for (i = 0; i < Count; i++) {
			if (strncmp((const char *) AppList[i].name, "Zelda", 5) == 0) {
				pWabbitemu->SetBreakpoint(0, hWnd, FALSE, AppList[i].page, 0x416A);
			}
		}
		
		break;
	}
	case WM_USER:
		Sleep(5000);
		pWabbitemu->ClearBreakpoint(0, HIWORD(wParam), LOWORD(wParam), LOWORD(lParam));
		break;
It's worth noting that you could have also called with the address 0x016A. SetBreakpoint will simply clear off the bank selection bits.
Post Reply