Hacker News new | past | comments | ask | show | jobs | submit login
Show HN: WinGPT – AI assistant for Windows 3.1 (dialup.net)
382 points by dialupdotnet on June 25, 2023 | hide | past | favorite | 90 comments
Hey HN, I didn't want my Gateway 4DX2-66 from 1993 to be left out of the AI revolution, so I built an AI Assistant for Windows 3.1, based on the OpenAI API.

The most interesting parts of building this were:

- Getting TLS 1.2 and 1.3 working on Windows 3.1 so that WinGPT could directly connect to OpenAI's server without relying on a modern machine for TLS termination.

- Learning about the memory segmentation architecture on 16-bit Windows, including the difference between far and near pointers.

- Building the UI in plain C code with the Windows API and limited selection of controls in Windows 3.1.

You can check it out here and learn more about what it was like to build it: https://www.dialup.net/wingpt/




Maybe you could incorporate it into a version of ms office from that era as well. You could even give it an anthropomorphised personality embodied by a skeuomorphic element of irl office supplies more common in that era, like a rubber band… or… a… paperclip…


Good idea :) Clippy is Office 97 and later though, so I'll need to make a version that fits in with the Windows 95/98 (or even Windows Me) look!


MS Agent would be a perfect fit for that. It's basically Clippy as a Windows API. It even includes speech synthesis.

IIRC it ships with Windows 2000, but works on Windows 95 too.


Maybe Bob would be a good fit too. https://en.m.wikipedia.org/wiki/Microsoft_Bob


Bob looks an awful lot like Bill Gates.


Melinda Gates was marketing manager, so maybe it was intentional.


Full circle AI from paperclip to paperclip maximizer!


Getting TLS 1.2 and 1.3 working on Windows 3.1 so that WinGPT could directly connect to OpenAI's server without relying on a modern machine for TLS termination.

That's in a separate page here: https://www.dialup.net/wingpt/tls.html

...and is well worth reading. I'm surprised you had trouble getting a TLS implementation to fit in 64k of code and data, since a lot of deeply-embedded stuff (some even using 8-bit CPUs with bankswitching) for IoT and similar applications support TLS 1.2.


So glad to see someone working on TLS 1.3 for Windows 3.1.

It's a sad day when slightly older operating systems have trouble accessing the internet.


Maybe some of those chips have some hardware support for crypto?


Really miss Windows 3.1, 95 and 98 era. Interfaces have only gone worse since then. Every time I crank up my 386 or Pentium I am completely blown away by how clean and stress-free the GUI was. Really tired of this Apple/Google low-contrast pop-up hell.


The Windows Interface Guidelines from 1995 is an interesting read: https://www.ics.uci.edu/~kobsa/courses/ICS104/course-notes/M...


This is an amazing reference, thanks.


Remember how you could actually RESIZE things in that era? Sidebars, toolbars, etc.?

Now half of my UIs have "Tap to...." labels when localized. So many amazing modern UI tools and the rockstar developers wielding them can't even make a draggable sidebar.


One man's rockstar developer is another man's script kiddie.

I do, however have considerably more time for script kiddies.


Good luck resizing a typical modal window though. Also good luck with high-DPI...

Even resizing regular windows was not always an option, and if it was, it was very rarely thought through by the developers. I vividly remember that the Swing framework for Java was very special just because of this, as in you couldn't really specify it in pixels where your components would be placed, you'd have all sorts of strategies to divide and position them. (Not saying it was any good, but certainly a notable effort.)


This was grey-downvoted, but it's correct: Win16/32 MessageBox() modals are not resizeable.

Not only that, but window resizing was something that had to be implemented for each window, so lots of applications had unresizeable dialogs and only the "document" area was resizeable.

Even worse, the use of pixel positioning meant that nothing was scaleable. High-DPI display? Choose (a) not being able to read anything or (b) bad linear rescale by a limited number of scales.

I too am a fan of the simplicity and clarity of the old Windows UI, and Microsoft haven't really managed to improve on it, but let's not pretend it doesn't have serious limitations.


Why do you people think that nerdsplaining a few corner cases somehow refutes a change in general situation?

Yes, I remember modals not being resizable, I was there. That was not the point.


> Memory is quite limited on Windows 3.1 machines, so I tried to reduce the amount of memory needed for WinGPT, especially in sending and receiving the query and response from the OpenAI API. The JSON responses of modern APIs aren't especially optimized for size, and OpenAI's API is no exception. I've asked the model to be brief in an effort to keep responses as small as possible. I've also chosen not to send the text of previous turns in the API calls, even though this means that the bot won't be able to use prior conversation context.

You can trade space for CPU time using SAX-style parsing[1]. SAX-style parsing visits each node of a tree from top to bottom, firing events for each node visited. The amount of memory required compared to fully parsing JSON is negligible, and writing a custom SAX-style parser for JSON shouldn't be too difficult. There are existing SAX-style JSON parsers you can examine as well.[2]

[1]: https://en.wikipedia.org/wiki/Simple_API_for_XML [2]: https://rapidjson.org/md_doc_sax.html


Yep! I'm using JSMN (https://github.com/zserge/jsmn), which is a streaming parser that visits each token sequentially, so there's only one copy of each JSON response in memory. I also avoid allocating new intermediate memory whenever possible; for example, to unescape backslashes in the JSON strings, I use a destructive loop that moves the non-backslash characters forward in memory, and truncates the string by moving the null terminator earlier in the string. Not something I'd imagine doing in most environments today, but as you said, it saves a bit of space at the expense of CPU time :)

  void DestructivelyUnescapeStr(LPSTR lpInput) {
    int offset = 0;
    int i = 0;
    while (lpInput[i] != '\0') {
      if (lpInput[i] == '\\') {
        offset++;
      } else {
        lpInput[i - offset] = lpInput[i];
      }
      i++;
    }
    lpInput[i - offset] = '\0';
  }


Strong odds the supporting infrastructure for the textbox control I am typing this into consumes more system resources than WinGPT does in its entirety.

Goes to show that we waste literal orders of magnitudes of memory for small gains in developer productivity. Is programming raw Windows controls hard? Sure. But Delphi or VB on Win95 was arguably (much) more productive than modern day UI toolkits, and the resulting apps consumed a fraction of the resources. The main thing they lacked was mobile support and DPI awareness!


> ... for small gains in developer productivity

I think this is an underestimation, to be honest. What I struggled with native code to be able to do when I was younger is now stuff that literally anyone can do using any number of off the shelf libraries and tools targeting web browsers. This is an amazing achievement and not a bad thing in and of itself; if anything, what I lament the most is that the browser is killing native apps by being a "better" overall option.

Most software companies nowadays take it for granted that they need to ship some kind of web access to their network service, so that's the first thing they work on. Next they probably want to support iPhone and Windows, and probably Android, macOS, maybe even Linux... There are some options that cover each of these platforms to some degree, but by this point they probably already have at least a proof of concept in a web browser, and with a single NPM install, they can have that show up in a separate window, ready to ship with an installer and deployment system (not a great one mind you, but still.)

This wouldn't be as much of a problem if there were good, production-quality, efficient native code GUI frameworks that could efficiently target the DOM and native UIs across Windows, macOS, Android and iPhone, have first-class support for native text input with IME and platform-native semantics as well as accessibility support with screen reader integration, deal with responsive UI changes when dealing with different scree sizes, and have robust but performant DPI-independent visuals that handle fractional scale correctly. (Easy stuff, right?)

But there's not. And although I love Delphi VCL, or even just raw Win32, it's just not most of that either. Supporting all of these platforms is very hard. Browsers do a very good job and are often some of the best sources of example code for writing deep platform-specific code you can find. And best of all, since you're targeting web anyway most of the time, and browser engines are "native code", it's a hell of a lot easier to just ship the browser or at least JS engine to platforms that already run native code than it is to try to create an isomorphic native code solution that can also run in a browser environment.

I think that things will get better, eventually. But, they'll probably get worse before they get better.


Can you elaborate on "arguably much more productive"?


Let me give a more recent example.

A few years back I was building a B2B website for companies to manage event listings[1], fully modern React stack.

I wanted to get the backend API up and running first so I threw together a prototype in WinForms and C#. I had been writing React all day every day for a couple years at that point, and I hadn't used C# or WinForms for quite a few years (3 or 4 at least).

Also none of the GCP APIs I was using had official C# WinForms libraries (hah!) but of course everything had nice React integrations.

So anyway, within a day and a half or so I have a C# desktop app up and running that has about 80% of the site's planned functionality implemented. It is ugly, but it works.

Over 3 months later I have the React site up and running.

The React site supported Mobile and Desktop browsers, and it looked nicer, but the productivity to create the React site was literal orders of magnitude less.

FWIW I had a similar experience going from React to Svelte, I got done in 3 days what would have taken me weeks in React.

(For those paying attention, Svelte was still slower than C#!)

Part of the difference is that we expect web apps to be all shiny and work at any screen size with fancy CSS, vs a desktop app which can just do its thing.

The other part is that, IMHO, HTML+CSS are crap for laying out application UIs. Better than what they used to be, but still absurdly complicated.

[1] Create their business profile, list and manage events on a timeline/calendar, view attendees, send announcements to attendees, real time view of people as they show up to the event by hooking into Geo-locating on the phone, manage photos, and so on and so forth.


> The other part is that, IMHO, HTML+CSS are crap for laying out application UIs. Better than what they used to be, but still absurdly complicated.

Not just absurdly complicated, but also absurdly inconsistent. If you write an app in JS+HTML+CSS and use Electron to deploy it, the UI could literally be anything, as can the controls, etc. Nothing matches the OS UI neither, and standards have gone out of the window :(


> If you write an app in JS+HTML+CSS and use Electron to deploy it, the UI could literally be anything, as can the controls, etc. Nothing matches the OS UI neither

This may be seen by some people as an advantage though. For example my work computer is a Mac and my personal laptop runs Windows & Linux and I specifically like when application's UX is consistent across the different operating systems...


Very true. In some cases, it can be a force for good; a force for innovation.


What's wrong with the OS styled inputs?


Productivity has to incorporate some notion of deployment. As was standard for that era, Delphi/VB ignored this question completely. Time to deploy your app? If you made a simple zip utility, no problem, copy a single EXE onto a network mount somewhere inside your firewalled LAN. Windows has a pseudo-filesystem embedded into the binary which just about services for loading icons and strings, that'll do. Something more complicated, with DLLs and registry entries perhaps? Buy a copy of InstallShield for hundreds of dollars and learn InstallScript. Not only was there nothing in between until MSI and WiX came along but right up until the mid 1990s Microsoft saw the internet as this exotic fad, and using networks for software distribution was considered unworkable due to low bandwidth. Software was for CD-ROMs and shipping meant physically putting it on a ship.

Problem is, iteration speed mattered more to people than almost anything else including raw productivity. The world changed faster than Delphi did. Borland could have recognized the trend of hacking browsers into making apps was representing some fundamentally unarticulated need and come up with e.g. an Object Pascal interpreter. They could have done some sort of "Delphi Browser", for instance, and it would have gained adoption, but their codebase was fundamentally oriented around producing native Windows apps so it would have been difficult to make that move. Plus, Borland were basically guests on the Windows platform and tended to follow Microsoft's lead. Microsoft were pushing ActiveX as the way to bridge the web and the Windows world; Borland realized too late that ActiveX wasn't going to meet people's needs. They saw the web first as not a competitor, and then later as a mere carrier for Delphi apps, and then later still pushed using Delphi for writing web servers but its strengths didn't apply there.

So the lessons I took away from this were really about unarticulated preferences that you have to learn about by watching what people do, not what they say, and also the overwhelming importance of deployment - still a blind spot for most web competitors today. Up until last year if you wanted to use a Delphi-like platform with web-like deployment where apps are always refreshed on launch there just wasn't much out there. Even Electron only offers fully asynchronous desktop-style updates. I have a little company that makes products for fixing deployment of desktop apps (within the constraints of the native platforms), which adds a web-like deployment mode called aggressive updates (https://hydraulic.dev/). With that an update check is done on every launch, so you can iterate very fast as long as your users restart the app from the time to time or of course you can force it when the time is right, no different to requiring users to close and reload tabs for a SPA.

Anyway, I disagree that the main thing they lacked was mobile + DPI. Delphi, VB, GTK, Cocoa etc had lost the desktop before smartphones mattered at all because they lacked a good deployment and update system, and the ability to push out fixes and changes instantly mattered more than all the other features combined.


> and the ability to push out fixes and changes instantly mattered more than all the other features combined.

It mattered for developers. Users couldn’t care less.

While I do agree that back in the day, we missed standardized update systems, we do have them now (Flatpack, Winget, the stores …) and they could have appeared sooner if the industry did not plunge entirely in this web thing.

Sure the old days were not perfect but we are now in such an extreme opposite that your computer doesn’t even compute anything except a browser engine.


I agree that it's gone from one extreme to the other and this isn't really healthy, hence our work on Conveyor, trying to find a nice middle ground for non-web apps.

I think users do appreciate fast iteration. If they report a bug in the morning and it's fixed by the afternoon, that feels very different to reporting a bug and being told it'll get fixed in the next version which ships in 2 months. Even very basic and subtle differences between web and non-web apps matter here, for example, the lack of version numbers, the precise control over caching policy, the refresh button all make big differences to the overall feel of things.


The pace of technological advancement has gotten so fast, that we are starting to experience a culture shock from our culture: future shock. It is going to accelerate even further in our lifetime.

It is great to see Windows 3.1 software again.

I am just going to leave this here, strictly for the retro enthusiasts: https://www.xfce-look.org/p/1016410


Native TLS is the most impressive part.

I remember being told that modern cryptography isn't usable on old CPUs simply because of the amount of unoptimizable number crunching involved. As in, some steps of the key exchange algorithm would take so long that the server would time out. But apparently that's not a problem for a 386 despite being old and slow?


Considering how many embedded devices are in use, a lot of which are 8 bit microcontrollers with minimal RAM, designing systems that way would be irresponsible. There probably are some systems that don’t have an embedded use case that would (Eg. Encryption for live video) but not everyone is connecting to the internet on the newest iPhone.


One of the specific design requirements for the AES competition is that it could be used in embedded systems, which at the time was synonymous with 8-bits and limited memory. There are AES candidate 'reference' implementation floating around for the original AES bakeoff (that Rijndael eventually won) running in a couple of KB of memory for the 8051 and mc6805, for example, and I know of at least one PIC version of AES in use. There's probably tons of other examples; given how well documented the algorithm is, it's one of those things a lot of people probably take a swing at.

Now...this is obviously for sending small amounts of data at low (very) bit rates 'securely', not modern web or streaming or anything fun like that. And my understanding is that the real killer in trying to do something like TLS on such small platforms is the key generation/exchange/management part. YMMV.


I've always had the impression that modern internet-connected (and I mean the public internet with TLS and all that, not just LAN) embedded devices use fairly beefy, and at least 32-bit, CPUs just for that reason. But the bits don't make as much difference as the clock speed, and that can go much higher in modern days thanks to the smaller node size.


In 2023 yes but there are lot of in production systems designed in the past around older chip designs and old hardware in the real world with slower chips. For example a common low processing power network device you can still make easily today is an Arduino Uno with a network hat.


the network "hat" use to be a full blown ESP8266, an mcu that is a lot more powerful than the arduino Uno !


Are you sure an Arduino has enough resources to establish a TLS 1.3 connection?


There are "100 MIPS" 8051 variants (for some value of MIPS) like the Silicon Labs C8051F360. Not sure that's fast enough for 'modern web', but probably fast enough for a lot of interesting things.


This is fantastic! I was just thinking of creating a windows 3.11 working environment with win32s, dos7.1 for fat32 long filenames, some popular 16bit compiled unix binaries and calmira shell. Keep everything more simple. If tls 1.3 is possible on windows 3.1, people can also make a gemini client.


This is extremely neat and I will probably try it on one of my actual Windows 3.1 machines :)

A suggestion (which seems easy enough to implement, I might give it a try if I can get the build environment set up): make the system prompt customizable in the Options dialog. Having it be 1992 is fun, but kinda limiting. I might actually use this at some point -- if you're on your retro computer, trying to solve a problem, it might actually make some semblance of sense to use this rather than dig out a modern computer or smartphone.


That's a great idea. Please do give it a try!


If you used Win32s for Windows 3.1, you wouldn't have to bother with the segmented memory model and it could also work on 64-bit Windows.


Yeah, however stuff like Win32s and WinG seem like lore that only old timers remember, and only those of us that would regularly buy programming magazines.


This is great. After all these efforts, you should consider switching from ChatGPT 3.5 to ChatGPT 4.

Here is the answer of ChatGPT4 when asked the same question about the status bar (I truncated the code output because it's very long):

Using the Shell Common Controls in Windows 3.1 can be a bit tricky due to its older architecture and limited capabilities, but it's certainly doable.

However, there are a few complications to note:

1. Windows 3.1 does not natively support the status bar as a control. Status bars are part of the Common Controls library introduced in Win32, specifically, it was introduced in Windows 95 with COMCTL32.DLL. Windows 3.1 is a 16-bit environment and does not include this library.

2. If you want a status bar in a Windows 3.1 application, you'll have to draw and manage it yourself.

3. Windows 3.1 programming is largely obsolete. It can be a fun academic exercise or a necessity for maintaining legacy software, but if you're developing new software it would be much more practical to use a more modern version of Windows and its associated API.

Assuming that you still want to go ahead, here's a basic idea of how you might implement a status bar yourself:

  ```c
  #include <windows.h>
  
  #define ID_STATUS 100
  
  LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
  
  int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, 
      PSTR szCmdLine, int iCmdShow) 
 {
  ...


The Common Controls library actually became available with Windows 3.11. The Windows 3.11 SDK contains the commctrl.h header. The wfw31wh.hlp file explains how to use the controls. Windows 95 still provided a 16 bit commctrl.dll but omitted the CreateHeaderWindow function.


Checked the installation disks. It is only available in Windows for Workgroups. The DLL already exists in WfW 3.1. It does not exist in the plain, not for Workgroups Windows version 3.11 released after WfW 3.11.


There might be a control in the Calmira source code that would help, but it is in Pascal and not C.

http://www.calmira.net/source/index.htm


not everyone has access to gpt 4 yet.


if you pay chat gpt plus then yes everyone has had access for quite some time now


There's a difference between being able to access gpt4 via chat gpt plus, and being able to access gpt4 over the openai APIs.


Such a cool project! Also the example conversation in the screenshot is hilarious.


Can ChatGPT be told to pretend it's 1990 and answer accordingly?


I just tested this out. The first couple answers it said things like, "In the year 1990, this was.." and "The Internet as we know it now was not yet as widespread..", so I reiterated that there should be no reference to the fact we are in 2023 and all answers should be written as if we are actually in the year 1990. Then I tried a few questions and it worked out pretty well. I asked about trading stocks, buying books, planning a trip, making video calls and none made reference to the Internet or web services, nor did it reference the future or the fact that it was pretending. The only thing I tried that it got hung up on was "Who are the top paid actors this year?" And it gave the standard reply, "As an AI, I don't have specific data about top paid actors in the year 1990"


Got it working from the get-go and got similar results. I think the "this year?" in the prompt confuses it too much. With my prompt below, using "this decade?" works quite well.

Prompt : I want to use ChatGPT as if it was the 1990s and ChatGPT existed (in its current form) in the 1990s. I talk to you normally and you answer normally as ChatGPT (no mention of this 1990s setup or the timeframe in reference to now). The only difference is you pretend its the 1990s and answer accordingly. Stay in character, you play yourself. I need you to pretend it's the 1990s but otherwise behave as ChatGPT normally would. Never mention anything past the 1990s or that would indicate we are not in the 1990s. Do not mention this conversation (it's a pre-prompt). Let's go. First question : which internet browser do you recommend ?

Answer: There are several good browsers available currently. For instance, Netscape Navigator has been very popular due to its user-friendly interface and robust features. It's currently one of the most widely used browsers.

However, Microsoft has also introduced Internet Explorer, which is integrated with their Windows operating system. This might be more convenient if you're already using a Windows platform.

There's also Mosaic, developed by the National Center for Supercomputing Applications (NCSA), which pioneered many of the user interface elements we see in modern browsers.

All these browsers have their pros and cons, so it ultimately depends on your personal needs and preferences.

Q : Who are the top paid actors this decade? A : During the 1990s, some of the highest-grossing actors have been:

Tom Cruise - He's been in a string of successful films including the "Mission: Impossible" franchise which started in 1996.

Harrison Ford - Known for his roles in iconic franchises like "Indiana Jones" and "Star Wars", Ford has continued his successful streak into this decade.

Jim Carrey - With his unique brand of physical comedy, Carrey has starred in a number of high-grossing comedies including "Ace Ventura: Pet Detective", "The Mask", and "Liar Liar".

Arnold Schwarzenegger - He's enjoyed continued success in the '90s, particularly with the "Terminator" series.

Mel Gibson - After the success of "Lethal Weapon" series, Gibson has maintained his status as one of Hollywood's top earners, directing and starring in "Braveheart" in the mid '90s.

Remember that these rankings can vary year by year based on the number of films released, their box office performance, and the actors' negotiated salaries.


Yep, I've hardcoded a "system" message that tells ChatGPT to answer in the present tense as if it's 1992, and to make no reference to the current year. It does still slip up and mention the year as mitchdoogle experienced, but it's pretty good most of the time - even with complex questions like asking how many countries there are in NATO.


You can, but you sometimes have to remind it over the course of a conversation.


WinGPT seems to prepend every user prompt with:

You are a friendly but concise chat bot. Answer all questions in the present tense as if it is 1992, and make no reference to the current year.


Thanks! :)


I maybe feel nostalgic, but the old ui is so much... Better :)


Have you considered building it into Clippy?


the UI is screaming speed. Actually most of the apps I use in Windows now, have that kind of UI, I hate that with the kind of hardware we have currently, we need to wait for a window to appear.

Apps I use daily: totalcmd, clipx, far, sublime text ( only for edit text, code with intellij )


> Another fun part of building WinGPT was designing the icon in Borland's Image Editor, which is really just a clone of Microsoft Paint that happens to make ICO files instead.

Wow! 40yo me forgot how much time I used to spend creating icons for my apps back in 1999. After trying a million times to create C++ programs Visual Studio 6, I would often fall into just drawing icons in the icon editor as it was the only thing left to do once I introduced a compiler error and couldn't resolve it.


> It will not work on 64-bit versions of Windows

ouch


It could work with the help with otvdm: https://github.com/otya128/winevdm


Same reason why DOS programs don't run there.


But it will probably work fine on Linux with Wine.


I am not installing Linux and Wine just to run a Windows program. 64-bit CPUs have been available for PCs for at least 20 years. while this is a neat idea, omitting 64-bit support makes this nothing more than a fun experiment.


Now we just need one for System 6.0.8!


There is a similar Client for System 7 called LegacyAI that has been making waves in VintageApple circles


Talking Moose 2023?


Shame microsoft agent (clippy) is 98 or later only, could be pretty fun integrated into that.


> difference between far and near pointers

Remembrance unlocked! There are really near (offset only) and far (segment + offset) pointers in x86 16 bit architecture. Also near and far jumps. Gods, how long ago was that...


Cool project, but as the author quickly found out there was a good reason why non masochists were already using C++ frameworks, TPW, VB, Delphi, VF, VO,...instead of raw C.


So cool! Can it run on Windows NT 3.51? Would doing so solve some of the memory limitations?


If you got TLS 1.3 to work in Win 3.11, you deserve an award from Microsoft.


Now all they need to do is get ChatGPT integrated with AOL and Compuserv.


So this is how win3.1 got Clippy then?


Would be nice to see the source :)


Source code download is at the bottom of this page: https://www.dialup.net/wingpt/tls.html


(The app part is in watcom16/wingpt.)


Well done. Very creative.


How about Win 3.11 ? It has networking support, you know.


Barely. TCP/IP networking requires third party winsock adapters.

The built in network stack and applications in Windows 3.11 is limited to file, print sharing and maybe sending some popup messages.


Why though


Man, you’re on the wrong website.


The answer is as always: Why not?


Intellectual curiosity, I'd guess


You are asking the wrong question!




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: