Repository: nanochess/bootLogo Branch: master Commit: e3ce458a6d4e Files: 8 Total size: 18.7 KB Directory structure: gitextract_abq_j2r6/ ├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── bootlogo.asm ├── bootlogo.com ├── bootlogo.img └── e.bat ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ .DS_Store ================================================ FILE: LICENSE ================================================ bootLogo - Small Logo language in a boot sector. Copyright (c) 2024 Oscar Toledo G. http://nanochess.org/ All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================ FILE: Makefile ================================================ # Makefile contributed by jtsiomb src = bootlogo.asm .PHONY: all all: bootlogo.img bootlogo.com bootlogo.img: $(src) nasm -f bin -o $@ $(src) bootlogo.com: $(src) nasm -f bin -o $@ -Dcom_file=1 $(src) .PHONY: clean clean: $(RM) bootlogo.img bootlogo.com .PHONY: rundosbox rundosbox: bootlogo.com dosbox $< .PHONY: runqemu runqemu: bootlogo.img qemu-system-i386 -fda bootlogo.img ================================================ FILE: README.md ================================================ _ _ _ | | | | | | | |__ ___ ___ | |_| | ___ __ _ ___ | '_ \ / _ \ / _ \| __| | / _ \ / _` |/ _ \ | |_) | (_) | (_) | |_| |___| (_) | (_| | (_) | |_.__/ \___/ \___/ \__\_____/\___/ \__, |\___/ __/ | |___/ ### bootLogo interpreter in 512 bytes (boot sector or COM file) *by Oscar Toledo G. Mar/18/2024* http://nanochess.org https://github.com/nanochess This is a small interpreter of Logo language. It's compatible with the 8088 processor (the original IBM PC), and it even works on CGA mode! If you want to assemble it, you must download the Netwide Assembler (NASM) from www.nasm.us Use this command line: nasm -f bin bootlogo.asm -Dcom_file=1 -o bootlogo.com nasm -f bin bootlogo.asm -Dcom_file=0 -o bootlogo.img Tested with VirtualBox for macOS running Windows XP running this interpreter, it also works with DOSBox and probably with QEMU: qemu-system-x86_64 -fda bootlogo.img You can set also the following labels: * video_mode. This sets the video mode used for bootLogo (default = 4 for CGA mode 320x200x4 colors). A good alternative is 13 (EGA/VGA 320x200x16 mode). * color1. This sets the color for the letters in the command line (default = 1 for CGA mode) * color2. This sets the color for line drawing (default = 3 for CGA mode) Enjoy it! ## User's manual Line entry is done with the keyboard, finish the line with Enter. Backspace can be used to correct mistakes. The following commands are implemented: ### CLEARSCREEN Clears the screen and returns the turtle to the center, and pointing to the north. This command can only be used alone. ### FD 40 Move the turtle 40 pixels ahead. Caveat: If you use zero, it will be taken as 65536 pixels. ### BK 40 Move the turtle 40 pixels backward. Caveat: If you use zero, it will be taken as 65536 pixels. ### RT 25 Rotate the turtle 25 degrees clockwise. ### LT 25 Rotate the turtle 25 degrees counterclockwise. ### REPEAT 10 FD 10 Repeat 10 times FD 10 ### REPEAT 10 [FD 10 RT 20] Repeat 10 times FD 10 RT 20. REPEAT can be nested. If you somehow miss the final ] character then bootLogo will crash. ### PU Pen up. The turtle doesn't draw for following commands. ### PD Pen down. The turtle draws again. ### SETCOLOR 2 Set color for pen. Only 0-3 available in CGA, and 0-15 for EGA/VGA. ### TO [name] [command or list of commands] END This command allows you to define procedures. All the definition should fit inside one line (120 characters). A single command could be a REPEAT. Several commands can be grouped using [ and ]. Only the two first letters of the name are taken in account. The predefined commands have priority (so you cannot define them out). Also, once defined a procedure, it cannot be edited again (sorry, lack of space). For example: TO CURVE REPEAT 4 [LT 10 FD 10] END TO PETAL [CURVE LT 140 CURVE] END TO FLOWER REPEAT 4 [PETAL LT 50] END FLOWER RT 180 FD 50 RT 140 PETAL PU FD 50 ### QUIT Exit to command line (only .COM version) ## Examples ![bootLogo command sequence](example3.png) ![Result of bootLogo command sequence](example4.png) ## Acknowledgments * jcmeyrignac for an idea to make smaller the number decoding. * Jim Leonard (MobyGamer) for making me thinking about a higher-precision sin function, and suggesting me the use of the Set Pixel BIOS service. * raulamd for reminding me that cubicDoom had a smaller sin function. ## More on this? Do you want to learn 8086/8088 assembler? Get my book Programming Boot Sector Games containing an 8086/8088 crash course! Now available from Lulu: [Paperback book](http://www.lulu.com/shop/oscar-toledo-gutierrez/programming-boot-sector-games/paperback/product-24188564.html) [Hard-cover book](http://www.lulu.com/shop/oscar-toledo-gutierrez/programming-boot-sector-games/hardcover/product-24188530.html) [eBook](https://nanochess.org/store.html) These are some of the example programs documented profusely in the book: * Guess the number. * Tic-Tac-Toe game. * Text graphics. * Mandelbrot set. * F-Bird game. * Invaders game. * Pillman game. * Toledo Atomchess. * bootBASIC language. ================================================ FILE: bootlogo.asm ================================================ ; ; bootLogo: A Logo implementation in a boot sector. ; ; by Oscar Toledo G. ; https://nanochess.org/ ; ; (c) Copyright 2024 Oscar Toledo G. ; ; Creation date: Mar/18/2024 5:40pm. ; Revision date: Mar/18/2024 8:22pm. Working base commands. ; Revision date: Mar/18/2024 10:13pm. Working REPEAT command. ; Revision date: Mar/19/2024. Optimized number decoding. Optimized sin function ; and now it has 7-bit precision. Used extra bytes ; for PU/PD commands. ; cpu 8086 ; ; bootLogo is an implementation of the basics of the Logo language. ; ; You have the following commands: ; ; CLEARSCREEN Clears the screen (only can be used alone) ; FD 40 Move the turtle 40 pixels ahead ; BK 40 Move the turtle 40 pixels backward. ; RT 25 Rotate the turtle 25 degrees clockwise. ; LT 25 Rotate the turtle 25 degrees counterclockwise. ; REPEAT 10 FD 10 Repeat 10 times FD 10 ; REPEAT 10 [FD 10 RT 20] Repeat 10 times FD 10 RT 20. ; Repeat can be nested. ; PU Pen up (turtle doesn't draw). ; PD Pen down (turtle draws). ; SETCOLOR 1 Set color for pen. ; TO name def END Defines a procedure "name" with definition "def" ; "def" can be any single command, or a list of ; commands between [ and ]. ; QUIT Exit to command line (only .COM version) ; %ifndef com_file com_file: equ 0 %endif %ifndef video_mode video_mode: equ 4 ; CGA 320x200x4 colors. %endif %ifndef color1 color1: equ 1 ; Color for command line. %endif %ifndef color2 color2: equ 3 ; Color for drawing. %endif %if com_file org 0x0100 %else org 0x7c00 %endif ; ; Variables are saved just after the program. ; ANGLE: equ $+0x0400 ; Current angle of the turtle. X_COOR: equ $+0x0402 ; Current fractional X-coordinate (9.7) Y_COOR: equ $+0x0404 ; Current fractional Y-coordinate (9.7) PEN: equ $+0x0406 ; Current pen state. NEXT: equ $+0x0407 PROCS: equ $+0x0409 ; Procedures. BUFFER: equ $+0x0300 ; Buffer for commands. FRACTION_BITS: equ 7 ; How many bits has the fraction. UNIT: equ 0x01<' ; Show prompt character. input_loop: mov dx,di ; Get column. jmp input_loop3 input_loop2: mov al,' ' ; Erase previous character with a space. mov dx,di ; Point to previous character. dec di ; Buffer pointer gets back. input_loop3: call set_cursor ; CH is zero from here. mov cl,1 ; One character. int 0x10 ; Call BIOS. mov ah,0x00 ; Wait for key function. int 0x16 ; Call BIOS. cmp al,0x08 ; Backspace? jz input_loop2 ; Yes, jump. cmp al,'a' ; Is it lowercase? jb .1 cmp al,'z'+1 jnb .1 ; No, jump. sub al,0x20 ; Convert to uppercase. .1: stosb ; Save into buffer. cmp al,0x0d ; Is it Enter? jne input_loop ; No, jump to wait for more keys. call xor_turtle ; Remove turtle (2nd XOR) pop si ; SI points to start of the command buffer. ; ; Run commands alone or in a list. ; run_commands: call avoid_spaces ; Avoid spaces. cmp al,'[' ; Is it a list of commands? jne run_command ; No, jump to process a single command. inc si ; Avoid list character '['. .1: call run_command ; Run a single command. call avoid_spaces ; Avoid spaces. cmp al,']' ; Is it end of list? jne .1 ; No, keep reading commands. inc si ; Avoid list character ']'. ret ; ; Run a command. ; SI = Pointer to current position in buffer. ; run_command: call avoid_spaces ; ; Search for builtin commands. ; mov di,commands ; DI points to command list. mov cx,11 ; Eleven commands. lodsw ; Read command to execute. .1: scasw ; Compare with command from table. jz found ; Jump if same. scasb ; Avoid command address. loop .1 ; ; Search for defined procedures. ; mov di,PROCS-PROC_SIZE .7: lea di,[di+PROC_SIZE] ; Go to next procedure. cmp di,[NEXT] ; End of defined procedures? je avoid_command ; Yes, jump. scasw ; Compare against procedure name. jnz .7 ; Jump if not the same. push si mov si,di ; Use definition as source pointer. call run_commands ; Run command or commands. pop si ; ; Avoid extra letters of command. ; avoid_command: lodsb ; Read a character. sub al,0x41 ; Make 'A'-'Z' to be 0-25. cmp al,0x1a ; Is it a letter? jb avoid_command ; Yes, jump. dec si ; Get back to the right point. ; ; Avoid spaces. ; avoid_spaces: lodsb ; Read a character. cmp al,0x20 ; Is it space? je avoid_spaces ; Yes, jump. dec si ; Get back to the right point. ret ; ; Command found. ; found: call avoid_command xor cx,cx ; Set number to zero. .3: lodsb ; Get a character. sub al,'0' ; Is it a number? cmp al,10 jnb .5 ; No, jump. cbw ; Extend digit 0-9 in AL to AX. push ax ; AH guaranteed to be zero. mov al,10 ; CX = CX * 10 + digit mul cx pop cx add cx,ax jmp short .3 ; Keep reading number. .5: dec si ; >>> This depends on all commands and command table located ; inside the same 256-byte page <<< push di pop ax ; To get high byte of address. add al,[di] ; Get location (low byte). jmp ax ; ; Set cursor position. ; DL = column (0-255). ; set_cursor: mov cx,40 ; 40 columns. .1: sub dl,cl ; Limit column to range 0-39. jnb .1 add dl,cl mov dh,21 ; Row 21 of the screen. mov bx,color1 ; Page (bh) and color (bl). mov ah,0x02 ; Set video row, column function. int 0x10 ; Call BIOS. mov ah,0x09 ret ; ; Limit the angle to 0-359 and then to the size of the sin table. ; limit: mov bx,360 ; 360 degrees is the limit. cwd ; Sign extend AX to DX:AX idiv bx ; Limit it to 360 degrees... or dx,dx ; ...by getting modulo. jns .1 add dx,bx ; Make modulo positive. .1: mov ax,128 ; Multiply by sin table length. mul dx div bx ; Divide by 360 degrees. ; Now AX is between 0 and 127. ; (this means AH is zero) ; ; Get sine ; test al,64 ; Angle >= 180 degrees? pushf test al,32 ; Angle 90-179 or 270-359 degrees? je .2 xor al,31 ; Invert bits (reduces table) .2: and al,31 ; Only 90 degrees in table mov bx,sin_table xlat ; Get fraction popf je .3 ; Jump if angle less than 180 neg ax ; Else negate result .3: ret ; Return. ; ; XOR turtle against the background. ; xor_turtle: push word [X_COOR] ; Save X-coordinate. push word [Y_COOR] ; Save Y-coordinate. mov cl,5 ; 5 pixels (depends on CH being zero). xor ax,ax .1: call advance ; Advance to get turtle nose. loop .1 ; Until reaching 5 pixels. ; ch guaranteed to be zero here. mov si,turtle_angles ; Table to draw the turtle. lodsb ; Get angle for this line. .2: mov cl,5 mul cl .3: mov bx,0x0080 ; XOR pixel. call draw_pixel2 ; Draw in X,Y coordinates. loop .3 ; Loop to draw the line. lodsb ; Get angle for next line. test al,al ; Is it zero? jnz .2 .4: pop word [Y_COOR] ; Restore Y-coordinate. pop word [X_COOR] ; Restore X-coordinate. ret ; Return. commands: db "CL" db command_clearscreen-$ db "FD" db command_fd-$ db "BK" db command_bk-$ db "RT" db command_rt-$ db "LT" db command_lt-$ db "RE" db command_repeat-$ db "PU" db command_pu-$ db "PD" db command_pd-$ db "SE" db command_setcolor-$ db "TO" db command_to-$ db "QU" db command_quit-$ ; ; CLEARSCREEN command ; command_clearscreen: mov ax,video_mode int 0x10 ; Set video mode. mov di,ANGLE ; Point to ANGLE variable. xor ax,ax ; Zero (north) stosw ; Store word. mov ah,UNIT*160/256 ; Initial X-coordinate. stosw ; Store word. mov ah,UNIT*100/256 ; Initial Y-coordinate. stosw ; Store word. inc ax ; Pen down. stosb ; Store byte. ret repeat_loop: pop si ; Restore start position to re-parse. ; ; REPEAT command ; command_repeat: push si ; Save position in buffer. push cx ; Save repeat count. call run_commands pop cx ; Restore count. loop repeat_loop pop di ; Ignore start position, keep advanced position. ret ; ; TO command ; command_to: mov di,[NEXT] ; Pointer to space for next procedure. movsw ; Copy procedure name (only 2 letters) call avoid_command ; Avoid extra letters. mov cx,PROC_SIZE rep movsb ; Copy procedure body. mov [NEXT],di ; Update pointer. ret ; ; BK command. ; command_bk: mov ax,-180 ; Reverse direction (-180 degrees) db 0xba ; mov dx, to jump following instruction. ; ; FD command. ; command_fd: xor ax,ax ; Normal direction. ; ; Set pixel. ; pixel_set: call draw_pixel ; Draw in X,Y coordinates. loop pixel_set ret ; ; LT command. ; command_lt: neg cx ; Negate angle. ; ; RT command. ; command_rt: add [ANGLE],cx ; Rotate turtle clockwise. ret ; Return. ; ; PU command ; command_pu: mov al,0 ; Pen up. db 0xba ; MOV DX to jump over following instruction ; ; PD command ; command_pd: mov al,1 ; Pen down. mov [PEN],al ; Set pen status. ret ; Return. ; ; SETCOLOR command ; command_setcolor: mov [COLOR],cl ; Save new pen color. ret ; Return. ; ; QU command. ; command_quit: int 0x20 ; Exit to DOS or bootOS. ; ; Draw pixel in current X,Y integer coordinates. ; draw_pixel: test byte [PEN],0x01 jz draw_pixel3 xor bx,bx ; Set pixel. draw_pixel2: push ax push cx mov cl,FRACTION_BITS mov ax,[X_COOR] ; Get X-coordinate. shr ax,cl ; Remove fractional part. mov dx,[Y_COOR] ; Get Y-coordinate. shr dx,cl ; Remove fractional part. xchg ax,cx COLOR: equ $+1 ; Self-modifying code. mov ax,0x0c00+color2 ; Color for pen plus Set Pixel function code. or al,bl ; ...plus mode (SET or XOR). int 0x10 pop cx pop ax draw_pixel3: ; ; Advance turtle in direction. ; ax = Offset in degrees for angle. ; advance: push ax add ax,[ANGLE] ; Add current angle to offset in ax. push ax call limit ; Limit angle and get sin. add [X_COOR],ax ; Add to X-coordinate. pop ax add ax,90 ; For getting cos. call limit sub [Y_COOR],ax ; Subtract to Y-coordinate. pop ax ret ; ; Shape for the turtle. ; It draws 5 pixels in each of the following relative angles. ; turtle_angles: db 210/5 db 210/5 db 70/5 db 110/5 db 330/5 db 330/5 ; ; Table ending marked by a zero byte taken from the start of sin_table. ; ; ; sin() function table ; It must follow FRACTION_BITS. ; sin_table: db 0x00, 0x06, 0x0d, 0x13, 0x19, 0x1f, 0x25, 0x2b db 0x31, 0x37, 0x3c, 0x42, 0x47, 0x4c, 0x51, 0x56 db 0x5b, 0x5f, 0x63, 0x67, 0x6a, 0x6e, 0x71, 0x74 db 0x76, 0x79, 0x7a, 0x7c, 0x7e, 0x7f, 0x7f, 0x80 %if com_file %else times 510-($-$$) db 0xff db 0x55,0xaa ; Make it a bootable sector %endif ================================================ FILE: e.bat ================================================ nasm -f bin bootlogo.asm -l bootlogo.lst -o bootlogo.img nasm -f bin bootlogo.asm -Dcom_file=1 -o bootlogo.com