Latenite - 1.0.6.1 Update [Monday 20/08/2007]
- benryves
- Maxcoderz Staff
- Posts: 3089
- Joined: Thu 16 Dec, 2004 10:06 pm
- Location: Croydon, England
- Contact:
Latenite 1.0.6.1
Just overwrite the old EXE with this one.
Bug Fixes:
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).
- Useless combo box at top of source files.
- Useless "Toggle Breakpoint" option (F9).
-
- Calc King
- Posts: 1513
- Joined: Sat 05 Aug, 2006 7:22 am
I found a bug*
edit: why does tab changing change the selected index anyway?
*: 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?)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)
edit: why does tab changing change the selected index anyway?
- benryves
- Maxcoderz Staff
- Posts: 3089
- Joined: Thu 16 Dec, 2004 10:06 pm
- Location: Croydon, England
- Contact:
Cheers. I'll look into it.
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.King Harold wrote:edit: why does tab changing change the selected index anyway?
Oh, yeah, that was fun ![Smile :)](./images/smilies/grayscale_smile.gif)
![Smile :)](./images/smilies/grayscale_smile.gif)
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
http://api.timendus.com/ - Make your life easier, leave the coding to the API
http://vera.timendus.com/ - The calc lover's OS
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.
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.
- benryves
- Maxcoderz Staff
- Posts: 3089
- Joined: Thu 16 Dec, 2004 10:06 pm
- Location: Croydon, England
- Contact:
Sounds very cool to me! ![Smile :)](./images/smilies/grayscale_smile.gif)
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!)
![Smile :)](./images/smilies/grayscale_smile.gif)
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!)
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:
Structures:
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:
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.
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;
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);
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);
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.
- benryves
- Maxcoderz Staff
- Posts: 3089
- Joined: Thu 16 Dec, 2004 10:06 pm
- Location: Croydon, England
- Contact:
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.
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.
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: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](http://group.revsoft.org/wabbitemuclient.png)
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);
![Image](http://group.revsoft.org/wabbitemuclient.png)
- benryves
- Maxcoderz Staff
- Posts: 3089
- Joined: Thu 16 Dec, 2004 10:06 pm
- Location: Croydon, England
- Contact:
That seems to have done the trick, thanks. ![Smile :)](./images/smilies/grayscale_smile.gif)
Edit: Here's the current C# project, if you're intereseted -- WabbitemuFrontEnd.zip
![Smile :)](./images/smilies/grayscale_smile.gif)
Edit: Here's the current C# project, if you're intereseted -- WabbitemuFrontEnd.zip
Alright a couple updates. Here's the new functions:
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
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.It's worth noting that you could have also called with the address 0x016A. SetBreakpoint will simply clear off the bank selection bits.
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 );
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
...
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;