BMOW title
Border

Goodbye BMOW, and a Contest

It’s a bittersweet day today. After 18 months of development, occupying the top of my desk and the majority of my spare time, BMOW 1 has been officially retired to the closet. I packed up the case, packed up the power supply, keyboard, cables, EPROM programmer, and everything else. At least it had a good send-off party at the Maker Faire. Now I can actually see the surface of my desk for the first time since 2007, and I’m ready to turn my full attention to my next project.


To mark the occasion, I’m running a small contest, with ten fabulous BMOW stickers as the prize. If you’ve followed my progress for a while, then you know that the “C” key doesn’t work in BMOW BASIC, due to a bug related to control-C handling that I never bothered to fix. The contest is simple: write a BMOW BASIC program that prints the letter C to the screen, without typing “C” as part of the program. This isn’t as easy as it might seem, since many of the relevant BASIC keywords also have the letter C in their name.The first person to reply with a working solution, as judged by me, will receive the stickers by mail, and the honorary title of “BMOW Guru”. It’s not quite like being knighted, but it’s close.

Some hints:

  • BMOW BASIC is a straight port of Microsoft BASIC, but does not include any machine specific commands for file I/O, graphics, etc. Do a Google search to learn more about MS BASIC keywords.
  • The video memory is not mapped anywhere into the BASIC address space, so you can’t just POKE a byte into screen memory.
  • Try this Javascript Applesoft BASIC interpreter, which is also a Microsoft BASIC variant. But remember, BMOW BASIC isn’t 100% identical to Applesoft. Try the BMOW simulator on the Downloads page if you’re unsure.
Read 31 comments and join the conversation 

31 Comments so far

  1. Peter Lund June 14th, 2009 1:10 pm

    10 PRINT ” *** ”
    20 PRINT “* *”
    30 PRINT “*”
    40 PRINT “*”
    50 PRINT “* *”
    60 PRINT ” *** ”

    ;)

  2. Peter Lund June 14th, 2009 2:21 pm

    I don’t think there are any prebuilt strings available with a “C” in them.

    Typing CHR$(67) and “C” are both ruled out.

    That leaves creating a string with a “C” in it by using POKE or by running machine code (through the USR function). Or creating a BASIC program with “C” or CHR$ in it by using POKE or by running machine code (through the USR function). Or running machine code that prints it to the screen by switching to the right page.

    Running machine code that does any of the above requires using POKE anyhow, unless one somehow manages to find just the right instruction sequence somewhere in the BASIC interpreter or its data areas (inside a string or the tokenized BASIC code or someplace else).

    Using POKE requires knowing the address of the tokenized code or a string (for writing a “C” or CHR$) or it requires the address of free area (for poking machine code). One could use PEEK to look for a signature, of course.

    Given that I never really liked 6502 machine code — and would have to look up the details anyway and then look up how BMOW differs — I prefer not to use machine code in the solution.

    Yet another option, similar in spirit to much first cheat, would be to switch to a graphical mode and simply plot the C pixel by pixel. I don’t know if BMOW BASIC has keyword support for that.

    Considering all these options, how about something like:

    10 A$=”ABD”
    20 FOR I=512 TO 65530
    30 IF PEEK(I)=65 THEN IF PEEK(I+1)=66 THEN IF PEEK(I+2)=68 THEN GOTO 100
    40 NEXT I
    50 PRINT “Sorry :(
    60 STOP
    100 POKE I+2,67
    110 PRINT A$

    A Boyer-Moore-like loop combined with a longer string would be much faster for a search through so much memory.

    I’m guessing that strings are placed outside of zero-page and the stack ;)

    The loop could be tightened considerably with some knowledge of the BMOW memory map. And for all I know, BMOW doesn’t even use ASCII ;)

    I couldn’t find the source code to your Basic and I’m not going to fire up VMWare and booting Windows to run the simulator or attempt a disassembly of msbasic.bin. Yes, it might run under Mono, but…

  3. Erik Petrich June 14th, 2009 2:39 pm

    Give me a few minutes while I reload my brain from the cassette tape…

    If your variant of MSBasic supports the VARPTR function, you could do something like:

    10 A$=”B”
    20 A=VARPTR(A$)
    30 B=PEEK(A+1)+PEEK(A+2)*256
    40 POKE B,67
    50 PRINT A$

    VARPTR will return the address of the 3-byte string descriptor. The first byte is the string length, and the second and third bytes are a pointer to the actual string location in whatever endianness (I assumed little endian above) your platform uses. String constants in a program are not copied to the string heap but left embedded in the tokenized source, so the POKE instruction actually ends up modifying line 10 as a side-effect.

    If VARPTR isn’t available, we could do a brute force search and replace. Again the program will end up modifying itself:

    10 A$=”DOG”
    15 PRINT “WITH A BIT OF HARMLESS DNA”
    16 PRINT “FIDDLING, WE CAN TURN A “;A$
    20 FOR A=768 TO 4095
    30 IF PEEK(A)68 THEN GOTO 60
    40 IF PEEK(A+1)79 THEN GOTO 60
    50 IF PEEK(A+2)71 THEN GOTO 60
    55 POKE A,67
    56 POKE A+1,65
    57 POKE A+2,84
    58 PRINT “INTO A “;A$
    59 STOP
    60 NEXT A

    Might have to tweak the range in line 20. I was assuming the keyboard buffer was between 512 and 767 and that 0 to 511 would be used for internal variables and the stack.

  4. Steve June 14th, 2009 3:00 pm

    Good answers both! Peter’s solution is virtually identical to the one I came up with. In fact, they’re so eerily similar, I wonder if he was spying on me! Erik’s second solution also works, except the the range needs to be expanded to include the entire 64K address space. Email me your postal addresses, and I’ll send you both some of those BMOW stickers. :-)

  5. Peter Lund June 14th, 2009 3:02 pm

    By the looks of token.s in msbasic.zip at http://www.pagetable.com/?p=46 VARPTR is not supported.

    I think your range in line 20 is wrong. Judging by msbasic.lbl in bmowsim.zip, the BASIC interpreter follows right after the stack and input buffer and continues to somewhere past the 12K range. The page right before 16K is used for hardware I/O — or at least keyboard control/data.

  6. Erik Petrich June 14th, 2009 3:18 pm

    I’m too slow for Peter; oh well.

    Something a bit shorter: we could generate an error message with a “C” in it. If the 2 character error codes are enabled, you could type:

    PRINT SQR(-1)

    and get an “?FC ERROR”. If instead the longer error messages are enabled you could type:

    INPUT A

    and get an “ILLEGAL DIRECT ERROR”. I’m not sure if this qualifies as a program, though, since it wouldn’t be an error if you gave it a line number and ran it.

  7. Peter Lund June 14th, 2009 3:35 pm

    “Yet another option, similar in spirit to much first cheat, would be to switch to a graphical mode and simply plot the C pixel by pixel. I don’t know if BMOW BASIC has keyword support for that.”

    Similar in spirit to /my/ first cheat, of course.

    I like the error message-cheat, btw :) — what does the “return stack too deep” message say? Is the Microsoft easter egg that prints “Microsoft” included in this version? If so, one could run that.

  8. Erik Petrich June 14th, 2009 9:22 pm

    Trying to overflow the stack just gives “OUT OF MEMORY” or “?OM” errors, so no “C” available there.

  9. vince June 16th, 2009 10:51 am

    I’m not sure how closely you map the memory layout of Applesoft.

    On a real Apple II the following works:

    5 POKE 2049,67
    10 PRINT “B”

    But this depends on the tokenized program being stored starting at 0×801. A slightly more complex version could be written that reads the starting address from 0×67, but that would depend on your zero page mappings being the same as applesoft.

  10. Gregg C Levine June 16th, 2009 7:11 pm

    Hello!
    To be honest I am not really going to contribute to the issues with BMOW’s methods of doing BASIC….

    But I agree with you regarding a project.. It can be fun while it lasts, but it can be a mess on your nerves when it ends because of the left over stress.

    Now what you do need is a new project for your work area and take your mind off of this.

  11. Steve June 16th, 2009 7:17 pm

    Yup. And that project is already underway, in the form of 3D Graphics Thingy. I’ve been slowly reading through the documentation for my FPGA starter kit, and hope to produce some crude pixels on-screen soon.

  12. Peter Lund June 20th, 2009 6:37 am

    My stickers just arrived this morning — thanks, Steve :)

    I saw you used three stamps that had no value printed on them and then I went “hmmm…. I wonder what the story is with that — and how much does it cost, anyway?”

    So I learned that the US has an interesting thing called “Forever” stamps that always happen to be worth exactly what it costs to send a 1 ounce letter by first-class mail. Which was 42 cents until May 10 and 44 cents after that. Apparently, Finland and the UK also have them. And the bell /is/ the Liberty Bell, as I thought.

    I also learned that Denmark is in country group 5. Other EU countries are in group 3 or 4 or 5. I wonder what the logic is behind that.

    I’m surprised that it costs slightly less than a dollar to send a letter from the US to Denmark. That’s not much more than the price inside Denmark!

    I’m such a slave to my curiosity :/

  13. Friedrich Brunzema July 10th, 2009 12:23 pm

    What does Date$ print? If it prints the month, set the clock to December first, and parse out the “C” in december with Print Mid$(Date$, n, n), where n is the position of the letter C.

  14. jonas November 17th, 2009 11:33 am

    Would something like this not work?

    PRINT LEFT$(MKI$(67*257),1)

  15. jonas February 21st, 2010 3:06 am

    To Erik Petrich: I think PRINT SQR(-1) may work even if the basic prints full error messages, as the message in some basics is “Illegal function call”, not “Illegal quantity”. If it doesn’t, there are other error messages with “c” you can generate easily: PRINT A(999) should give a “Subscript out of range” or “Bad subscript”; PRINT 1+”A” a “Type mismatch”; and although it only works when typed directly, not from a program, CONT without running a program should give “Can’t continue”. (In addittion, some basics already print a letter “c” in their startup message, eg. “**** COMMODORE 64 BASIC V2 **** 64K RAM SYSTEM 38911 BASIC BYTES FREE”)

  16. Steve February 21st, 2010 8:32 am

    Haha, you guys are far too clever! I should have stipulated that I was looking for a way to print “C” procedurally, so it could just as easily print “CCCC” or “calculation cache” if needed. Forcing an error message with a C in it doesn’t help.

  17. helios July 29th, 2010 1:09 pm

    Technically…

    10 PRINT “01000011″

    You never said it could be the binary equivalent of “C”. :-D

  18. PC Fórum October 20th, 2010 8:36 pm

    Építsen saját processzort, házilag!…

    Egy kaliforniai férfi másfél éves munkával és mindössze ezer dollárnyi költséggel saját processzort épített…

  19. videoklipler November 18th, 2010 7:34 am

    :D you are so clever what is that man :D have a nice day by videoklip izle,dailymotion videoları izle

  20. ivan November 19th, 2010 2:21 am

    Ну блин! Обидели парня! он тепрь проект закрыл.Но похоже, это правда , он действительно скопировал отечественное изделие…
    Так что Русские и по компам рулят! А современные IBM PC это клон компьютера СССР – Вектор. Ну немного усовершенствовано.

  21. Donn Lee April 6th, 2011 10:38 pm

    I met you and BMOW at Maker Faire in San Mateo. It was a real highlight of the show for me. Kinda sad to hear it has been retired, however it had a great run and could be ‘on tour’ again one day. Thanks for showing us such a cool project!

  22. makerimages June 13th, 2013 10:14 pm

    Where would one have to start from to build a machine like this over the summer? I guess I`d have to design the instruction set off of assembler at the beginning and then plan the hardware.

  23. Makerimages July 8th, 2013 11:44 pm

    Dear Steve,

    I have recently begun to think about constructing something like this myself. Do you happen to have any of bmow’s original design docs I could study? Or, do you have any recommendations for online tutorials/books on this topic?mostly, I am going to need to learn about the program interpretation and the overall operation of the device on a logic level.

    Please respond.

  24. Steve Chamberlin July 9th, 2013 8:17 am

    Makerimages, the BMOW design docs and files are in the “BMOW 1″ section under Product Summaries at the top-left of the page. A textbook like Hennessy and Patterson may also be helpful if you’re new to the concepts of computer architecture: http://www.amazon.com/books/dp/0123704901

  25. Steve Chamberlin July 9th, 2013 8:18 am

    You can also contact me at steve@bigmessowires.com with any other specific questions.

  26. Makerimages July 9th, 2013 10:51 am

    Thank you, for some odd reason, I had always clicked the BMOW1 under categories…(Maybe you should rename the Project summaries to, lets say-Downloadable information or something)

  27. Makerimages July 9th, 2013 10:56 am

    And just out of interest- would BMOW still run today, if you were to boot it up?

  28. Steve Chamberlin July 11th, 2013 6:23 am

    Yes, I booted it up a few months ago for some reason. It still works just fine!

  29. Makerimages July 11th, 2013 9:43 am

    Then maybe-improve it?

  30. Makerimages July 11th, 2013 9:46 am

    Darn me, I cant fit all the things into one comment…

    Anyways, I was able to grab a hold of the 5th editio of the book you gave me a link to(dont ask how I did it) , is it good aswell, or had the 4th edition something special in it for a project like this?

    Do you know anywhere one could buy the HM6116 series SRAM chips?

  31. Helder Novais September 18th, 2014 8:27 am

    Too bad it ended. Very interesting project.
    I doubt I could do nearly the same :(

Leave a reply. Comments may take a few minutes to appear.