My drawing language developed at age 9

The Brand language created by Seymour Papert in 1967 was fairly well-known within the eighties as a software to show programming to children. Now in 2024, I can see it was nice to make good drawings on the display and study trigonometry, and a few very lucky children had an actual robotic turtle drawing on paper, however it wasn’t so good for instructing programming as a result of no house pc got here with Brand, it was costly, and its implementations differed drastically of their assist of necessary programming constructs.
Anyway, I used to be in love with Brand, and being the daring child I used to be, I made a decision to make a Brand language for the coed’s pc developed by my father, and I might code it in Z80 machine code at age 9. Moreover, I might have forgotten this utterly if it wasn’t as a result of the handwritten program was saved away within the class folder that my father nonetheless saved and I discovered the pages the final Sunday, March 10, 2024, virtually 36 years later. I virtually could not consider it!
These are photos of the three pages composing this system. You’ll be able to see the machine code is considerably readable as a result of every instruction is separated. The ultimate web page comprises the guide!
LOCS means Lenguaje de Oscar Computadora eStudiantil (or Oscar’s language for college students’ computer systems). OTEK comes from my father’s initials (Oscar Toledo Esteva) which we used as a sort of firm identify.
My language instructions are fairly easy: BORRA clears the display, TORTUGA facilities the “turtle”, there are 4 instructions to attract (SM up, AM down, DM proper, IM left), and eventually we now have the PT command (Pone Tortuga) to position the turtle anyplace on the display.
Making it to work
This program relies upon closely on having a keyboard, so this time I gained’t port it to Colecovision to avoid wasting me time. I might assign a perform to every key within the keypad however it might require an enormous code chunk and I might find yourself rewriting this system utterly.
Anyway, right here we go analyzing it. We’ll begin by getting ready a easy MSX translation layer.
; ; LOCS ; ; by Oscar Toledo G. ; (c) Copyright 1988 Oscar Toledo G. ; ; Creation date: Sep/09/1988. I used to be age 9. ; ; ; Layer to adapt it to MSX computer systems. ; WRTVDP: EQU $0047 ; Set VDP handle HL. WRTVRM: EQU $004D ; Write byte A to VRAM handle HL. FILVRM: EQU $0056 ; Fill VRAM handle HL with A repeated BC occasions. SETWRT: EQU $0053 ; Set write handle HL for VDP. CHGET: EQU $009F ; Learn character from keyboard into A. VDP: EQU $98 ; Base VDP port. ; MSX Cartridge header ORG $4000 DB "AB" DW START DW 0 DW 0 DW 0 DW 0 ; ; Set a VDP handle to put in writing. ; L0100: JP SETWRT ; ; Copy rapid knowledge to VRAM. ; L0169: EX (SP),HL .1: LD A,(HL) OR A JR Z,.2 OUT (VDP),a INC HL JR .1 .2: EX (SP),HL RET ; ; Clear the display. ; Set display buffer to VRAM $3c00. ; L04CC: LD BC,$0F02 ; VDP register 2 = $3c00. CALL WRTVDP LD HL,$3C00 ; Clear the display. LD BC,$0300 ; 32x24 grid. LD A,$20 ; Area character. JP FILVRM ; Fill VRAM. ; ; Learn the keyboard. ; L04F5: CALL CHGET ; Learn keyboard. CP $61 ; Is it lowercase? RET C CP $7B RET NC ; No, return. SUB $20 ; Sure, make it uppercase. RET ; ; Learn a hexadecimal quantity in HL. ; READ_WORD: CALL READ_BYTE ; Learn a byte. READ_BYTE: CALL READ_HEX ; Learn a hexadecimal digit. READ_HEX: CALL L04F5 ; Learn the keyboard. PUSH HL LD HL,(L87F0) ; Get cursor handle. CALL WRTVRM ; Show key on the display. INC HL LD (L87F0),HL ; Replace cursor handle. POP HL SUB $30 ; Convert ASCII 0-9 to 0-9. CP $0A JR C,.1 SUB $07 ; Convert ASCII A-F to 10-15. .1: ADD HL,HL ; Shift HL to the left 4 bits. ADD HL,HL ADD HL,HL ADD HL,HL OR L ; Add hexadecimal digit. LD L,A RET
This program calls the ROM of the educative pc. It makes use of 5 capabilities:
- L0100, Set VDP handle.
- L0169, Copy a message to VRAM.
- L04CC, Clear the display.
- L04F5, Learn the keyboard.
- RST $10, Learn a hexadecimal quantity into HL (4 digits).
It relies upon additionally on the display grid to be obtainable on the VRAM handle $3c00 (the MSX default is $1800) so in my translation layer for L04CC it writes the VDP register 2 to vary it.
This system begins like this:
START: LD SP,L87F0 CALL L8114 CALL L0100 CALL L0169 DB "LOCS OTEK",0 IF 0 LD HL,$3C41 CALL L0100 CALL L0169 DB "32 BYTES",0 ELSE DB 0,0,0 DB 0,0,0 DB 0,0,0 DB 0,0,0,0 DB 0,0,0,0 DB 0 ENDIF
It units the stack pointer on the preliminary handle for the 2K RAM college students pc, and instantly the code is patched earlier than exhibiting this system title.
L8114: CALL L8075 LD HL,$3C01 RET L8075: LD HL,$3D50 LD (L86F0),HL CALL L04CC RET
The patch units the “turtle” place to $3D50 (the middle of the display), this place is saved within the L86F0 handle, then it clears the display calling L04CC, after which hundreds HL with $3C01 to level to the highest left of the display. Discover it is not precisely $3C00 however $3c01 as a result of my Sony Trinitron TV of the time “ate” the primary column.
It took me most likely half an hour to find what I patched with tons of handwritten zero bytes (NOP directions), and it was merely an additional message saying “32 BYTES”. I feel that Dr. Brand confirmed the overall bytes obtainable for this system, and I feel that saying 32 bytes was my joke as a result of there is not such factor as a reminiscence supervisor.
L8028: CALL L81C1 CALL L807F CALL L0169 DB "GRAFICO",0 LD HL,$3EE1 CALL L8063 LD A,$3E OUT (VDP),A LD (L86F2),HL LD DE,L8700 L8049: CALL L04F5 LD (DE),A INC DE CP $0D JR Z,L8068 LD HL,(L86F2) PUSH AF CALL L0100 POP AF OUT (VDP),A INC HL LD (L86F2),HL JP L8049 L8063: CALL L0100 INC HL RET L807F: PUSH HL LD HL,(L86F0) CALL L0100 LD A,$2A OUT (VDP),A POP HL CALL L0100 RET L81C1: LD HL,$0118 ; Redefine the # character CALL L0100 ; as a strong block. LD B,$08 L81C9: LD A,$FF OUT (VDP),A DJNZ L81C9 L81CF: LD HL,$0918 CALL L0100 LD B,$08 L81D7: LD A,$FF OUT (VDP),A DJNZ L81D7 LD HL,$1118 CALL L0100 LD B,$08 L81E5: LD A,$FF OUT (VDP),A DJNZ L81E5 LD HL,$3EC1 ; Level to command space. RET
The principle loop begins by calling L81C1, clearly a patch, as a result of it ends setting HL to $3EC1 (the command space on the display), however first it redefines the # character to be a strong block. The redefinition is finished in three areas of VRAM as a result of the educative pc was hardcoded to VDP mode 2, however the MSX begins in mode 0, so solely the primary loop is critical however I saved all of it.
The subsequent name jumps to L807F to attract the “turtle” within the present place. An asterisk, I am stunned I did not even attempt to attract a turtle. On the finish of the L807F it calls L0100 to level to the VRAM handle for the command space.
Now it exhibits a “GRAFICO” message (akin to a READY message), and within the subsequent row ($3EE1 in VRAM) it places a > signal to attend for the keyboard. Discover the L8063 patch as a result of I could not match an INC HL to avoid wasting the present handle in VRAM at L86F2.
There isn’t any cursor, it merely waits for the keyboard and shows the typed key on the display (L86F2 comprises the present handle in VRAM), and saves the important thing additionally within the RAM buffer situated at L8700. I’ve moved early the CP $0D comparability ready for the Enter key, so it does not present trash in MSX, as a result of within the educative pc that character wasn’t outlined so when displayed it was invisible.
It does not deal with the backspace key, so you must assume earlier than typing something.
In your command
At this level, it begins processing the language instructions:
L8068: LD A,(L8700) CP $42 JR NZ,L808F CALL L04CC JP L8028
The primary carried out command is “BORRA”, however on the time I did not know the right way to evaluate entire phrases, so it merely checks for the primary letter “B” (ASCII $42), calls L04CC and jumps again to L8028.
L808F: CP $54 JR NZ,L80BF LD HL,(L86F0) CALL L0100 LD A,$20 OUT (VDP),A LD HL,$3D50 LD (L86F0),HL CALL L0100 LD A,$2A OUT (VDP),A CALL L80B0 JP L8028 L80B0: LD HL,$3EC1 L80B3: CALL L0100 LD B,$40 L80B8: LD A,$20 OUT (VDP),A DJNZ L80B8 RET
The second command is “TORTUGA” (T). It merely will get the present place of the turtle, places an area character to erase it, facilities it once more on the display, and attracts it once more. Apparently I forgot I had a turtle drawing subroutine at L807F, or that the L8028 bounce already attracts the turtle.
L80BF: CP $53 JR NZ,L80E6 LD A,(L8700+3) SUB $30 LD B,A L80C9: LD HL,(L86F0) CALL L0100 LD A,$23 OUT (VDP),A LD DE,$0020 SBC HL,DE LD (L86F0),HL DJNZ L80C9 CALL L80B0 CALL L807F JP L8028
The third command is “SM” (S). It expects the size within the fourth byte as a digit, so you should sort precisely SM adopted by an area and the digit.
It converts the digit to a price between 0-9 and saves it into B as counter. It takes the present place of the turtle and attracts a block, displaces the pointer, and repeats. It ends clearing the command space, redrawing the turtle, and leaping again to the principle loop.
Discover it by no means validates the size, zero will draw 256 blocks.
Did I say block? Proper, I did not know something about pixels, so when you do not have pixels, you’ve got blocks, proper? A really daring child.
L80E6: CP $44 JR NZ,L811B LD A,(L8700+3) SUB $30 LD B,A L80F0: LD HL,(L86F0) CALL L0100 LD A,$23 OUT (VDP),A LD DE,$0001 ADD HL,DE NOP LD (L86F0),HL DJNZ L80F0 CALL L80B0 CALL L807F JP L8028
The fourth command is “DM” (D). It’s precisely the identical code, I solely modified the displacement offset to go the precise.
L811B: CP $41 JR NZ,L8142 LD A,(L8700+3) SUB $30 LD B,A L8125: LD HL,(L86F0) CALL L0100 LD A,$23 OUT (VDP),A LD DE,$0020 ADD HL,DE NOP LD (L86F0),HL DJNZ L8125 CALL L80B0 CALL L807F JP L8028 L8142: CP $49 JR NZ,L8169 LD A,(L8700+3) SUB $30 LD B,A L814C: LD HL,(L86F0) CALL L0100 LD A,$23 OUT (VDP),A LD DE,$0001 SBC HL,DE LD (L86F0),HL DJNZ L814C CALL L80B0 CALL L807F JP L8028
The fifth command is “AM” (A) for taking place, and the sixth command “IM” (I) for going to left. Once more, I solely modified the displacement offsets. I might have saved tons of bytes by having a generic drawing subroutine the place you can present an offset, however I used to be nonetheless studying, and doubtless afraid of juggling with registers.
L8169: CP $50 JR NZ,L8194-1 LD HL,$3EE5 LD (L87F0),HL CALL READ_WORD ; Modified from RST $10 LD D,H LD E,L LD HL,(L86F0) CALL L0100 LD A,$20 OUT (VDP),A LD HL,$3C00 ADD HL,DE LD (L86F0),HL CALL L0100 LD A,$2A OUT (VDP),A CALL L80B0 JP L8028
The seventh command is “PT”. It units a place for the inner cursor by studying a hexadecimal phrase into HL that’s saved instantly into DE. It deletes the turtle from the display, and repositions it on the DE place added $3c00 to place it into the precise VRAM handle. Nearly the identical code because the TORTUGA command, and once more I forgot I had a turtle redraw subroutine.
By the way in which, there’s a tiny bug right here. Within the machine code I calculated wrongly the relative bounce JR NZ and it jumps one byte earlier than the precise handle, because the opcode $81 is an ADD instruction, it does not have an effect on and it really works good ($41 in MSX, LD B,C)
L8194: LD HL,$3C01 CALL L0100 CALL L0169 DB "* ERROR *",0 LD B,$05 L81A9: PUSH BC LD BC,$0000 L81AD: DEC BC LD A,B OR C JR NZ,L81AD POP BC DJNZ L81A9 LD HL,$3C00 CALL L80B3 CALL L80B0 JP L8028
Lastly, my LOCS program ends with an error message for an unrecognized command. It does an enormous delay, erases it, and returns to the principle loop.
I’ve made a tiny video exhibiting my LOCS program in motion.
Downloads
You’ll be able to obtain the unique LOCS program (495 bytes), and the MSX tailored model (589 bytes with the interpretation layer), together with the unique assembler code for each.
- Obtain locs.zip (4.33 kb) containing assembler supply code and binaries.
Epilogue
To be a whole language it might want variables, expressions, and at the very least a conditional loop. However does not matter, HTML is known as a language and does not have this!
I did not perceive precisely how angles labored on the time so there are none in any respect in my program. The usage of blocks as an alternative of pixels was loopy, additionally the dearth of validation of the consumer’s typing, however I can perceive I used to be fairly enthusiastic (detecting instructions with one single letter!) and I empirically found the precept of “it’s higher to have it working than having nothing”.
Associated hyperlinks
Final modified: Mar/12/2024