The latest news about a “Windows 10 Lean” version of Windows sounds exciting, but it is not enough. Why ?
The technology today is there to create the tiniest x86 device yet which can run Windows 10 on a device as small as a Raspberry PI Zero. Yes, not just the Raspberry PI size SOC but one as small as the Raspberry PI Zero. We already have TV Stick style x86 devices capable of running Windows 10 and it is not without reason to think that something smaller could be created. But why haven’t we gotten there yet ?
The problem is with how software is written
What is overlooked is the core of Windows which has been there for a long time. Yes, the WIN32 API. Today everything is all about cross platform and mobile and the technologies used for that make some sense, but tiny x86 devices are not about cross platform nor are they all about browsing the web. Such devices would have a use for the so called “Maker” market, robotics and IOT (Internet of Things). A totally different approach is required for such devices. The key to such markets is:
“smaller, faster, smaller, faster, smaller, faster”
and that is not about hardware, but software. This quote was by the late Bob Zale, the creator of the once famous Turbo Basic (Borland International bought it from him) and the great grand child of Turbo Basic, called Powerbasic. I had the privilege to interview Mr. Zale back in 2011 and you can read the article on Tech Republic’s website here:
https://www.techrepublic.com/blog/software-engineer/interview-with-powerbasic-founder-bob-zale/
You can also listen to the Dot.Net Rocks podcast of their interview with Bob Zale and also Ethan Winer (co-founder of Crescent Software) here:
https://www.dotnetrocks.com/default.aspx?showNum=20
What did Bob Zale mean by “smaller, faster” ? Having used his BASIC compilers for nearly 20 years now, I can attest to how fast they compile, how powerful they are and how small an executable they can create. Powerbasic is one of the software industries best kept secrets. The only way to describe Powerbasic is that is it BASIC, with the raw power of C. This is not your grandfathers old interpreted BASIC, but it is a lean and powerful development system. It leverages the raw power of the WIN32 API, something I am well aware of myself. Having coded directly to the WIN32 API for nearly 2 decades now, it still amazes me the raw power there and the blazingly fast performance one can get from it. The beauty of BASIC when it comes to the WIN32 API is that the code is readable and understandable. For example here is a simple example which I created which emulates a Caption Bar inside a real custom control. The control is compiled into a DLL which can be used with any application, even ones written in C.
%ControlClassExtraData = 6
$ControlClassName = "CAPCTRL32"
%WM_MYCOLOR = %WM_CTLCOLORSTATIC
DECLARE FUNCTION GetControlLong(BYVAL hWnd AS LONG, BYVAL N&) AS LONG
DECLARE SUB SetControlLong(BYVAL hWnd AS LONG, BYVAL N&, BYVAL V&)
DECLARE SUB RegisterControlClass()
DECLARE SUB ControlClassPaint(BYVAL hWnd AS LONG)
DECLARE SUB ControlClassDraw(BYVAL hWnd AS LONG)
DECLARE SUB BuildBitmap(BYVAL hWnd AS LONG, BYVAL CFlag&)
%CP_CUSTOM_MESSAGE = %WM_USER+100
%CP_GETSTATE = %WM_USER+101
FUNCTION LIBMAIN(BYVAL hInstance AS LONG, _
BYVAL fwdReason AS LONG, _
BYVAL lpvReserved AS LONG) EXPORT AS LONG
SELECT CASE fwdReason
CASE %DLL_PROCESS_ATTACH
RegisterControlClass
CASE %DLL_THREAD_ATTACH
CASE %DLL_THREAD_DETACH
CASE %DLL_PROCESS_DETACH
CASE ELSE
END SELECT
LIBMAIN=1
END FUNCTION
SUB RegisterControlClass()
LOCAL windowclass AS WndClassEx
LOCAL szClassName AS ASCIIZ * 80
szClassName = $ControlClassName+CHR$(0)
windowclass.cbSize = SIZEOF(windowclass)
windowclass.style = %CS_HREDRAW OR %CS_VREDRAW OR %CS_PARENTDC OR %CS_DBLCLKS
windowclass.lpfnWndProc = CODEPTR(ControlClassWndProc)
windowclass.cbClsExtra = 0
windowclass.cbWndExtra = %ControlClassExtraData*4
windowclass.hInstance = GetModuleHandle(BYVAL %NULL)
windowclass.hIcon = %NULL
windowclass.hCursor = LoadCursor( %NULL, BYVAL %IDC_ARROW )
windowclass.hbrBackground = GetStockObject( %WHITE_BRUSH )
windowclass.lpszMenuName = %NULL
windowclass.lpszClassName = VARPTR( szClassName )
windowclass.hIconSm = %NULL
RegisterClassEx windowclass
END SUB
SUB DefTrueSize(BYVAL hWnd&, AY&, ACY&)
LOCAL AWS&, AH&
AWS&=GetWindowLong(hWnd&, %GWL_EXSTYLE) AND %WS_EX_TOOLWINDOW
IF AWS&=%WS_EX_TOOLWINDOW THEN
AH&=GetSystemMetrics(%SM_CYSMCAPTION)
ELSE
AH&=GetSystemMetrics(%SM_CYCAPTION)
END IF
AY&=(AY&+ACY&)-AH&
ACY&=AY&+AH&-1
END SUB
FUNCTION GetTrueTop(BYVAL hWnd&, BYVAL Y2&) AS LONG
LOCAL AWS&, AH&
AWS&=GetWindowLong(hWnd&, %GWL_EXSTYLE) AND %WS_EX_TOOLWINDOW
IF AWS&=%WS_EX_TOOLWINDOW THEN
AH&=GetSystemMetrics(%SM_CYSMCAPTION)
ELSE
AH&=GetSystemMetrics(%SM_CYCAPTION)
END IF
FUNCTION=Y2&-AH&
END FUNCTION
FUNCTION GetHeight(BYVAL hWnd&) AS LONG
LOCAL AWS&, AH&
AWS&=GetWindowLong(hWnd&, %GWL_EXSTYLE) AND %WS_EX_TOOLWINDOW
IF AWS&=%WS_EX_TOOLWINDOW THEN
AH&=GetSystemMetrics(%SM_CYSMCAPTION)
ELSE
AH&=GetSystemMetrics(%SM_CYCAPTION)
END IF
AH&=AH&+GetSystemMetrics(%SM_CYDLGFRAME)
FUNCTION=AH&
END FUNCTION
FUNCTION ControlClassWndProc(BYVAL hWnd AS LONG, _
BYVAL Msg AS LONG, _
BYVAL wParam AS LONG, _
BYVAL lParam AS LONG) EXPORT AS LONG
LOCAL RV&, hParent AS LONG
SELECT CASE Msg
CASE %WM_SIZE
IF GetControlLong(hWnd,6)=0 THEN
SetControlLong hWnd,6,1
FUNCTION = DefWindowProc(hWnd,Msg,wParam,lParam)
DIM R AS RECT
GetWindowRect hWnd,R
R.nTop=R.nBottom-GetHeight(hWnd)
ScreenToClient GetParent(hWnd), BYVAL VARPTR(R)
ScreenToClient GetParent(hWnd), BYVAL VARPTR(R)+8
MoveWindow hWnd, R.nLeft, R.nTop, R.nRight-R.nLeft, R.nBottom-R.nTop, 1
SetControlLong hWnd,6,0
EXIT FUNCTION
END IF
CASE %WM_CREATE
DIM CS AS CREATESTRUCT PTR, WS&, EXS&, WP2 AS WINDOWPOS
CS=lParam
WS&=@CS.style
EXS&=@CS.dwExStyle
WS&=WS& AND (%WS_CHILD OR %WS_VISIBLE OR %WS_CLIPSIBLINGS OR %WS_CLIPCHILDREN OR %WS_SYSMENU)
WS&=WS& OR %WS_CAPTION
@CS.style=WS&
EXS&=EXS& AND %WS_EX_TOOLWINDOW
@CS.dwExStyle=EXS&
SetWindowLong hWnd, %GWL_STYLE, WS&
SetWindowLong hWnd, %GWL_EXSTYLE, EXS&
CASE %WM_NCHITTEST
FUNCTION=%HTCLIENT
EXIT FUNCTION
CASE %WM_LBUTTONDOWN
IF GetControlLong(hWnd,5)=0 THEN
SetControlLong hWnd,5,1
SendMessage hWnd, %WM_NCACTIVATE, 1,0
ELSE
SetControlLong hWnd,5,0
SendMessage hWnd, %WM_NCACTIVATE, 0,0
END IF
hParent=GetParent(hWnd)
IF hParent<>0 THEN
SendMessage hParent, %WM_COMMAND,MAKLNG(GetWindowLong(hWnd,%GWL_ID),%STN_CLICKED), hWnd
END IF
FUNCTION=0
EXIT FUNCTION
CASE %WM_LBUTTONDOWN
FUNCTION=0
EXIT FUNCTION
CASE %CP_CUSTOM_MESSAGE
CASE %CP_GETSTATE
FUNCTION=GetControlLong(hWnd,5)
EXIT FUNCTION
CASE %WM_PAINT
CASE %WM_ERASEBKGND
CASE %WM_SETCURSOR
CASE %WM_LBUTTONDBLCLK
hParent=GetParent(hWnd)
IF hParent<>0 THEN
SendMessage hParent, %WM_COMMAND, MAKLNG(GetWindowLong(hWnd,%GWL_ID),%STN_DBLCLK), hWnd
END IF
CASE %WM_DESTROY
CASE ELSE
END SELECT
FUNCTION = DefWindowProc(hWnd,Msg,wParam,lParam)
END FUNCTION
FUNCTION GetControlLong(BYVAL hWnd AS LONG, BYVAL N&) AS LONG
LOCAL I&, RV&
RV&=0
IF N&>=1 AND N&<=%ControlClassExtraData THEN
I&=(N&-1)*4
IF IsWindow(hWnd) THEN
RV&=GetWindowLong(hWnd, I&)
END IF
END IF
FUNCTION=RV&
END FUNCTION
SUB SetControlLong(BYVAL hWnd AS LONG, BYVAL N&, BYVAL V&)
LOCAL I&
IF N&>=1 AND N&<=%ControlClassExtraData THEN
I&=(N&-1)*4
IF IsWindow(hWnd) THEN
SetWindowLong hWnd, I&, V&
END IF
END IF
END SUB
Notice, that despite it being WIN32 API code, it is still quite readable. Yes, BASIC makes WIN32 coding easier. Now this does not mean that one has to write everything in low level WIN32 API code. You can write higher level libraries on top of it or even use PowerBasic’s thin API user interface wrapper (called Dynamic Dialog Tools) to makes things a little easier. I built my own GUI framework using Powerbasic and the runtime for the entire framework is only about 1 megabyte in size and it includes a number of built in custom controls, a 2D sprite engine, a 3D openGL based graphic control and much more. By writing easy to use wrappers over the WIN32, one can build software even faster and more easily. Here is how the code to a simple app looks like using a GUI framework I wrote in Powerbasic:
#COMPILE EXE
#DIM ALL
#INCLUDE "..\includes\ezgui50.inc"
%FORM1_LABEL1 = 100
%FORM1_HScrollBar1 = 105
%FORM1_LABEL2 = 110
DECLARE SUB FORM1_HScrollBar1_Click()
#INCLUDE "..\includes\ezwmain50.inc"
SUB EZ_Main(VerNum&) EXPORT
EZ_LoadPatternLib "", ""
EZ_Color 0,-56
EZ_Form "FORM1", "", "Select Colors", 0, 0, 48, 18, "C"
END SUB
SUB EZ_DesignWindow(FormName$) EXPORT
SELECT CASE FormName$
EZ_Color 0, 0
EZ_UseFont -1
EZ_UseFont 4
EZ_Label %FORM1_LABEL1, 1, 1, 46, 10, "", "CS"
EZ_Color -1,-1
EZ_UseFont 4
EZ_HScroll %FORM1_HScrollBar1, 2, 12, 44, 1.5, ""
EZ_SetHScroll "FORM1", %FORM1_HScrollBar1, -57, 36, 0, 5
EZ_Color 15, 1
EZ_DefFont 10, "Tahoma", 16, "BV"
EZ_UseFont 10
EZ_Label %FORM1_LABEL2, 2, 15, 45, 2, "Move Slider to change colors", "CI"
CASE ELSE
END SELECT
END SUB
SUB EZ_Events(FormName$, CID&, CMsg&, CVal&, Cancel&) EXPORT
SELECT CASE FormName$
CASE "FORM1"
SELECT CASE CID&
CASE %EZ_Window
IF CMsg&=%EZ_Close THEN
END IF
CASE %FORM1_HScrollBar1
IF CMsg&=%EZ_Change THEN
IF CVal&<=31 THEN
EZ_SetColor "FORM1", %FORM1_LABEL1, 0, CVal&
EZ_SetText "Form1", 0, "Current Color Number is "+STR$(CVal&)
END IF
END IF
CASE ELSE
END SELECT
CASE ELSE
END SELECT
END SUB
The point is, that one need not have to write code for a Windows Lean using the WIN32 directly, but one can easily build easier to use wrappers over it, but without all the bulk of most of todays UI engines, like dot.net. Yes, dot.net has its place with the cross platform world, but in the IOT world or “Maker” world, coding to the native API’s produce amazingly lean and fast applications and the hardware requirements are minimal. The GUI framework I wrote can work even on an old legacy PC with earlier Windows versions (before XP) with as little as 256 meg ram or even less and the CPU need not be more than 300 MHz (that is megahertz, not gigahertz). The diskspace requirements are almost nothing (less than a floppy disk for app and runtime).
So I have no doubt that a leaner Windows would still perform extremely well if one leveraged the WIN32 API.
Most of the current x86 “Maker” boards (System on a Chip or SOC’s) are targeting at full blown Windows and they need at least 2 GB ram and 32 GB EMMC disk space. But a tiny SOC board with as little as 1 GB ram and an 8 GB EMMC (or even less) would suffice for a very lean (WIN32 only) Windows 10 and apps written using Powerbasic or C. Actually I would not doubt that using Powerbasic, if Windows could run on as little as a 500 MHz CPU, 256 meg RAM and whatever the OS needed for diskspace plus 1 GB extra, would suffice for developing apps and running them all on the device itself. Some manufacturers are already making SOC boards with minimal x86 hardware, such as the 86Duino which sports a 300 MHz CPU and has directly accessible GPIO ports on it, which I have not doubt Powerbasic could run on, if a Windows Lean was able to run on it. Check out the 86Duino boards here:
http://shop.dmp.com.tw/INT/products-516
http://www.86duino.com/
Do real software companies actually use the likes of Powerbasic ?
Absolutely! Fathom Systems in the UK are writing many applications for industrial use using Powerbasic. Check out this video of an amazing piece of industrial equipment where a laptop running an app written using Powerbasic is controlling it:
At about 4 minutes and 33 seconds you will see a laptop running the controlling software which was written in Powerbasic.
Native coding is a must for developing fast and lean applications which can run with minimal hardware. Check out Herb Sutter’s talk (on Channel 9) entitled “Why C++ ?” and notice his comments about the benefits of native coding:
https://channel9.msdn.com/posts/C-and-Beyond-2011-Herb-Sutter-Why-C
The hardware is capable in the x86 world. Now software needs to catch up. This would allow manufacturers of small and tiny x86 devices (SOC’s) to build even smaller and cheaper x86 boards and devices. Imagine school children being able to purchase a tiny x86 board with a Lean Windows 10 on it and be able to write apps on it even in BASIC (a real compiler with the raw power of C). It is doable and I sure would like to see it happen.