GetMax does what its name says: Gets the latest (SVN) version of BlitzMax for you.
Upsides: has a simple GUI, does NOT require an SVN client and is small.
Downsides: rather slow, does not update and has no error handling.
Source available below.

Updated with SebHoll's changes.
Source:
Upsides: has a simple GUI, does NOT require an SVN client and is small.
Downsides: rather slow, does not update and has no error handling.
Source available below.

Updated with SebHoll's changes.
Source:
SuperStrict Framework MaxGUI.Drivers Import BRL.EventQueue Import BRL.FileSystem Import BRL.SocketStream Import Bah.Base64 AppTitle = "Get BlitzMax" Function CreateHttpStream:TSocketStream( server:String, port:Int, file:String = "/", auth:String = "" ) Local stream:TSocketStream=TSocketStream.CreateClient( server, port ) If Not stream Return Null stream.WriteLine "GET "+file+" HTTP/1.0" stream.WriteLine "Host: "+server stream.WriteLine "Authorization: Basic "+auth stream.WriteLine "" Return stream End Function Function DLDir(base:String, dir:String, auth:String, text:Int(t:String)) Local stream:TSocketStream = CreateHttpStream("blitzbasic.com", 81, base+dir, auth) PollSystem() While stream And Not stream.Eof() If stream.ReadLine()="" Exit Wend If stream And Not stream.Eof() If Not CreateDir( dir, True ) Return End If While stream And Not stream.Eof() Local l:String = stream.ReadLine().Trim() If l.StartsWith("<li><a") Local href:String = l.Split("~q")[1].Replace("%20", " ") If href.EndsWith("/") If href<>"../" Then DLDir base, dir+href, auth, text Else DLFile base, dir, href, auth, text End If End If Wend End Function Function DLFile(base:String, dir:String, file:String, auth:String, text:Int(t:String)) If FileType(dir+file) Return PollSystem() Local stream:TSocketStream = CreateHttpStream("blitzbasic.com", 81, base+dir+file, auth) Local length% While stream And Not stream.Eof() Local l:String = stream.ReadLine() If l.StartsWith("Content-Length") Then length = Int(l.Split(" ")[1]) If l="" Exit Wend Local out:TStream If stream And Not stream.Eof() out = WriteFile(dir+file) If Not out Return text String(dir+file).Replace("%20"," ") + " ("+Int((length/1000.0)+1)+"KB)" End If Local data:Byte[] While stream And Not stream.Eof() Local tmpBytes:Byte[SocketReadAvail(SocketStreamSocket(stream))] stream.ReadBytes( tmpBytes, tmpBytes.length ) data:+tmpBytes PollSystem() Wend Assert data.length = length, "File length mismatch!" If out Then If data Then out.WriteBytes data, data.length out.close() EndIf End Function Local win:TGadget = CreateWindow(AppTitle, 100, 100, 400, 300, Null, WINDOW_TITLEBAR|WINDOW_CLIENTCOORDS ) 'User details Local ulabel:TGadget = CreateLabel("Username: ", 10,15,70,25, win) Local user:TGadget = CreateTextField(80,10,110,25, win) Local plabel:TGadget = CreateLabel("Password: ", 210,15,70,25, win) Local pass:TGadget = CreateTextField(280,10,110,25, win, TEXTFIELD_PASSWORD) 'Directory Local dlabel:TGadget = CreateLabel("Target: ", 10,50,70,25, win) Local dir:TGadget = CreateTextField(80,45,220,25, win) Local dirget:TGadget = CreateButton("Browse...", 310,45,80,25, win) 'Platforms Local blabel:TGadget = CreateLabel("Platform: ", 10,85,70,25, win) Local binary:TGadget = CreateComboBox(80,80,110,25, win) AddGadgetItem binary, "Windows (x86)", GADGETITEM_DEFAULT, -1, "", "win32_x86" AddGadgetItem binary, "Linux (x86)", 0, -1, "", "linux_x86" AddGadgetItem binary, "Mac OS X (x86)", 0, -1, "", "macos_x86" AddGadgetItem binary, "Mac OS X (PPC)", 0, -1, "", "macos_ppc" 'MaxGUI? Local guimod:TGadget = CreateButton("Get MaxGUI", 200,80,110,25, win, BUTTON_CHECKBOX) 'Start Local start:TGadget = CreateButton("Start", 310,80,80,25, win) DisableGadget start 'Output Display Global outputdisp:TGadget = CreateListBox(10,115,380,175, win) ActivateGadget user Repeat Select WaitEvent() Case EVENT_GADGETACTION Select EventSource() Case start Exit Case dirget SetGadgetText dir, RequestDir("Choose a new BlitzMax directory...") EndSelect If GadgetText(user) And GadgetText(pass) And GadgetText(dir) Then EnableGadget(start) Else DisableGadget(start) Case EVENT_WINDOWCLOSE End End Select Forever DisableGadget dir DisableGadget dirget DisableGadget user DisableGadget pass DisableGadget binary DisableGadget guimod DisableGadget start EnableGadget outputdisp Function ShowText:Int(s:String) If s Then AddGadgetItem outputdisp,s,GADGETITEM_DEFAULT End Function If Not FileType(GadgetText(dir)) Then CreateDir(GadgetText(dir), True) If Not ChangeDir(GadgetText(dir)) Notify "Unable to create directory: "+GadgetText(dir), True End End If If Not user Or Not pass Notify "Username/password required!", True End End If Local auth:String = GadgetText(user)+":"+GadgetText(pass) Local c:Byte Ptr = auth.ToCString() auth = TBase64.Encode(c, auth.length) MemFree c DLDir "/svn/blitzmax/dev/main/", "", auth, ShowText DLDir "/svn/blitzmax/dev/"+String(GadgetItemExtra(binary, SelectedGadgetItem(binary)))+"/", "", auth, ShowText If ButtonState(guimod) If Not FileType(GadgetText(dir)+"/mod/maxgui.mod") Then CreateDir(GadgetText(dir)+"/mod/maxgui.mod", True) If Not ChangeDir(GadgetText(dir)+"/mod/maxgui.mod") Notify "Unable to create directory: "+GadgetText(dir)+"/mod/maxgui.mod", True End End If DLDir "/svn/maxgui/dev/maxgui.mod/", "", auth, ShowText End If Notify "All done!", False