├── README.TXT ├── README.md ├── build-linux.sh ├── build-openbsd.sh ├── build-osx.sh ├── buildwin.bat ├── disk_images ├── README.TXT ├── mikeos.dmg ├── mikeos.flp └── mikeos.iso ├── doc ├── CHANGES.TXT ├── CREDITS.TXT ├── LICENSE.TXT ├── handbook-appdev-asm.html ├── handbook-appdev-basic.html ├── handbook-sysdev.html └── handbook-user.html ├── programs ├── advnture.bas ├── archive.bas ├── calc.bas ├── cf.bas ├── draw.bas ├── edit.asm ├── edit.bin ├── example.bas ├── fileman.asm ├── fileman.bin ├── fisher.asm ├── fisher.bin ├── forth.asm ├── forth.bin ├── hangman.asm ├── hangman.bin ├── keyboard.asm ├── keyboard.bin ├── mbpp.bas ├── memedit.bas ├── mikedev.inc ├── monitor.asm ├── monitor.bin ├── muncher.bas ├── sample.pcx ├── serial.asm ├── serial.bin ├── sudoku.bas ├── viewer.asm └── viewer.bin ├── source ├── bootload │ ├── bootload.asm │ └── bootload.bin ├── features │ ├── basic.asm │ ├── cli.asm │ ├── disk.asm │ ├── keyboard.asm │ ├── math.asm │ ├── misc.asm │ ├── ports.asm │ ├── screen.asm │ ├── sound.asm │ └── string.asm ├── kernel.asm └── kernel.bin └── test-linux.sh /README.TXT: -------------------------------------------------------------------------------- 1 | ================================================================== 2 | MikeOS -- Open source 16-bit operating system for x86 PCs 3 | Copyright (C) 2006 - 2014 MikeOS Developers -- see doc/LICENSE.TXT 4 | ================================================================== 5 | 6 | 7 | MikeOS is a 16-bit real mode operating system for x86-compatible PCs, 8 | written entirely in assembly language, which boots from a floppy disk, 9 | CD-ROM or USB key. It features a text-based dialog-driven user 10 | interface, a command-line, support for FAT12 (MS-DOS-like) floppy 11 | disks, sound (PC speaker), text editor, BASIC interpreter and more. 12 | The kernel includes over 60 system calls. 13 | 14 | MikeOS is a learning tool for those wishing to understand simple OS 15 | construction and x86 assembly. Quick getting-started guide: MikeOS can 16 | run from a floppy disk or CD-ROM, either on an emulator or a real PC. 17 | See the disk_images/ directory for files that you can write to the 18 | appropriate media or boot in, for instance, VMware, QEMU or VirtualBox. 19 | 20 | You can find the source code in the source/ directory, and sample 21 | programs (included on the disk images) in the programs/ directory. 22 | See the doc/ directory for more info, including: 23 | 24 | # handbook-user.html -- How to run and use MikeOS 25 | 26 | # handbook-appdev-basic.html -- Writing software in BASIC 27 | # handbook-appdev-asm.html -- Writing software in assembly 28 | # handbook-sysdev.html -- Building and modifying the OS 29 | 30 | # LICENSE.TXT -- The open source, BSD-like license 31 | # CHANGES.TXT -- Detailed list of changes in previous releases 32 | # CREDITS.TXT -- People involved in the project 33 | 34 | Have fun, and see the website at http://mikeos.sourceforge.net 35 | 36 | -- Mike Saunders (okachi@gmail.com) 37 | 38 | 39 | ================================================================== 40 | 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | MikeOS 2 | ====== 3 | 4 | Open source 16-bit operating system for x86 PCs 5 | ----------------------------------------------- 6 | 7 | ``` 8 | Copyright (C) 2006 - 2014 MikeOS Developers -- see doc/LICENSE.TXT 9 | ``` 10 | 11 | MikeOS is a 16-bit real mode operating system for x86-compatible PCs, 12 | written entirely in assembly language, which boots from a floppy disk, 13 | CD-ROM or USB key. It features a text-based dialog-driven user 14 | interface, a command-line, support for FAT12 (MS-DOS-like) floppy 15 | disks, sound (PC speaker), text editor, BASIC interpreter and more. 16 | The kernel includes over 60 system calls. 17 | 18 | MikeOS is a learning tool for those wishing to understand simple OS 19 | construction and x86 assembly. Quick getting-started guide: MikeOS can 20 | run from a floppy disk or CD-ROM, either on an emulator or a real PC. 21 | See the disk_images/ directory for files that you can write to the 22 | appropriate media or boot in, for instance, VMware, QEMU or VirtualBox. 23 | 24 | You can find the source code in the source/ directory, and sample 25 | programs (included on the disk images) in the programs/ directory. 26 | See the doc/ directory for more info, including: 27 | 28 | - [handbook-user.html](doc/handbook-user.html) -- How to run and use MikeOS 29 | 30 | - [handbook-appdev-basic.html](doc/handbook-appdev-basic.html) -- Writing software in BASIC 31 | - [handbook-appdev-asm.html](doc/handbook-appdev-asm.html) -- Writing software in assembly 32 | - [handbook-sysdev.html](doc/handbook-sysdev.html) -- Building and modifying the OS 33 | 34 | - [LICENSE.TXT](doc/LICENSE.TXT) -- The open source, BSD-like license 35 | - [CHANGES.TXT](doc/CHANGES.TXT) -- Detailed list of changes in previous releases 36 | - [CREDITS.TXT](doc/CREDITS.TXT) -- People involved in the project 37 | 38 | Have fun, and see the [website](http://mikeos.sourceforge.net) 39 | 40 | [Mike Saunders](mailto:okachi@gmail.com) 41 | 42 | -------------------------------------------------------------------------------- /build-linux.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # This script assembles the MikeOS bootloader, kernel and programs 4 | # with NASM, and then creates floppy and CD images (on Linux) 5 | 6 | # Only the root user can mount the floppy disk image as a virtual 7 | # drive (loopback mounting), in order to copy across the files 8 | 9 | # (If you need to blank the floppy image: 'mkdosfs disk_images/mikeos.flp') 10 | 11 | 12 | if test "`whoami`" != "root" ; then 13 | echo "You must be logged in as root to build (for loopback mounting)" 14 | echo "Enter 'su' or 'sudo bash' to switch to root" 15 | exit 16 | fi 17 | 18 | 19 | if [ ! -e disk_images/mikeos.flp ] 20 | then 21 | echo ">>> Creating new MikeOS floppy image..." 22 | mkdosfs -C disk_images/mikeos.flp 1440 || exit 23 | fi 24 | 25 | 26 | echo ">>> Assembling bootloader..." 27 | 28 | nasm -O0 -w+orphan-labels -f bin -o source/bootload/bootload.bin source/bootload/bootload.asm || exit 29 | 30 | 31 | echo ">>> Assembling MikeOS kernel..." 32 | 33 | cd source 34 | nasm -O0 -w+orphan-labels -f bin -o kernel.bin kernel.asm || exit 35 | cd .. 36 | 37 | 38 | echo ">>> Assembling programs..." 39 | 40 | cd programs 41 | 42 | for i in *.asm 43 | do 44 | nasm -O0 -w+orphan-labels -f bin $i -o `basename $i .asm`.bin || exit 45 | done 46 | 47 | cd .. 48 | 49 | 50 | echo ">>> Adding bootloader to floppy image..." 51 | 52 | dd status=noxfer conv=notrunc if=source/bootload/bootload.bin of=disk_images/mikeos.flp || exit 53 | 54 | 55 | echo ">>> Copying MikeOS kernel and programs..." 56 | 57 | rm -rf tmp-loop 58 | 59 | mkdir tmp-loop && mount -o loop -t vfat disk_images/mikeos.flp tmp-loop && cp source/kernel.bin tmp-loop/ 60 | 61 | cp programs/*.bin programs/*.bas programs/sample.pcx tmp-loop 62 | 63 | sleep 0.2 64 | 65 | echo ">>> Unmounting loopback floppy..." 66 | 67 | umount tmp-loop || exit 68 | 69 | rm -rf tmp-loop 70 | 71 | 72 | echo ">>> Creating CD-ROM ISO image..." 73 | 74 | rm -f disk_images/mikeos.iso 75 | mkisofs -quiet -V 'MIKEOS' -input-charset iso8859-1 -o disk_images/mikeos.iso -b mikeos.flp disk_images/ || exit 76 | 77 | echo '>>> Done!' 78 | 79 | -------------------------------------------------------------------------------- /build-openbsd.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # This script assembles the MikeOS bootloader, kernel and programs 4 | # with NASM, and then creates floppy and CD images (on OpenBSD) 5 | 6 | # Only the root user can mount the floppy disk image as a virtual 7 | # drive (loopback mounting), in order to copy across the files 8 | 9 | 10 | echo "Experimental OpenBSD build script..." 11 | 12 | 13 | if test "`whoami`" != "root" ; then 14 | echo "You must be logged in as root to build (for loopback mounting)" 15 | echo "Enter 'su' to switch to root" 16 | exit 17 | fi 18 | 19 | 20 | if [ ! -e disk_images/mikeos.flp ] 21 | then 22 | echo ">>> Creating new MikeOS floppy image..." 23 | dd if=/dev/zero of=disk_images/mikeos.flp bs=512 count=2880 || exit 24 | vnconfig vnd3 disk_images/mikeos.flp && newfs_msdos -f 1440 vnd3c && vnconfig -u vnd3 || exit 25 | fi 26 | 27 | 28 | echo ">>> Assembling bootloader..." 29 | 30 | nasm -O0 -w+orphan-labels -f bin -o source/bootload/bootload.bin source/bootload/bootload.asm || exit 31 | 32 | 33 | echo ">>> Assembling MikeOS kernel..." 34 | 35 | cd source 36 | nasm -O0 -w+orphan-labels -f bin -o kernel.bin kernel.asm || exit 37 | cd .. 38 | 39 | 40 | echo ">>> Assembling programs..." 41 | 42 | cd programs 43 | 44 | for i in *.asm 45 | do 46 | nasm -O0 -w+orphan-labels -f bin $i -o `basename $i .asm`.bin || exit 47 | done 48 | 49 | cd .. 50 | 51 | 52 | echo ">>> Adding bootloader to floppy image..." 53 | 54 | dd conv=notrunc if=source/bootload/bootload.bin of=disk_images/mikeos.flp || exit 55 | 56 | 57 | echo ">>> Copying MikeOS kernel and programs..." 58 | 59 | rm -rf tmp-loop 60 | vnconfig vnd3 disk_images/mikeos.flp || exit 61 | 62 | mkdir tmp-loop && mount -t msdos /dev/vnd3c tmp-loop && cp source/kernel.bin tmp-loop/ 63 | 64 | cp programs/*.bin programs/*.bas programs/sample.pcx tmp-loop 65 | 66 | echo ">>> Unmounting loopback floppy..." 67 | 68 | umount tmp-loop || exit 69 | 70 | vnconfig -u vnd3 || exit 71 | rm -rf tmp-loop 72 | 73 | 74 | echo ">>> Creating CD-ROM ISO image..." 75 | 76 | rm -f disk_images/mikeos.iso 77 | mkisofs -quiet -V 'MIKEOS' -r -J -o disk_images/mikeos.iso -b mikeos.flp disk_images/ || exit 78 | 79 | echo '>>> Done!' 80 | 81 | -------------------------------------------------------------------------------- /build-osx.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | if test "`whoami`" != "root" ; then 4 | echo "[halt] Not running with superuser privileges." 5 | exit 6 | fi 7 | 8 | echo "[okay] Running from superuser" 9 | 10 | vercomp () { 11 | if [[ $1 == $2 ]] 12 | then 13 | return 0 14 | fi 15 | local IFS=. 16 | local i ver1=($1) ver2=($2) 17 | # fill empty fields in ver1 with zeros 18 | for ((i=${#ver1[@]}; i<${#ver2[@]}; i++)) 19 | do 20 | ver1[i]=0 21 | done 22 | for ((i=0; i<${#ver1[@]}; i++)) 23 | do 24 | if [[ -z ${ver2[i]} ]] 25 | then 26 | # fill empty fields in ver2 with zeros 27 | ver2[i]=0 28 | fi 29 | if ((10#${ver1[i]} > 10#${ver2[i]})) 30 | then 31 | return 1 32 | fi 33 | if ((10#${ver1[i]} < 10#${ver2[i]})) 34 | then 35 | return 2 36 | fi 37 | done 38 | return 0 39 | } 40 | 41 | nasm_version_check () { 42 | vercomp $nasm_ENV $2 43 | case $? in 44 | 0) op='=';; 45 | 1) op='>';; 46 | 2) op='<';; 47 | esac 48 | if [ $op = '=' ] || [ $op = '>' ] 49 | then 50 | echo "[okay] nasm version at least 2.10.09" 51 | nasm_okay=true 52 | else 53 | echo "[halt] nasm version is too low" 54 | fi 55 | } 56 | 57 | if [[ ! -f /usr/bin/nasm && ! -f /bin/nasm && ! -f /usr/sbin/nasm && ! -f /sbin/nasm && ! -f /usr/local/bin/nasm && ! -f /usr/x11/bin/nasm && ! -f /opt/local/bin/nasm ]] ; then 58 | echo [halt] nasm was not found on the system! Make sure it is named nasm and in the right place. 59 | exit 60 | elif [ -f /opt/local/bin/nasm ] ; then 61 | nasm_version_string_full=$(/opt/local/bin/nasm -v 2>&1) 62 | nasm_ENV=${nasm_version_string_full:13:7} 63 | nasm_version_check $nasm_ENV 2.10.09 64 | if $nasm_okay 65 | then 66 | full_nasm_path="/opt/local/bin/nasm" 67 | fi 68 | elif [ [ -f /usr/bin/nasm ] -a [ ! $nasm_okay ] ] ; then 69 | nasm_version_string_full=$(/usr/bin/nasm -v 2>&1) 70 | nasm_string_trash= 71 | nasm_ENV=${nasm_version_string_full:13:7} 72 | echo $items 73 | nasm_version_check $nasm_ENV 2.10.09 74 | if $nasm_okay 75 | then 76 | full_nasm_path="/usr/bin/nasm" 77 | fi 78 | elif [ [ -f /bin/nasm ] -a [ ! $nasm_okay ] ] ; then 79 | nasm_version_string_full=$(/bin/nasm -v 2>&1) 80 | nasm_ENV=${nasm_version_string_full:13:7} 81 | nasm_version_check $nasm_ENV 2.10.09 82 | if $nasm_okay 83 | then 84 | full_nasm_path="/bin/nasm" 85 | fi 86 | elif [ [ -f /usr/sbin/nasm ] -a [ ! $nasm_okay ] ] ; then 87 | nasm_version_string_full=$(/usr/sbin/nasm -v 2>&1) 88 | nasm_ENV=${nasm_version_string_full:13:7} 89 | nasm_version_check $nasm_ENV 2.10.09 '>=' 90 | if $nasm_okay 91 | then 92 | full_nasm_path="/usr/sbin/nasm" 93 | fi 94 | elif [ [ -f /sbin/nasm ] -a [ ! $nasm_okay ] ] ; then 95 | nasm_version_string_full=$(/sbin/nasm -v 2>&1) 96 | nasm_ENV=${nasm_version_string_full:13:7} 97 | nasm_version_check $nasm_ENV 2.10.09 98 | if $nasm_okay 99 | then 100 | full_nasm_path="/sbin/nasm" 101 | fi 102 | elif [ [ -f /usr/local/bin/nasm ] -a [ ! $nasm_okay ] ] ; then 103 | nasm_version_string_full=$(/usr/local/bin/nasm -v 2>&1) 104 | nasm_ENV=${nasm_version_string_full:13:7} 105 | nasm_version_check $nasm_ENV 2.10.09 106 | if $nasm_okay 107 | then 108 | full_nasm_path="/usr/local/bin/nasm" 109 | fi 110 | elif [ [ -f /usr/x11/bin/nasm ] -a [ ! $nasm_okay ] ] ; then 111 | nasm_version_string_full=$(/usr/x11/bin/nasm -v 2>&1) 112 | nasm_ENV=${nasm_version_string_full:13:7} 113 | nasm_version_check $nasm_ENV 2.10.09 114 | if $nasm_okay 115 | then 116 | full_nasm_path="/usr/x11/bin/nasm" 117 | fi 118 | else 119 | echo "[halt] nasm not found or version is incompatible" 120 | fi 121 | $full_nasm_path -O0 -f bin -o source/bootload/bootload.bin source/bootload/bootload.asm || exit 122 | echo "[okay] Assembled bootloader" 123 | cd source 124 | $full_nasm_path -O0 -f bin -o kernel.bin kernel.asm || exit 125 | cd .. 126 | echo "[okay] Assembled kernel" 127 | cd programs 128 | for i in *.asm 129 | do 130 | /opt/local/bin/nasm -O0 -f bin $i -o `basename $i .asm`.bin || exit 131 | echo "[okay] Assembled program: $i" 132 | done 133 | cd .. 134 | cp disk_images/mikeos.flp disk_images/mikeos.dmg 135 | echo "[okay] Copied floppy image" 136 | dd conv=notrunc if=source/bootload/bootload.bin of=disk_images/mikeos.dmg || exit 137 | echo "[okay] Added bootloader to image" 138 | rm -rf tmp-loop 139 | dev=`hdid -nobrowse -nomount disk_images/mikeos.dmg` 140 | mkdir tmp-loop && mount -t msdos ${dev} tmp-loop && cp source/kernel.bin tmp-loop/ 141 | cp programs/*.bin programs/*.bas programs/sample.pcx tmp-loop 142 | echo "[okay] Added programs to image" 143 | diskutil umount tmp-loop || exit 144 | hdiutil detach ${dev} 145 | rm -rf tmp-loop 146 | echo "[okay] Unmounted floppy image" 147 | rm -f disk_images/mikeos.iso 148 | mkisofs -quiet -V 'MIKEOS' -input-charset iso8859-1 -o disk_images/mikeos.iso -b mikeos.dmg disk_images/ || exit 149 | echo "[okay] Converted floppy to ISO-8859-1 image" 150 | echo "[done] Build completed" 151 | -------------------------------------------------------------------------------- /buildwin.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | echo Build script for Windows 3 | echo. 4 | 5 | echo Assembling bootloader... 6 | cd source\bootload 7 | nasm -O0 -f bin -o bootload.bin bootload.asm 8 | cd .. 9 | 10 | echo Assembling MikeOS kernel... 11 | nasm -O0 -f bin -o kernel.bin kernel.asm 12 | 13 | echo Assembling programs... 14 | cd ..\programs 15 | for %%i in (*.asm) do nasm -O0 -fbin %%i 16 | for %%i in (*.bin) do del %%i 17 | for %%i in (*.) do ren %%i %%i.bin 18 | cd .. 19 | 20 | echo Adding bootsector to disk image... 21 | cd disk_images 22 | partcopy ..\source\bootload\bootload.bin 0 200 mikeos.flp 0 23 | cd .. 24 | 25 | echo Mounting disk image... 26 | imdisk -a -f disk_images\mikeos.flp -s 1440K -m B: 27 | 28 | echo Copying kernel and applications to disk image... 29 | copy source\kernel.bin b:\ 30 | copy programs\*.bin b:\ 31 | copy programs\sample.pcx b:\ 32 | copy programs\*.bas b:\ 33 | 34 | echo Dismounting disk image... 35 | imdisk -D -m B: 36 | 37 | echo Done! 38 | -------------------------------------------------------------------------------- /disk_images/README.TXT: -------------------------------------------------------------------------------- 1 | These are floppy disk and CD-ROM images containing MikeOS and accompanying 2 | programs. mikeos.flp and mikeos.dmg are identical -- the latter can be used 3 | on Mac OS X without having to change the extension. 4 | 5 | You can use 'dd' on Linux or RAWRITE on Windows to write the floppy disk 6 | image to a real floppy. Alternatively, you can burn the .iso to a CD-R and 7 | boot from it in your CD burning utility. 8 | 9 | Note that the CD image is generated automatically from the build scripts, 10 | and uses the floppy image as a boot block (a virtual floppy disk). 11 | 12 | In Linux/Unix, you can create a new floppy image with this command: 13 | 14 | mkdosfs -C mikeos.flp 1440 15 | 16 | The build-linux.sh script does this if it doesn't find mikeos.flp. 17 | 18 | -------------------------------------------------------------------------------- /disk_images/mikeos.dmg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mig-hub/mikeOS/685306a87ddf1a41c069ec7670d24c7d2023ff20/disk_images/mikeos.dmg -------------------------------------------------------------------------------- /disk_images/mikeos.flp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mig-hub/mikeOS/685306a87ddf1a41c069ec7670d24c7d2023ff20/disk_images/mikeos.flp -------------------------------------------------------------------------------- /disk_images/mikeos.iso: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mig-hub/mikeOS/685306a87ddf1a41c069ec7670d24c7d2023ff20/disk_images/mikeos.iso -------------------------------------------------------------------------------- /doc/CREDITS.TXT: -------------------------------------------------------------------------------- 1 | ================================================================== 2 | MikeOS -- Open source 16-bit operating system for x86 PCs 3 | Copyright (C) 2006 - 2014 MikeOS Developers -- see doc/LICENSE.TXT 4 | ================================================================== 5 | 6 | 7 | PROJECT ADMIN (MAIN CODE AND HANDBOOKS) 8 | 9 | * Mike Saunders -- okachi@gmail.com 10 | 11 | 12 | DEVELOPMENT 13 | 14 | * E Dehling 15 | * Ian Seyler 16 | * Joshua Beck 17 | * Justin Tokarchuk 18 | * Matej Horvat 19 | * Michael van Tellingen 20 | * Mike Gonta 21 | * Peter Nemeth 22 | * Paulo Valongo 23 | * Takayoshi Sasano 24 | * Tomasz Gorol 25 | * Tslil Clingman 26 | * Walt Nagel 27 | * Yutaka Saiko 28 | 29 | 30 | WEBSITE, DOCS AND ARTWORK 31 | 32 | * Nitin Reddy Katkam -- logo and site design 33 | * Paul Sommers -- Handbook API reference 34 | * Helen Ewart -- MikeOS cat mascot 35 | 36 | 37 | ================================================================== 38 | 39 | -------------------------------------------------------------------------------- /doc/LICENSE.TXT: -------------------------------------------------------------------------------- 1 | ================================================================== 2 | MikeOS -- License 3 | ================================================================== 4 | 5 | 6 | Copyright (C) 2006 - 2014 MikeOS Developers -- http://mikeos.sourceforge.net 7 | 8 | All rights reserved. 9 | 10 | Redistribution and use in source and binary forms, with or without 11 | modification, are permitted provided that the following conditions are met: 12 | 13 | * Redistributions of source code must retain the above copyright 14 | notice, this list of conditions and the following disclaimer. 15 | 16 | * Redistributions in binary form must reproduce the above copyright 17 | notice, this list of conditions and the following disclaimer in the 18 | documentation and/or other materials provided with the distribution. 19 | 20 | * Neither the name MikeOS nor the names of any MikeOS contributors 21 | may be used to endorse or promote products derived from this software 22 | without specific prior written permission. 23 | 24 | THIS SOFTWARE IS PROVIDED BY MIKEOS DEVELOPERS AND CONTRIBUTORS "AS IS" 25 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 | ARE DISCLAIMED. IN NO EVENT SHALL MIKEOS DEVELOPERS BE LIABLE FOR ANY 28 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 29 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 30 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 31 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 32 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 33 | USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 | 35 | 36 | ================================================================== 37 | 38 | -------------------------------------------------------------------------------- /doc/handbook-user.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | The MikeOS User Handbook 8 | 9 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 459 | 460 |
75 | 76 |

Navigate

77 | 78 |

Booting

79 | 85 | 86 |

Running

87 | 94 | 95 |

Extra

96 | 100 | 101 |
110 | 111 |

The MikeOS User Handbook

112 | 113 |

For version 4.5, 21 December 2014 - (C) MikeOS Developers

114 | 115 |

This documentation file explains how to boot and use the MikeOS operating system on a real PC or an 116 | emulator. If you have just downloaded MikeOS and want to run it, this is the guide you need. If you have 117 | any questions, see the MikeOS website for contact details 118 | and mailing list information.

119 | 120 |

Click the links on the left to navigate around this guide.

121 | 122 |
123 | 124 | 125 |
126 | 127 | 128 |

Booting

129 | 130 | 131 |

Disk images

132 | 133 |

After you have extracted the MikeOS .zip file, switch into the 134 | disk_images/ directory and you'll see three files:

135 | 136 |
    137 |
  • mikeos.flp -- Floppy disk image containing MikeOS and programs
  • 138 |
  • mikeos.dmg -- Same as above, but with a Mac-friendly extension
  • 139 |
  • mikeos.iso -- CD ISO image built using the floppy disk image
  • 140 |
141 | 142 |

So, these files are virtual disk images that you can write to real floppy disks or 143 | CD-Rs, or run in a PC emulator as described in a moment.

144 | 145 | 146 |
147 | 148 | 149 | 150 |

Writing

151 | 152 |

For running MikeOS on a real PC, you will need to write one of the virtual disk images 153 | to physical media. If you have a USB key then this is simple -- we can write the floppy disk 154 | image to the USB key, and the PC will boot it like a virtual floppy.

155 | 156 |

On Linux, insert your USB key and unmount it when it appears (but don't remove it). Then open a command line 157 | window and enter dmesg to view the kernel messages. You will see an indication at the end of the messages of the device you just plugged 158 | in -- eg /dev/sdb. Note that you just need the device, eg /dev/sdb, rather than the number (eg /dev/sdb1). Then enter (in the disk_images directory):

159 | 160 |
dd if=mikeos.flp of=/dev/sdb
161 | 162 |

Of course, replace sdb with the device node. The key is now ready for booting.

163 | 164 |

On Windows, download the open source Flashnul program, plug in your USB key and 165 | enter flashnul -p to get a list of drives. When you've spotted your USB key, enter 166 | flashnul [number] -L mikeos.flp (in the disk_images directory), replacing [number] 167 | with the number you got before. The key is now ready for booting.

168 | 169 |

Note: if you plug your USB key back into the machine, the operating system may try to alter the 170 | partition structure and stop it from working properly. So treat it as a MikeOS-only key until you 171 | want to reformat it for normal use.

172 | 173 |

For floppy disks, on Windows you can use a program called RawWrite 174 | to copy mikeos.flp to a floppy disk. On Linux, use the dd 175 | utility like this:

176 | 177 |
dd if=mikeos.flp of=/dev/fd0
178 | 179 |

If you want to run MikeOS on a machine that doesn't have a floppy drive and doesn't 180 | boot from USB keys, you can burn and boot the mikeos.iso CD image. Any decent Windows CD burning software will 181 | allow you to write an ISO image to a CD-R; if you don't have one, try InfraRecorder.

182 | 183 |

On Linux, a graphical burning program such as K3b should do the trick, or you can use 184 | the command line:

185 | 186 |
cdrecord -dao dev=/dev/cdrom mikeos.iso
187 | 188 | 189 |
190 | 191 | 192 | 193 |

Real PCs

194 | 195 |

At a minimum, any 386 PC with 1MB of memory and a keyboard should be able to run MikeOS. In 196 | fact, you may be able to get it running on an older machine -- please do let us know if so! Just 197 | start your PC with the MikeOS floppy, CD-ROM or USB key inserted, and you should see the initial 198 | dialog screen.

199 | 200 |

On some systems, you may need to change the boot order in your BIOS so that the PC boots 201 | from the floppy, CD or USB key rather than the hard drive.

202 | 203 | 204 |
205 | 206 | 207 | 208 |

Emulators

209 | 210 |

A quick way to try MikeOS, and one that doesn't involve writing disk images to physical media, 211 | is to use an emulator. This is particularly useful if you're writing MikeOS software or changing 212 | the OS as described in the other two Handbooks.

213 | 214 |

Some of the best emulators:

215 | 216 |
    217 |
  • QEMU -- Small, simple and open source (link)
  • 218 |
  • VirtualBox -- Very powerful with a good GUI (link)
  • 219 |
  • VMware -- Popular proprietary virtualisation app (link)
  • 220 |
  • Bochs -- Takes a bit of work to set up, but good debugging tools (link)
  • 221 |
222 | 223 |

For VirtualBox and VMware, configure the boot device to use the MikeOS floppy disk or CD ISO image. 224 | With QEMU on Linux, run test-linux.sh, or for QEMU on Windows switch into the directory 225 | where you installed the emulator and enter:

226 | 227 |
228 | qemu.exe -L . -m 4 -boot a -fda mikeos.flp -soundhw all -localtime
229 | 
230 | 231 |

You will need to change the path to mikeos.flp accordingly.

232 | 233 | 234 |
235 | 236 | 237 |
238 | 239 | 240 |

Running

241 | 242 | 243 |

Usage

244 | 245 |

When MikeOS starts up, you'll see a dialog box which gives you the option of a program 246 | list of a command line interface. Using the cursor keys and Enter, choose OK for the former 247 | and Cancel for the latter.

248 | 249 |

In the program list you can select a .BIN or .BAS program with the up/down cursor 250 | keys and hit Enter to run it. Also, you can press Esc to return back to the original list/CLI 251 | selection screen.

252 | 253 |

At the command line, enter DIR to show a list of programs, and HELP 254 | to display inbuilt commands. You can run a program by entering the full filename (eg EDIT.BIN) 255 | or just the name without the extension (eg EDIT). There are also file management commands such 256 | as COPY, REN, DEL and SIZE.

257 | 258 | 259 |
260 | 261 | 262 | 263 |

Programs

264 | 265 |

MikeOS includes several programs to perform various tasks and demonstrate features of the OS, such as:

266 | 267 |
    268 |
  • EDIT.BIN -- Simple full-screen text editor (Unix-type text files only)
  • 269 |
  • EXAMPLE.BAS -- Demonstration of BASIC features (open it in EDIT.BIN to explore)
  • 270 |
  • FILEMAN.BIN -- Delete, rename and copy files on the floppy disk
  • 271 |
  • HANGMAN.BIN -- Guess the names of cities around the world
  • 272 |
  • MEMEDIT.BAS -- Colourful, powerful memory editor
  • 273 |
  • DRAW.BAS -- ASCII art drawing program
  • 274 |
  • CALC.BAS -- Powerful calculator
  • 275 |
  • SUDOKU.BAS -- Sudoku game
  • 276 |
  • CF.BAS -- Cosmic Flight game
  • 277 |
  • MUNCHER.BAS -- Snake-like game (use WASD keys)
  • 278 |
  • ADVNTURE.BAS -- A text adventure
  • 279 |
  • KEYBOARD.BIN -- Musical keyboard; use the bottom row of keys to play and Q to quit
  • 280 |
  • MONITOR.BIN -- Simple machine code monitor (see below)
  • 281 |
  • SERIAL.BIN -- Minicom-like serial terminal program (see below)
  • 282 |
  • VIEWER.BIN -- Views text files and 320x200x16 PCX images such as SAMPLE.PCX
  • 283 |
284 | 285 |

Note that FILEMAN.BIN and EDIT.BIN try to write to the floppy drive, 286 | so if you've booted from a CD-R and try to manipulate files you will see write errors as it's a read-only 287 | medium after burning.

288 | 289 | 290 |
291 | 292 | 293 | 294 |

Copying files

295 | 296 |

If you've written MikeOS to a real floppy disk, you can just copy extra files 297 | onto that disk in your file manager. But if you want to add files to the floppy disk images, 298 | that requires a bit of extra work -- you need to access the disk image as if it was a real 299 | floppy. First up is Linux: switch to the MikeOS main directory, then enter the following 300 | commands as root:

301 | 302 |
303 | mkdir looptmp
304 | mount -o loop -t vfat disk_images/mikeos.flp looptmp
305 | 
306 | 307 |

Now the contents of the MikeOS virtual floppy disk image are accessible in the newly-created looptmp/ 308 | directory. (We have loopback-mounted the disk image onto our filesystem.) Copy your programs into that directory, for example:

309 | 310 |
311 | cp MYPROG.BIN looptmp/
312 | 
313 | 314 |

When you're done, unmount the virtual floppy image and remove the temporary directory:

315 | 316 |
317 | umount looptmp
318 | rm -rf looptmp
319 | 
320 | 321 |

You can now write mikeos.flp to a floppy disk or boot it in an emulator. If you want 322 | to recreate the CD ISO image, run build-linux.sh as root; this will update mikeos.iso 323 | with the new floppy contents.

324 | 325 |

If you're running Windows, you will need a special program to access mikeos.flp as if it 326 | was a real floppy. One tool you can use is the ImDisk 327 | Virtual Disk Driver; download and run it to install. You can then mount the floppy disk image like this:

328 | 329 |
330 | imdisk -a -f mikeos.flp -s 1440K -m B:
331 | 
332 | 333 | Copy your files into the B: drive. When you are finished, enter: 334 | 335 |
336 | imdisk -d -m B:
337 | 
338 | 339 |

Now the files that you copied to B: have been written into mikeos.flp.

340 | 341 | 342 |
343 | 344 | 345 | 346 |

Monitor

347 | 348 |

Yutaka Saito has contributed a MikeOS program that lets you enter machine code in hexadecimal format 349 | and execute it. Run MONITOR.BIN from the command line and you'll be presented 350 | with a '=' prompt. Now you can enter your instructions, or just 'x' to exit back to the OS.

351 | 352 |

MikeOS programs are loaded at the 32K (32768) point. The monitor converts hex code and executes 353 | it at location 36864 in RAM -- that is, 4K after the where the monitor program is loaded. This is 354 | so that your code doesn't overwrite the monitor! Consequently, any code you run should 355 | be ORGed to 36864. For example, this is a small MikeOS program which displays the letter 'M' on 356 | the screen. After we've assembled it, we can run ndisasm on the resulting binary 357 | to see the hexadecimal codes:

358 | 359 |
360 | 361 |
362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 |
Source codeHexadecimal
BITS 16 
%INCLUDE "mikedev.inc" 
ORG 36864 
  
mov si, messageBE0790
call os_print_stringE8FD6F
retC3
  
message db 'M', 04D00
374 |
375 | 376 |
377 | 378 |

(The first three lines are merely assembly directives, so they don't generate any code.) Now 379 | that we have the hex codes, we can enter them into the monitor. Note that the code must be terminated 380 | with a dollar sign ($) character, and spaces are allowed. So, you can enter at the '=' prompt:

381 | 382 |
BE0790 E8FD6F C3 4D00$
383 | 384 |

When you enter this, the monitor will convert the hex codes to machine code at location 36864 in 385 | RAM, and call that location to execute it. (Just like normal MikeOS programs, you should finish with 386 | a ret instruction.) After execution, you'll be returned to the monitor. You can then 387 | enter 'r' to re-run the converted code, or 'x' to exit.

388 | 389 | 390 |
391 | 392 | 393 | 394 |

Serial port

395 | 396 |

You can use MikeOS as a Minicom-like serial terminal emulator with SERIAL.BIN. This lets 397 | you connect a MikeOS machine to, for instance, a UNIX machine, and operate the UNIX machine from 398 | MikeOS. Connect a serial (null-modem) cable between the two machines, then set up your UNIX machine 399 | with a terminal session on the serial port.

400 | 401 |

For instance, if you have a Linux machine, you would add a line like this to /etc/inittab:

402 | 403 |
404 | T0:2345:respawn:/sbin/getty/ -L ttyS0 9600 vt100
405 | 
406 | 407 |

When you restart your Linux machine, it will wait for a login on the serial port. Connect 408 | the null-modem cable to a MikeOS machine, and run SERIAL.BIN in MikeOS. You can now enter your 409 | username and password to log in.

410 | 411 |

Note that MikeOS configures the serial port to be 9600 baud, no parity, 8 data bits, 1 stop 412 | bit. If you wish to change these settings, edit source/features/serial.asm and see the port 413 | port setup code at the start of the file (then rebuild MikeOS as described in the System Developer Handbook). 414 | Also note that only a handful of VT100 commands have been implemented at present, so programs which do complicated 415 | things with the screen (such as Emacs) may not display properly.

416 | 417 |

To exit the program, press the F8 key. (You can change this to a different key by editing 418 | the source code near the start of programs/serial.asm.)

419 | 420 | 421 |
422 | 423 | 424 |
425 | 426 | 427 |

Extra

428 | 429 | 430 |

Help

431 | 432 | 433 |

If you have any questions about MikeOS, or you're developing a similar OS and want 434 | to share code and ideas, go to the MikeOS website 435 | and join the mailing list as described. You can then email 436 | mikeos-developer@lists.berlios.de 437 | to post to the list.

438 | 439 | 440 |
441 | 442 | 443 | 444 |

License

445 | 446 |

MikeOS is open source and released under a BSD-like license (see doc/LICENSE.TXT 447 | in the MikeOS .zip file). Essentially, it means you can do anything you like with the 448 | code, including basing your own project on it, providing you retain the license file and give credit 449 | to the MikeOS developers for their work.

450 | 451 | 452 |
453 | 454 | 455 |
456 | 457 | 458 |
461 | 462 | 463 | 464 | 465 | 466 | -------------------------------------------------------------------------------- /programs/advnture.bas: -------------------------------------------------------------------------------- 1 | 2 | REM ------------------------------------------------ 3 | REM ADVENTURE 2.3 -- By Justin Tokarchuk 4 | REM For MikeOS and MikeBasic Derivatives 5 | REM ------------------------------------------------ 6 | 7 | REM VARS: 8 | REM $1 = Player Name 9 | REM a = room number 10 | REM b = got note 11 | REM c = got candle 12 | REM d = opened treasure chest 13 | REM e = got key 14 | 15 | a = 1 16 | b = 0 17 | c = 0 18 | d = 0 19 | e = 0 20 | f = 0 21 | $1 = "" 22 | 23 | LOGO: 24 | CLS 25 | PRINT " _______ __ __ __ " 26 | PRINT " | _ |.--| |.--.--.-----.-----.| |_.--.--.----.-----.| |" 27 | PRINT " | || _ || | | -__| || _| | | _| -__||__|" 28 | PRINT " |___|___||_____| \___/|_____|__|__||____|_____|__| |_____||__|" 29 | PRINT " " 30 | PRINT " --------------------------------------------------------------" 31 | PRINT " | A Text-Based Adventure Game | " 32 | PRINT " ------------------------------- " 33 | PRINT "" 34 | PRINT "" 35 | PRINT "" 36 | PRINT "" 37 | 38 | GETNAME: 39 | PRINT "" 40 | PRINT " What do you call yourself?: " ; 41 | INPUT $1 42 | IF $1 = "" THEN GOTO GETNAME 43 | 44 | GETNAMEREMARK: 45 | RAND X 1 3 46 | PRINT "" 47 | PRINT " " ; 48 | PRINT $1 ; 49 | if x = 1 then PRINT "! Did your mother even love you? Oh well, it's your name." 50 | if x = 2 then PRINT "? What kind of name is that! Oh well, not like we can change it." 51 | if x = 3 then PRINT "!? You aren't from around here, are you?" 52 | GOSUB PRESSAKEY 53 | 54 | GOTO GAMEINTRO 55 | 56 | HELP: 57 | PRINT "" 58 | PRINT " The following are valid commands ingame:" 59 | PRINT "" 60 | PRINT " CLS - CLEARS THE SCREEN" 61 | PRINT " LOOK - REPRINTS ROOM DESCRIPTION" 62 | PRINT " INVENTORY - VIEW WHAT YOU ARE CARRYING" 63 | PRINT " NORTH, WEST, SOUTH, EAST - MOVES TO INPUTTED DIRECTION" 64 | PRINT " EXAMINE (OBJECT) - EXAMINES AN OBJECT" 65 | PRINT " USE (OBJECT) - USES AN OBJECT" 66 | PRINT " TAKE (OBJECT) - TAKES AN OBJECT" 67 | PRINT " OPEN (OBJECT) - OPENS A CONTAINER" 68 | PRINT " UNLOCK (OBJECT) - ATTEMPTS TO UNLOCK AN OBJECT" 69 | PRINT " HELP - VIEW THESE COMMANDS AGAIN" 70 | PRINT " EXIT - QUITS THE GAME" 71 | RETURN 72 | 73 | LOWERCASE: 74 | J = & $2 75 | FOR X = 1 TO 20 76 | PEEK K J 77 | IF K < 65 THEN GOTO NOTCAPITAL 78 | IF K > 90 THEN GOTO NOTCAPITAL 79 | K = K + 32 80 | POKE K J 81 | NOTCAPITAL: 82 | J = J + 1 83 | NEXT X 84 | RETURN 85 | 86 | GAMEINTRO: 87 | PRINT "" 88 | PRINT " HALLOWEEN NIGHT. The spookiest night of the year! Not very spooky" 89 | PRINT " in your cruddy room, though. So what if toilet paper takes hours" 90 | PRINT " to clean off of MR. RAUL's house. Why did I have to get grounded?" 91 | GOSUB PRESSAKEY 92 | PRINT " SCREW IT. I am " ; 93 | PRINT $1 ; 94 | PRINT ", I am mighty! I will not be held down by parents!" 95 | PRINT " I'm going to sneak out, and prove to everyone that MR. RAUL's house" 96 | PRINT " is not haunted!" 97 | GOSUB PRESSAKEY 98 | PRINT " You sneak down the stairs from your room, and notice your mother is" 99 | PRINT " fast asleep on the couch! Opportunity is knocking! You dart through" 100 | PRINT " your front door and across the street to MR. RAUL's house." 101 | GOSUB PRESSAKEY 102 | PRINT " You notice the door is cracked open, you push the door open and walk" 103 | PRINT " inside." 104 | GOSUB PRESSAKEY 105 | PRINT " -- SLAM!! -- Oh no! The door swings shut behind you! -- CLICK! --" 106 | PRINT " You examine the door to find a padlock holding it shut!" 107 | GOSUB PRESSAKEY 108 | GOSUB MOVEROOM 109 | GOTO PARSER 110 | 111 | MOVEROOM: 112 | IF a = 1 THEN GOSUB R1 113 | IF a = 2 THEN GOSUB R2 114 | IF a = 3 THEN GOSUB R3 115 | IF a = 4 THEN GOSUB R4 116 | IF a = 5 THEN GOSUB R5 117 | IF a = 6 THEN GOSUB R6 118 | RETURN 119 | 120 | R1: 121 | PRINT "" 122 | PRINT " -- The House Entrance -- " 123 | PRINT " The entrance of the house." 124 | PRINT " There is a large padlock behind you, barring your freedom." 125 | RETURN 126 | 127 | R2: 128 | PRINT "" 129 | PRINT " -- The Dining Room -- " 130 | PRINT " There is a large table in the middle of the room. There are multiple" 131 | PRINT " doors going out of this room. You see a large painting." 132 | RETURN 133 | 134 | R3: 135 | PRINT "" 136 | PRINT " -- The Kitchen -- " 137 | PRINT " There is a doorway in this room, with the door ripped off of the" 138 | PRINT " hinges. Odd, you think. The rest of the kitchen seems immaculate." 139 | RETURN 140 | 141 | R4: 142 | PRINT "" 143 | PRINT " -- The Bathroom -- " 144 | PRINT " Odd, for being a bathroom there are no windows or methods of" 145 | PRINT " ventilation." 146 | IF c = 0 THEN PRINT " There is a candle sitting atop the sink." 147 | RETURN 148 | 149 | R5: 150 | PRINT "" 151 | PRINT " -- The Bedroom -- " 152 | PRINT " A door leads back to the dining room." 153 | RETURN 154 | 155 | R6: 156 | PRINT "" 157 | PRINT " -- The Basement -- " 158 | IF c = 1 THEN PRINT " + You light your candle." 159 | IF c = 1 THEN PRINT " There is a treasure Chest on the floor." 160 | IF c = 0 THEN PRINT " It is too dark to see anything in here." 161 | RETURN 162 | 163 | PARSER: 164 | x = 0 165 | PRINT "" 166 | PRINT "> " ; 167 | INPUT $2 168 | GOSUB LOWERCASE 169 | IF $2 = "cls" THEN CLS 170 | IF $2 = "help" THEN GOSUB HELP 171 | IF $2 = "north" THEN GOSUB NORTH 172 | IF $2 = "n" THEN GOSUB NORTH 173 | IF $2 = "south" THEN GOSUB SOUTH 174 | IF $2 = "s" THEN GOSUB SOUTH 175 | IF $2 = "west" THEN GOSUB WEST 176 | IF $2 = "w" THEN GOSUB WEST 177 | IF $2 = "east" THEN GOSUB EAST 178 | IF $2 = "e" THEN GOSUB EAST 179 | IF $2 = "look" THEN GOSUB MOVEROOM 180 | IF $2 = "inventory" THEN GOSUB INVENTORY 181 | IF $2 = "examine rug" AND a = 1 THEN PRINT " A worn-out, stained old rug." 182 | IF $2 = "examine table" AND a = 2 THEN PRINT " A grandiose hardwood table." 183 | IF $2 = "examine table" AND a = 2 AND b = 0 THEN PRINT " A note sits atop it." 184 | IF $2 = "examine painting" AND a = 2 THEN PRINT " It is a picture of MR. RAUL" 185 | IF $2 = "take note" AND a = 2 AND b = 0 THEN b = 1 186 | IF $2 = "take note" AND a = 2 AND b = 1 THEN PRINT " You've taken the note." 187 | IF $2 = "open treasure chest" THEN GOSUB TREASURECHEST 188 | IF $2 = "unlock door" AND a = 1 AND e = 1 THEN GOTO GAMEEND 189 | IF $2 = "use note" THEN GOSUB NOTE 190 | IF $2 = "read note" THEN GOSUB NOTE 191 | IF $2 = "take candle" AND a = 4 AND c = 0 THEN GOSUB CANDLE 192 | IF $2 = "exit" THEN END 193 | IF $2 = "" THEN PRINT " Confused? Need a hand? Type HELP for a list of commands!" 194 | GOTO PARSER 195 | 196 | CANDLE: 197 | PRINT " + You take the candle from the sink." 198 | c = 1 199 | RETURN 200 | 201 | TREASURECHEST: 202 | IF a = 6 AND c = 1 THEN e = 1 203 | IF a = 6 AND e = 1 AND f = 0 THEN PRINT " + You open the treasure chest and take a KEY out of it." 204 | IF f = 1 THEN PRINT " You already have the treasure!" 205 | f = 1 206 | RETURN 207 | 208 | NOTE: 209 | IF b = 1 THEN PRINT " The note reads:" 210 | IF b = 1 THEN PRINT " The secret to your freedom lies in a box!" 211 | RETURN 212 | 213 | GAMEEND: 214 | PRINT " You unlock the door and rush outside as you gasp the free air!" 215 | PRINT " Nightfall is close and you almost had to spend the night! You " 216 | PRINT " decide that it would be wise to run home before mom wakes." 217 | PRINT " GAME OVER! Thanks for playing!" 218 | END 219 | 220 | INVENTORY: 221 | PRINT "" 222 | IF b = 0 AND c = 0 AND e = 0 THEN GOSUB EMPTY 223 | IF b = 1 THEN PRINT " NOTE" 224 | IF c = 1 THEN PRINT " CANDLE" 225 | IF e = 1 THEN PRINT " KEY" 226 | RETURN 227 | 228 | EMPTY: 229 | RAND X 1 5 230 | IF X = 1 THEN PRINT " Nothing. Not even so much as a fly out of your packsack." 231 | IF X = 2 THEN PRINT " You wonder why your packsack is so light, it's empty." 232 | IF X = 3 THEN PRINT " Your packsack has a surprising emptyness." 233 | IF X = 4 THEN PRINT " Apart from several dead flies in your packsack, it's empty." 234 | IF X = 5 THEN PRINT " You're packsack is full of loot!" 235 | IF X = 5 THEN PRINT " Not really, it's empty." 236 | RETURN 237 | 238 | NODIR: 239 | RAND X 1 3 240 | IF x = 1 THEN PRINT " ..So that's how the wall feels on my face. Excellent." 241 | IF x = 2 THEN PRINT " You cannot go that way." 242 | IF x = 3 THEN PRINT " You win!" 243 | IF x = 3 THEN PRINT " .... Just kidding." 244 | RETURN 245 | 246 | NORTH: 247 | REM -- ENTRANCE TO DINING ROOM -- 248 | IF a = 1 THEN x = 1 249 | IF a = 1 THEN a = 2 250 | IF x = 1 THEN GOSUB MOVEROOM 251 | IF x = 1 THEN RETURN 252 | REM -- DINING ROOM TO KITCHEN -- 253 | IF a = 2 THEN x = 2 254 | IF a = 2 THEN a = 3 255 | IF x = 2 THEN GOSUB MOVEROOM 256 | IF x = 2 THEN RETURN 257 | GOSUB NODIR 258 | RETURN 259 | 260 | WEST: 261 | REM -- ENTRANCE TO BEDROOM -- 262 | IF a = 1 THEN x = 1 263 | IF a = 1 THEN a = 5 264 | IF x = 1 THEN GOSUB MOVEROOM 265 | IF x = 1 THEN RETURN 266 | REM -- DINING ROOM TO BASEMENT -- 267 | IF a = 2 THEN x = 2 268 | IF a = 2 THEN a = 6 269 | IF x = 2 THEN GOSUB MOVEROOM 270 | IF x = 2 THEN RETURN 271 | REM -- KITCHEN TO BATHROOM 272 | IF a = 3 THEN x = 3 273 | IF a = 3 THEN a = 4 274 | IF x = 3 THEN GOSUB MOVEROOM 275 | IF x = 3 THEN RETURN 276 | GOSUB NODIR 277 | RETURN 278 | 279 | SOUTH: 280 | REM -- DINING ROOM TO ENTRANCE 281 | IF a = 2 THEN x = 2 282 | IF a = 2 THEN a = 1 283 | IF x = 2 THEN GOSUB MOVEROOM 284 | IF x = 2 THEN RETURN 285 | REM -- KITCHEN TO DINING ROOM -- 286 | IF a = 3 THEN x = 3 287 | IF a = 3 THEN a = 2 288 | IF x = 3 THEN GOSUB MOVEROOM 289 | IF x = 3 THEN RETURN 290 | GOSUB NODIR 291 | RETURN 292 | 293 | EAST: 294 | REM -- BATHROOM TO KITCHEN -- 295 | IF a = 4 THEN x = 4 296 | IF a = 4 THEN a = 3 297 | IF x = 4 THEN GOSUB MOVEROOM 298 | IF x = 4 THEN RETURN 299 | REM -- BEDROOM TO ENTRANCE -- 300 | IF a = 5 THEN x = 5 301 | IF a = 5 THEN a = 1 302 | IF x = 5 THEN GOSUB MOVEROOM 303 | IF x = 5 THEN RETURN 304 | REM -- BASEMENT TO DINING ROOM -- 305 | IF a = 6 THEN x = 6 306 | IF a = 6 then a = 2 307 | IF x = 6 THEN GOSUB MOVEROOM 308 | IF x = 6 THEN RETURN 309 | GOSUB NODIR 310 | RETURN 311 | 312 | PRESSAKEY: 313 | PRINT "" 314 | PRINT " -- Press any key to continue. --" 315 | WAITKEY X 316 | PRINT "" 317 | RETURN 318 | 319 | 320 | 321 | -------------------------------------------------------------------------------- /programs/archive.bas: -------------------------------------------------------------------------------- 1 | if $1 = "" then goto help 2 | d = ramstart 3 | 4 | main: 5 | rem >>> Collect command, help if invalid <<< 6 | gosub collect_parameter 7 | if $2 = "HELP" then goto help 8 | if $2 = "CREATE" then goto create_archive 9 | if $2 = "ADD" then goto add_file 10 | if $2 = "REMOVE" then goto remove_file 11 | if $2 = "EXTRACT" then goto extract_file 12 | if $2 = "EXTRACTALL" then goto extract_all 13 | if $2 = "LIST" then goto archive_list 14 | goto help 15 | 16 | collect_parameter: 17 | rem >>> Collects a parameter separated by a space to $2 <<< 18 | rem >>> Offset(P) updated each time <<< 19 | x = & $1 20 | x = x + p 21 | do 22 | x = x + 1 23 | peek v x 24 | if v = 0 then v = 32 25 | loop until v = 32 26 | poke 0 x 27 | x = & $1 28 | x = x + p 29 | string load $2 x 30 | len $2 v 31 | p = p + v + 1 32 | case upper $2 33 | return 34 | 35 | collect_list_item: 36 | rem >>> Collect an item from a comma separated list $2 to $3 <<< 37 | rem >>> offset in Q, returns null if list finished <<< 38 | if q = 255 then $3 = "" 39 | if q = 255 then return 40 | x = & $2 41 | x = x + q 42 | do 43 | x = x + 1 44 | peek v x 45 | if v = 0 then v = 44 46 | if v = 32 then v = 44 47 | loop until v = 44 48 | peek v x 49 | poke 0 x 50 | x = & $2 51 | x = x + q 52 | string load $3 x 53 | if v < 33 then q = 255 54 | len $3 v 55 | if q < 255 then q = q + v + 1 56 | case upper $3 57 | return 58 | 59 | find_free_block: 60 | rem >>> Find a free block big enough for filesize S <<< 61 | rem >>> Returns N = block number, M = number of blocks <<< 62 | 63 | if s = 0 then return 64 | 65 | x = d + 14 66 | peek y x 67 | 68 | rem turn raw size into a number of 512 byte blocks 69 | m = s / 512 70 | v = s % 512 71 | if v > 0 then m = m + 1 72 | w = 0 73 | z = 0 74 | 75 | x = d + 5 76 | peekint v x 77 | x = d + v 78 | 79 | rem search the allocation map for free space 80 | do 81 | peek v x 82 | x = x + 1 83 | if v = 0 then w = w + 1 84 | if v > 0 then w = 0 85 | z = z + 1 86 | rem if we exceed the allocation map there is no space 87 | if z > y then print "There is no area large enough for this file." 88 | if z > y then end 89 | loop until w = m 90 | 91 | n = z - m 92 | return 93 | 94 | allocate_file_entry: 95 | rem >>> Create a file entry with filename $3, size S and the used block <<< 96 | rem >>> Must run find_free_block first to get file area <<< 97 | 98 | rem check the maximum files is not reached 99 | x = d + 11 100 | peek v x 101 | x = d + 12 102 | peek w x 103 | if v = w then print "No free file entries." 104 | if v = w then end 105 | rem increase files in archive 106 | v = v + 1 107 | x = d + 11 108 | poke v x 109 | 110 | x = d + 7 111 | peekint v x 112 | x = v + d 113 | z = 0 114 | rem search the file list for blank entries 115 | do 116 | peek v x 117 | x = x + 17 118 | z = z + 1 119 | if z > w then print "No free file entries." 120 | if z > w then end 121 | loop until v = 0 122 | x = x - 17 123 | 124 | w = d + 9 125 | peekint z w 126 | 127 | rem store information in entry 128 | string store $3 x 129 | x = x + 13 130 | o = n * 512 + z 131 | pokeint o x 132 | x = x + 2 133 | pokeint s x 134 | return 135 | 136 | allocate_free_block: 137 | rem >>> Allocate free block found with find_free_block <<< 138 | 139 | x = d + 5 140 | peekint v x 141 | x = d + v + n 142 | 143 | rem store area as allocated 144 | w = m 145 | do 146 | poke 1 x 147 | x = x + 1 148 | w = w - 1 149 | loop until w = 0 150 | 151 | rem if the last block allocate is more than highest block, update 152 | w = n + m - 1 153 | x = d + 13 154 | peek v x 155 | if w > v then v = w 156 | poke v x 157 | return 158 | 159 | collect_file_data: 160 | rem >>> find filename $3 in the file list and get offset(O) and size(S) <<< 161 | x = d + 12 162 | peek z x 163 | 164 | x = d + 7 165 | peekint v x 166 | x = d + v 167 | 168 | rem search file entries until we find a match 169 | w = 0 170 | y = 0 171 | do 172 | string load $4 x 173 | if $4 = $3 then w = 1 174 | x = x + 17 175 | y = y + 1 176 | if y = z then print "File does not exist." 177 | if y = z then end 178 | loop until w = 1 179 | 180 | rem collect information 181 | x = x - 17 182 | x = x + 13 183 | peekint o x 184 | x = x + 2 185 | peekint s x 186 | return 187 | 188 | deallocate_block: 189 | rem >>> Deallocate block used by a file <<< 190 | rem >>> Run collect_file_info first <<< 191 | 192 | x = d + 9 193 | peekint v x 194 | 195 | rem figure out block number and amount from offset and size 196 | n = o - v / 512 197 | m = s / 512 198 | v = s % 512 199 | if v > 0 then m = m + 1 200 | if m = 0 then return 201 | 202 | x = d + 5 203 | peekint v x 204 | x = v + n + d 205 | y = m 206 | rem store blocks as unused 207 | do 208 | poke 0 x 209 | x = x + 1 210 | y = y - 1 211 | loop until y = 0 212 | 213 | x = d + 14 214 | peek z x 215 | x = d + 5 216 | peekint v x 217 | x = d + v + z - 1 218 | 219 | rem find the new highest block and update 220 | z = z + 1 221 | do 222 | peek v x 223 | x = x - 1 224 | z = z - 1 225 | if z = 0 then v = 1 226 | loop until v = 1 227 | 228 | x = d + 13 229 | poke z x 230 | return 231 | 232 | deallocate_file_entry: 233 | rem >>> Remove file entry with name $3 <<< 234 | rem >>> Must run collect_file_data first <<< 235 | 236 | rem reduce files in archive 237 | x = d + 11 238 | peek v x 239 | v = v - 1 240 | poke v x 241 | 242 | x = d + 7 243 | peekint v x 244 | x = d + v 245 | 246 | rem find file entry 247 | w = 0 248 | do 249 | string load $4 x 250 | x = x + 17 251 | if $4 = $3 then w = 1 252 | loop until w = 1 253 | 254 | rem blank file entry 255 | x = x - 17 256 | for y = 1 to 17 257 | poke 0 x 258 | x = x + 1 259 | next y 260 | return 261 | 262 | load_archive: 263 | rem >>> load and verify archive <<< 264 | 265 | print "Opening Archive..." 266 | rem get name off the commandline parameters 267 | gosub collect_parameter 268 | load $2 d 269 | rem preserve opened name 270 | $8 = $2 271 | 272 | rem make sure file is valid 273 | if s = 0 then print "Archive file is blank." 274 | if s = 0 then end 275 | 276 | if r = 1 then print "Archive file does not exist." 277 | if r = 1 then end 278 | 279 | rem check for archive header 280 | string load $4 d 281 | if $4 = "MFA" then rem 282 | else print "Not an archive file." 283 | else end 284 | 285 | rem check version is current 286 | x = d + 4 287 | peek v x 288 | if v > 1 then print "Archive version not supported." 289 | if v > 1 then end 290 | return 291 | 292 | save_archive: 293 | rem >>> calculate size and store archive <<< 294 | 295 | print "Saving Archive..." 296 | rem header size 297 | z = 14 298 | 299 | rem allocate block size 300 | x = d + 14 301 | peek v x 302 | z = z + v 303 | 304 | rem file list size 305 | x = d + 12 306 | peek v x 307 | v = v * 17 308 | z = z + v 309 | 310 | rem save only up to the last allocated block of data 311 | x = d + 13 312 | peek v x 313 | v = v + 1 314 | v = v * 512 315 | z = z + v 316 | 317 | rem save per existing name, overwrite 318 | delete $8 319 | save $8 d z 320 | return 321 | 322 | help: 323 | rem present is no arguments, help argument or invalid argument 324 | print "============================" 325 | print "ARCHIVE: File archiving tool" 326 | print "============================" 327 | print "Version 1.0.0" 328 | print "Copyright (C) Joshua Beck" 329 | print "Email: mikeosdeveloper@gmail.com" 330 | print "Licenced under the GNU General Public Licence v3" 331 | print "" 332 | print "Syntax: ARCHIVE (command) (archive filename) [comma separated list]" 333 | print "" 334 | print "Commands:" 335 | print " Create - Create an empty archive" 336 | print " Add - Added listed files to archive" 337 | print " Remove - Remove listed files from archive" 338 | print " Extract - Extract listed files from archive" 339 | print " ExtractAll - Extract all files from archive" 340 | print " List - List files in an archive" 341 | print " Help - Display this help screen" 342 | print "" 343 | end 344 | 345 | create_archive: 346 | rem >>> create new archive <<< 347 | 348 | rem file identifier 349 | d = ramstart 350 | $4 = "MFA" 351 | string store $4 d 352 | 353 | rem file version 354 | x = d + 4 355 | poke 1 x 356 | 357 | rem allocation map offset 358 | x = d + 5 359 | pokeint 15 x 360 | 361 | rem file list offset 362 | x = d + 7 363 | pokeint 45 x 364 | 365 | rem data offset 366 | x = d + 9 367 | pokeint 385 x 368 | 369 | rem files in archive 370 | x = d + 11 371 | poke 0 x 372 | 373 | rem file list entries 374 | x = d + 12 375 | poke 20 x 376 | 377 | rem highest allocated block 378 | x = d + 13 379 | poke 0 x 380 | 381 | rem blocks (512 bytes) in allocation map 382 | x = d + 14 383 | poke 40 x 384 | 385 | rem create blank allocation map 386 | x = d + 15 387 | for y = 1 to 40 388 | poke 0 x 389 | x = x + 1 390 | next y 391 | 392 | rem create blank file list 393 | x = d + 45 394 | for y = 1 to 340 395 | poke 0 x 396 | x = x + 1 397 | next y 398 | 399 | rem collect filename off parameter list 400 | gosub collect_parameter 401 | $8 = $2 402 | gosub save_archive 403 | print "File created." 404 | end 405 | 406 | add_file: 407 | gosub load_archive 408 | 409 | gosub collect_parameter 410 | gosub collect_list_item 411 | 412 | t = 0 413 | do 414 | $4 = "Adding file: " + $3 415 | print $4 416 | 417 | size $3 418 | gosub find_free_block 419 | gosub allocate_file_entry 420 | gosub allocate_free_block 421 | 422 | v = d + o 423 | load $3 v 424 | if r = 1 then print "File does not exist." 425 | if r = 1 then end 426 | 427 | gosub collect_list_item 428 | if $3 = "" then t = 1 429 | loop until t = 1 430 | 431 | gosub save_archive 432 | print "All files added successfully." 433 | end 434 | 435 | remove_file: 436 | gosub load_archive 437 | 438 | gosub collect_parameter 439 | gosub collect_list_item 440 | 441 | t = 0 442 | do 443 | $4 = "Removing file: " + $3 444 | print $4 445 | 446 | gosub collect_file_data 447 | gosub deallocate_block 448 | gosub deallocate_file_entry 449 | 450 | gosub collect_list_item 451 | if $3 = "" then t = 1 452 | loop until t = 1 453 | 454 | gosub save_archive 455 | print "All files successfully removed." 456 | end 457 | 458 | extract_file: 459 | gosub load_archive 460 | 461 | gosub collect_parameter 462 | gosub collect_list_item 463 | 464 | t = 0 465 | do 466 | $4 = "Extracting file: " + $3 467 | print $4 468 | 469 | gosub collect_file_data 470 | v = o + d 471 | delete $3 472 | save $3 v s 473 | if r > 0 then print "Invalid filename or read-only disk." 474 | if r > 0 then end 475 | 476 | gosub collect_list_item 477 | if $3 = "" then t = 1 478 | loop until t = 1 479 | 480 | print "All files extracted successfully." 481 | end 482 | 483 | extract_all: 484 | gosub load_archive 485 | 486 | x = d + 12 487 | peek w x 488 | w = w * 17 489 | x = d + 7 490 | peekint t x 491 | t = t + d 492 | u = t + w 493 | 494 | do 495 | string load $3 t 496 | t = t + 17 497 | 498 | $4 = "Extracting file: " + $3 499 | if $3 = "" then rem 500 | else print $4 501 | 502 | gosub collect_file_data 503 | v = o + d 504 | if $3 = "" then rem 505 | else delete $3 506 | else save $3 v s 507 | 508 | if r = 1 then print "Invalid filename or read-only disk." 509 | if r = 1 then end 510 | loop until t = u 511 | 512 | print "All files extracted successfully." 513 | end 514 | 515 | archive_list: 516 | gosub load_archive 517 | 518 | x = d + 11 519 | peek a x 520 | $4 = "File in archive: " + a 521 | x = d + 12 522 | peek b x 523 | 524 | $4 = "Files in archive: " + a 525 | $5 = "Maximum files: " + b 526 | $6 = "Archive size: " + s 527 | 528 | print "Mega File Archive - Version 1" 529 | print $4 530 | print $5 531 | print $6 532 | print "File list:" 533 | if v = 0 then end 534 | 535 | x = d + 12 536 | peek w x 537 | x = d + 7 538 | peekint v x 539 | x = d + v 540 | 541 | do 542 | string load $4 x 543 | if $4 = "" then rem 544 | else print $4 545 | x = x + 17 546 | w = w - 1 547 | loop until w = 0 548 | end 549 | 550 | 551 | -------------------------------------------------------------------------------- /programs/calc.bas: -------------------------------------------------------------------------------- 1 | rem Calculator Application (CALC.BAS) 2 | rem A simple calculator application. 3 | rem Version 2.0.1 4 | rem Made by Joshua Beck 5 | rem Released under the GNU General Public Licence version 3 6 | rem Send any bugs, ideas or comments to mikeosdeveloper@gmail.com 7 | 8 | rem Uses the MB++ Library version 3.0 9 | rem Avaliable at code.google.com/p/mikebasic-applications 10 | INCLUDE "MBPP.BAS" 11 | 12 | START: 13 | CLS 14 | REM MB++ initialise function 15 | GOSUB STARTPRG 16 | REM set the text colour and highlight (for the menu) 17 | C = 3 18 | H = 11 19 | REM set the box colour 20 | T = 2 21 | MOVE 30 13 22 | PRINT "Calculating..." 23 | GOTO MAIN 24 | 25 | MAIN: 26 | REM main menu 27 | $T = "Calculator" 28 | $5 = "Simple Calculations" 29 | $6 = "Advanced Maths" 30 | $7 = "Change Colour Scheme" 31 | $8 = "About" 32 | $9 = "Exit" 33 | GOSUB MENUBOX 34 | IF V = 1 THEN GOSUB BASEMATH 35 | IF V = 2 THEN GOSUB ADVMATH 36 | IF V = 3 THEN GOSUB COLCHANGE 37 | IF V = 4 THEN GOSUB ABOUT 38 | IF V = 5 THEN GOSUB ENDPROG 39 | GOTO MAIN 40 | 41 | COLCHANGE: 42 | $T = "Change Colour Scheme" 43 | $5 = "Input a new colour for outline, 1-255" 44 | $6 = "Input a new text colour, 1-15" 45 | V = 0 46 | GOSUB DINBOX 47 | $E = "Invalid colour" 48 | IF A < 1 THEN GOTO ERRBOX 49 | IF A > 255 THEN GOTO ERRBOX 50 | IF B < 1 THEN GOTO ERRBOX 51 | IF B > 15 THEN GOTO ERRBOX 52 | T = A 53 | C = B 54 | $5 = "Input a new highlight colour, 1-15" 55 | $6 = "" 56 | V = 0 57 | GOSUB INPBOX 58 | $E = "Invalid colour" 59 | IF V < 1 THEN GOTO ERRBOX 60 | IF V > 15 THEN GOTO ERRBOX 61 | H = V 62 | RETURN 63 | 64 | BASEMATH: 65 | REM start the menu loop 66 | DO 67 | REM set the menu title 68 | $T = "Simple Calculations" 69 | REM set items in the menu 70 | $5 = "Addition" 71 | $6 = "Subtraction" 72 | $7 = "Multiplication" 73 | $8 = "Division" 74 | $9 = "Back" 75 | REM call a menu 76 | GOSUB MENUBOX 77 | REM find out what they selected and gosub there 78 | IF V = 1 THEN GOSUB ADD 79 | IF V = 2 THEN GOSUB SUB 80 | IF V = 3 THEN GOSUB MUL 81 | IF V = 4 THEN GOSUB DIV 82 | REM present the menu again unless 'back' was selected 83 | LOOP UNTIL V = 5 84 | V = 0 85 | RETURN 86 | 87 | ADD: 88 | REM INPBOX and DINBOX use V to choose between text and numerical input 89 | REM we want numerical 90 | V = 0 91 | REM set the title 92 | $T = "Addition" 93 | REM first input prompt 94 | $5 = "Input first number..." 95 | REM second input prompt 96 | $6 = "Input second number..." 97 | REM DINBOX is similar to INPBOX (Print text and asks for input) but 98 | REM it asks for two inputs rather than just one. 99 | GOSUB DINBOX 100 | REM do the actual calculation 101 | REM the first input is A and the second is B 102 | a = a + b 103 | REM prompt above first number 104 | $5 = "Answer is:" 105 | REM prompt about second 106 | REM this is set to a blank string so it won't print it (we only need one) 107 | $6 = "" 108 | REM call a number box to print our answer 109 | GOSUB NUMBOX 110 | REM back to main menu 111 | RETURN 112 | 113 | SUB: 114 | v = 0 115 | $T = "Subtraction" 116 | $5 = "Input number to subtract from..." 117 | $6 = "Input number to subtract..." 118 | GOSUB DINBOX 119 | A = A - B 120 | $5 = "Answer is:" 121 | $6 = "" 122 | GOSUB NUMBOX 123 | RETURN 124 | 125 | MUL: 126 | v = 0 127 | $T = "Multiplication" 128 | $5 = "Input first number..." 129 | $6 = "Input second number..." 130 | GOSUB DINBOX 131 | A = A * B 132 | $5 = "Answer is:" 133 | $6 = "" 134 | GOSUB NUMBOX 135 | RETURN 136 | 137 | DIV: 138 | v = 0 139 | $T = "Division" 140 | $5 = "Input number to be divided..." 141 | $6 = "Input number to divide by..." 142 | GOSUB DINBOX 143 | REM define error message 144 | REM if the divisor is zero then present this error 145 | $E = "Attempted to divide by zero!" 146 | IF B = 0 THEN GOTO ERRBOX 147 | D = A / B 148 | E = A % B 149 | A = D 150 | B = E 151 | $5 = "Answer is:" 152 | $6 = "Reminder is:" 153 | GOSUB NUMBOX 154 | RETURN 155 | 156 | ADVMATH: 157 | DO 158 | $T = "Advanced Maths" 159 | $5 = "Square/Cube Number" 160 | $6 = "Power" 161 | $7 = "Mass Addition" 162 | $8 = "Mass Subtraction" 163 | $9 = "Back" 164 | GOSUB MENUBOX 165 | IF V = 1 THEN GOSUB SQUARE 166 | IF V = 2 THEN GOSUB POWER 167 | IF V = 3 THEN GOSUB MASSADD 168 | IF V = 4 THEN GOSUB MASSTAKE 169 | LOOP UNTIL V = 5 170 | V = 0 171 | RETURN 172 | 173 | SQUARE: 174 | $T = "Square/Cube Number" 175 | $5 = "" 176 | $6 = "Input a number to square and cube" 177 | V = 0 178 | GOSUB INPBOX 179 | A = V 180 | D = A 181 | A = A * D 182 | B = A * D 183 | $T = "Square/Cube Number" 184 | $5 = "Number Squared is:" 185 | $6 = "Number Cubed is:" 186 | GOSUB NUMBOX 187 | RETURN 188 | 189 | POWER: 190 | $T = "Power" 191 | $5 = "Input a number" 192 | $6 = "Input power to raise to" 193 | V = 0 194 | GOSUB DINBOX 195 | D = A 196 | IF B = 0 THEN A = 1 197 | IF B = 0 THEN GOTO POWERSKIP 198 | IF B = 1 THEN GOTO POWERSKIP 199 | DO 200 | A = A * D 201 | B = B - 1 202 | LOOP UNTIL B = 1 203 | POWERSKIP: 204 | $T = "Power" 205 | $5 = "Answer is:" 206 | $6 = "" 207 | GOSUB NUMBOX 208 | RETURN 209 | 210 | MASSADD: 211 | $T = "Mass Add" 212 | $5 = "Enter the base number" 213 | $6 = "Enter the first number to add" 214 | V = 0 215 | GOSUB DINBOX 216 | N = A 217 | N = N + B 218 | ADDMORE: 219 | $T = "Mass Add" 220 | $5 = "Enter another number to add" 221 | $6 = "or zero to finish the sum" 222 | V = 0 223 | GOSUB INPBOX 224 | N = N + V 225 | IF V > 0 THEN GOTO ADDMORE 226 | $5 = "The base number was: " 227 | $6 = "The total was: " 228 | B = N 229 | GOSUB NUMBOX 230 | RETURN 231 | 232 | MASSTAKE: 233 | $T = "Mass Subtract" 234 | $5 = "Enter the base number" 235 | $6 = "Enter the first number to take" 236 | V = 0 237 | GOSUB DINBOX 238 | N = A 239 | N = N - B 240 | TAKEMORE: 241 | $T = "Mass Subtract" 242 | $5 = "Enter another number to take" 243 | $6 = "or zero to finish the sum" 244 | V = 0 245 | GOSUB INPBOX 246 | N = N - V 247 | IF V > 0 THEN GOTO TAKEMORE 248 | $5 = "The base number was: " 249 | $6 = "The total was: " 250 | B = N 251 | GOSUB NUMBOX 252 | RETURN 253 | 254 | ABOUT: 255 | $T = "About" 256 | $5 = "Calculator, version 2.0.1" 257 | $6 = "An advanced calculator application" 258 | $7 = "Released under the GNU GPL v3" 259 | $8 = "Written in MikeOS BASIC" 260 | $9 = "Thanks to the MikeOS developers" 261 | GOSUB MESBOX 262 | 263 | $5 = "Uses the MB++ Library, version 3.0" 264 | $6 = "A great TUI library" 265 | $7 = "Created by Joshua Beck" 266 | $8 = "Mail: mikeosdeveloper@gmail.com" 267 | $9 = "Try the new mass addition/subtraction" 268 | GOSUB MESBOX 269 | RETURN 270 | -------------------------------------------------------------------------------- /programs/edit.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mig-hub/mikeOS/685306a87ddf1a41c069ec7670d24c7d2023ff20/programs/edit.bin -------------------------------------------------------------------------------- /programs/example.bas: -------------------------------------------------------------------------------- 1 | rem *** MikeOS BASIC demo *** 2 | 3 | cls 4 | 5 | $1 = "Hex dumper,MikeTron" 6 | $2 = "Choose a program to run," 7 | $3 = "Or press Esc to exit" 8 | 9 | listbox $1 $2 $3 a 10 | 11 | if a = 1 then goto runhex 12 | if a = 2 then goto runmiketron 13 | 14 | cls 15 | end 16 | 17 | 18 | runhex: 19 | 20 | rem *** Hex dumper *** 21 | 22 | cls 23 | 24 | print "Enter a filename to make a hex dump from:" 25 | input $1 26 | 27 | x = RAMSTART 28 | 29 | load $1 x 30 | if r = 1 then goto hexerror 31 | 32 | hexloop: 33 | peek a x 34 | print hex a ; 35 | print " " ; 36 | x = x + 1 37 | s = s - 1 38 | if s = 0 then goto hexfinish 39 | goto hexloop 40 | 41 | hexfinish: 42 | print "" 43 | end 44 | 45 | hexerror: 46 | print "Could not load file! Does it exist?" 47 | end 48 | 49 | 50 | 51 | runmiketron: 52 | 53 | rem *** MikeTron *** 54 | 55 | cls 56 | 57 | print "You control a vehicle leaving a trail behind it." 58 | print "" 59 | print "It is always moving, and if it crosses any part" 60 | print "of the trail or border (+ characters), the game" 61 | print "is over. Use the Q and A keys to change the direction" 62 | print "to up and down, and O and P for left and right." 63 | print "See how long you can survive! Score at the end." 64 | print "" 65 | print "NOTE: May perform at wrong speed in emulators!" 66 | print "" 67 | print "Hit a key to begin..." 68 | 69 | waitkey x 70 | 71 | 72 | cls 73 | cursor off 74 | 75 | 76 | rem *** Draw border around screen *** 77 | 78 | gosub setupscreen 79 | 80 | 81 | rem *** Start in the middle of the screen *** 82 | 83 | x = 40 84 | y = 12 85 | 86 | move x y 87 | 88 | 89 | rem *** Movement directions: 1 - 4 = up, down, left, right *** 90 | rem *** We start the game moving right *** 91 | 92 | d = 4 93 | 94 | 95 | rem *** S = score variable *** 96 | 97 | s = 0 98 | 99 | 100 | mainloop: 101 | print "+" ; 102 | 103 | pause 1 104 | 105 | getkey k 106 | 107 | if k = 'q' then d = 1 108 | if k = 'a' then d = 2 109 | if k = 'o' then d = 3 110 | if k = 'p' then d = 4 111 | 112 | if d = 1 then y = y - 1 113 | if d = 2 then y = y + 1 114 | if d = 3 then x = x - 1 115 | if d = 4 then x = x + 1 116 | 117 | move x y 118 | 119 | curschar c 120 | if c = '+' then goto finish 121 | 122 | s = s + 1 123 | goto mainloop 124 | 125 | 126 | finish: 127 | cursor on 128 | cls 129 | 130 | print "Your score was: " ; 131 | print s 132 | print "Press Esc to finish" 133 | 134 | escloop: 135 | waitkey x 136 | if x = 27 then end 137 | goto escloop 138 | 139 | 140 | setupscreen: 141 | move 0 0 142 | for x = 0 to 78 143 | print "+" ; 144 | next x 145 | 146 | move 0 24 147 | for x = 0 to 78 148 | print "+" ; 149 | next x 150 | 151 | move 0 0 152 | for y = 0 to 24 153 | move 0 y 154 | print "+" ; 155 | next y 156 | 157 | move 78 0 158 | for y = 0 to 24 159 | move 78 y 160 | print "+" ; 161 | next y 162 | 163 | return 164 | 165 | -------------------------------------------------------------------------------- /programs/fileman.asm: -------------------------------------------------------------------------------- 1 | ; ------------------------------------------------------------------ 2 | ; Simple file manager for MikeOS: copy, delete and rename files 3 | ; ------------------------------------------------------------------ 4 | 5 | 6 | BITS 16 7 | %INCLUDE "mikedev.inc" 8 | ORG 32768 9 | 10 | 11 | ; This is the point used by the disk buffer in the MikeOS kernel 12 | ; code; it's 24K after the kernel start, and therefore 8K before 13 | ; the point where programs are loaded (32K): 14 | 15 | disk_buffer equ 24576 16 | 17 | 18 | start: 19 | call .draw_background 20 | 21 | mov ax, .command_list ; Draw list of disk operations 22 | mov bx, .help_msg1 23 | mov cx, .help_msg2 24 | call os_list_dialog 25 | 26 | jc near .exit ; User pressed Esc? 27 | 28 | cmp ax, 1 ; Otherwise respond to choice 29 | je near .delete_file 30 | 31 | cmp ax, 2 32 | je near .rename_file 33 | 34 | cmp ax, 3 35 | je near .copy_file 36 | 37 | cmp ax, 4 38 | je near .file_size 39 | 40 | cmp ax, 5 41 | je near .disk_info 42 | 43 | 44 | 45 | .delete_file: 46 | call .draw_background 47 | 48 | call os_file_selector ; Get filename from user 49 | jc .no_delete_file_selected ; If Esc pressed, quit out 50 | 51 | push ax ; Save filename for now 52 | 53 | call .draw_background 54 | 55 | mov ax, .delete_confirm_msg ; Confirm delete operation 56 | mov bx, 0 57 | mov cx, 0 58 | mov dx, 1 59 | call os_dialog_box 60 | 61 | cmp ax, 0 62 | je .ok_to_delete 63 | 64 | pop ax 65 | jmp .delete_file 66 | 67 | .ok_to_delete: 68 | pop ax 69 | call os_remove_file 70 | jc near .writing_error 71 | 72 | 73 | 74 | .no_delete_file_selected: 75 | jmp start 76 | 77 | 78 | 79 | .rename_file: 80 | call .draw_background 81 | 82 | call os_file_selector ; Get filename from user 83 | jc .no_rename_file_selected ; If Esc pressed, quit out 84 | 85 | mov si, ax ; And store it 86 | mov di, .filename_tmp1 87 | call os_string_copy 88 | 89 | .retry_rename: 90 | call .draw_background 91 | 92 | mov bx, .filename_msg ; Get second filename 93 | mov ax, .filename_input 94 | call os_input_dialog 95 | 96 | mov si, ax ; Store it for later 97 | mov di, .filename_tmp2 98 | call os_string_copy 99 | 100 | mov ax, di ; Does the second filename already exist? 101 | call os_file_exists 102 | jnc .rename_fail ; Quit out if so 103 | 104 | mov ax, .filename_tmp1 105 | mov bx, .filename_tmp2 106 | 107 | call os_rename_file 108 | jc near .writing_error 109 | 110 | jmp start 111 | 112 | 113 | .rename_fail: 114 | mov ax, .err_file_exists 115 | mov bx, 0 116 | mov cx, 0 117 | mov dx, 0 118 | call os_dialog_box 119 | jmp .retry_rename 120 | 121 | 122 | .no_rename_file_selected: 123 | jmp start 124 | 125 | 126 | .copy_file: 127 | call .draw_background 128 | 129 | call os_file_selector ; Get filename from user 130 | jc .no_copy_file_selected 131 | 132 | mov si, ax ; And store it 133 | mov di, .filename_tmp1 134 | call os_string_copy 135 | 136 | call .draw_background 137 | 138 | mov bx, .filename_msg ; Get second filename 139 | mov ax, .filename_input 140 | call os_input_dialog 141 | 142 | mov si, ax 143 | mov di, .filename_tmp2 144 | call os_string_copy 145 | 146 | mov ax, .filename_tmp1 147 | mov bx, .filename_tmp2 148 | 149 | mov cx, 36864 ; 4K after FILEMAN.BIN load position 150 | call os_load_file 151 | 152 | cmp bx, 28672 ; Is file to copy bigger than 28K? 153 | jg .copy_file_too_big 154 | 155 | mov cx, bx ; Otherwise write out the copy 156 | mov bx, 36864 157 | mov ax, .filename_tmp2 158 | call os_write_file 159 | 160 | jc near .writing_error 161 | 162 | jmp start 163 | 164 | .no_copy_file_selected: 165 | jmp start 166 | 167 | .copy_file_too_big: ; If file bigger than 28K 168 | call .draw_background 169 | mov ax, .err_too_large_msg 170 | mov bx, 0 171 | mov cx, 0 172 | mov dx, 0 173 | call os_dialog_box 174 | jmp start 175 | 176 | 177 | 178 | .file_size: 179 | call .draw_background 180 | 181 | call os_file_selector ; Get filename from user 182 | jc .no_rename_file_selected ; If Esc pressed, quit out 183 | 184 | call os_get_file_size 185 | 186 | mov ax, bx ; Move size into AX for conversion 187 | call os_int_to_string 188 | mov bx, ax ; Size into second line of dialog box... 189 | 190 | mov ax, .size_msg 191 | mov cx, 0 192 | mov dx, 0 193 | call os_dialog_box 194 | 195 | jmp start 196 | 197 | 198 | .disk_info: 199 | mov cx, 1 ; Load first disk sector into RAM 200 | mov dx, 0 201 | mov bx, disk_buffer 202 | 203 | mov ah, 2 204 | mov al, 1 205 | stc 206 | int 13h ; BIOS load sector call 207 | 208 | mov si, disk_buffer + 2Bh ; Disk label starts here 209 | 210 | mov di, .tmp_string1 211 | mov cx, 11 ; Copy 11 chars of it 212 | rep movsb 213 | 214 | mov byte [di], 0 ; Zero-terminate it 215 | 216 | mov si, disk_buffer + 36h ; Filesystem string starts here 217 | 218 | mov di, .tmp_string2 219 | mov cx, 8 ; Copy 8 chars of it 220 | rep movsb 221 | 222 | mov byte [di], 0 ; Zero-terminate it 223 | 224 | mov ax, .label_string_text ; Add results to info strings 225 | mov bx, .tmp_string1 226 | mov cx, .label_string_full 227 | call os_string_join 228 | 229 | mov ax, .fstype_string_text 230 | mov bx, .tmp_string2 231 | mov cx, .fstype_string_full 232 | call os_string_join 233 | 234 | call .draw_background 235 | 236 | mov ax, .label_string_full ; Show the info 237 | mov bx, .fstype_string_full 238 | mov cx, 0 239 | mov dx, 0 240 | call os_dialog_box 241 | 242 | jmp start 243 | 244 | 245 | .writing_error: 246 | call .draw_background 247 | mov ax, .error_msg 248 | mov bx, .error_msg2 249 | mov cx, 0 250 | mov dx, 0 251 | call os_dialog_box 252 | jmp start 253 | 254 | 255 | .exit: 256 | call os_clear_screen 257 | ret 258 | 259 | 260 | .draw_background: 261 | mov ax, .title_msg 262 | mov bx, .footer_msg 263 | mov cx, 00100000b 264 | call os_draw_background 265 | ret 266 | 267 | 268 | .command_list db 'Delete a file,Rename a file,Copy a file,Show file size,Show disk info', 0 269 | 270 | .help_msg1 db 'Select a file operation to perform,', 0 271 | .help_msg2 db 'or press the Esc key to exit...', 0 272 | 273 | .title_msg db 'MikeOS File Manager', 0 274 | .footer_msg db 'Copy, rename and delete files', 0 275 | 276 | .label_string_text db 'Filesystem label: ', 0 277 | .label_string_full times 30 db 0 278 | 279 | .fstype_string_text db 'Filesystem type: ', 0 280 | .fstype_string_full times 30 db 0 281 | 282 | .delete_confirm_msg db 'Are you sure?', 0 283 | 284 | .filename_msg db 'Enter filename with extension (eg FOO.BAR):', 0 285 | .filename_input times 255 db 0 286 | .filename_tmp1 times 15 db 0 287 | .filename_tmp2 times 15 db 0 288 | 289 | .size_msg db 'File size (in bytes):', 0 290 | 291 | .error_msg db 'Error writing to the disk!', 0 292 | .error_msg2 db 'Read-only media, or file exists!', 0 293 | .err_too_large_msg db 'File too large (max 24K)!', 0 294 | .err_file_exists db 'File of that name exists!', 0 295 | 296 | .tmp_string1 times 15 db 0 297 | .tmp_string2 times 15 db 0 298 | 299 | 300 | ; ------------------------------------------------------------------ 301 | 302 | -------------------------------------------------------------------------------- /programs/fileman.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mig-hub/mikeOS/685306a87ddf1a41c069ec7670d24c7d2023ff20/programs/fileman.bin -------------------------------------------------------------------------------- /programs/fisher.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mig-hub/mikeOS/685306a87ddf1a41c069ec7670d24c7d2023ff20/programs/fisher.bin -------------------------------------------------------------------------------- /programs/forth.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mig-hub/mikeOS/685306a87ddf1a41c069ec7670d24c7d2023ff20/programs/forth.bin -------------------------------------------------------------------------------- /programs/hangman.asm: -------------------------------------------------------------------------------- 1 | ; ------------------------------------------------------------------ 2 | ; Geography-based hangman game for MikeOS 3 | ; 4 | ; At the end of this file you'll see a list of 256 cities (in 5 | ; lower-case to make the game code simpler). We get one city at 6 | ; random from the list and store it in a string. 7 | ; 8 | ; Next, we create another string of the same size, but with underscore 9 | ; characters instead of the real ones. We display this 'work' string to 10 | ; the player, who tries to guess characters. If s/he gets a char right, 11 | ; it is revealed in the work string. 12 | ; 13 | ; If s/he gets gets a char wrong, we add it to a list of misses, and 14 | ; draw more of the hanging man. Poor bloke. 15 | ; ------------------------------------------------------------------ 16 | 17 | 18 | BITS 16 19 | %INCLUDE "mikedev.inc" 20 | ORG 32768 21 | 22 | 23 | start: 24 | call os_hide_cursor 25 | 26 | 27 | ; First, reset values in case user is playing multiple games 28 | 29 | mov di, real_string ; Full city name 30 | mov al, 0 31 | mov cx, 50 32 | rep stosb 33 | 34 | mov di, work_string ; String that starts as '_' characters 35 | mov al, 0 36 | mov cx, 50 37 | rep stosb 38 | 39 | mov di, tried_chars ; Chars the user has tried, but aren't in the real string 40 | mov al, 0 41 | mov cx, 255 42 | rep stosb 43 | 44 | mov byte [tried_chars_pos], 0 45 | mov byte [misses], 1 ; First miss is to show the platform 46 | 47 | 48 | mov ax, title_msg ; Set up the screen 49 | mov bx, footer_msg 50 | mov cx, 01100000b 51 | call os_draw_background 52 | 53 | mov ax, 0 54 | mov bx, 255 55 | call os_get_random ; Get a random number 56 | 57 | mov bl, cl ; Store in BL 58 | 59 | 60 | mov si, cities ; Skip number of lines stored in BL 61 | skip_loop: 62 | cmp bl, 0 63 | je skip_finished 64 | dec bl 65 | .inner: 66 | lodsb ; Find a zero to denote end of line 67 | cmp al, 0 68 | jne .inner 69 | jmp skip_loop 70 | 71 | 72 | skip_finished: 73 | mov di, real_string ; Store the string from the city list 74 | call os_string_copy 75 | 76 | mov ax, si 77 | call os_string_length 78 | 79 | mov dx, ax ; DX = number of '_' characters to show 80 | 81 | call add_underscores 82 | 83 | 84 | cmp dx, 5 ; Give first char if it's a short string 85 | ja no_hint 86 | 87 | mov ax, hint_msg_1 ; Tell player about the hint 88 | mov bx, hint_msg_2 89 | mov cx, 0 90 | mov dx, 0 91 | call os_dialog_box 92 | 93 | call os_hide_cursor 94 | 95 | mov ax, title_msg ; Redraw screen 96 | mov bx, footer_msg 97 | mov cx, 01100000b 98 | call os_draw_background 99 | 100 | mov byte al, [real_string] ; Copy first letter over 101 | mov byte [work_string], al 102 | 103 | 104 | no_hint: 105 | call fix_spaces ; Add spaces to working string if necessary 106 | 107 | main_loop: 108 | call show_tried_chars ; Update screen areas 109 | call show_hangman 110 | call show_main_box 111 | 112 | cmp byte [misses], 11 ; See if the player has lost 113 | je lost_game 114 | 115 | call os_wait_for_key ; Get input 116 | 117 | cmp al, KEY_ESC 118 | je finish 119 | 120 | cmp al, 122 ; Work with just "a" to "z" keys 121 | ja main_loop 122 | 123 | cmp al, 97 124 | jb main_loop 125 | 126 | mov bl, al ; Store character temporarily 127 | 128 | mov cx, 0 ; Counter into string 129 | mov dl, 0 ; Flag whether char was found 130 | mov si, real_string 131 | find_loop: 132 | lodsb 133 | cmp al, 0 ; End of string? 134 | je done_find 135 | cmp al, bl ; Find char entered in string 136 | je found_char 137 | inc cx ; Move on to next character 138 | jmp find_loop 139 | 140 | 141 | 142 | found_char: 143 | inc dl ; Note that at least one char match was found 144 | mov di, work_string 145 | add di, cx ; Update our underscore string with char found 146 | mov byte [di], bl 147 | inc cx 148 | jmp find_loop 149 | 150 | 151 | done_find: 152 | mov si, real_string ; If the strings match, the player has won! 153 | mov di, work_string 154 | call os_string_compare 155 | jc won_game 156 | 157 | cmp dl, 0 ; If char was found, skip next bit 158 | jne main_loop 159 | 160 | call update_tried_chars ; Otherwise add char to list of misses 161 | 162 | jmp main_loop 163 | 164 | 165 | won_game: 166 | call show_win_msg 167 | .loop: 168 | call os_wait_for_key ; Wait for keypress 169 | cmp al, KEY_ESC 170 | je finish 171 | cmp al, KEY_ENTER 172 | jne .loop 173 | jmp start 174 | 175 | 176 | lost_game: ; After too many misses... 177 | call show_lose_msg 178 | .loop: ; Wait for keypress 179 | call os_wait_for_key 180 | cmp al, KEY_ESC 181 | je finish 182 | cmp al, KEY_ENTER 183 | jne .loop 184 | jmp start 185 | 186 | 187 | finish: 188 | call os_show_cursor 189 | call os_clear_screen 190 | 191 | ret 192 | 193 | 194 | 195 | 196 | add_underscores: ; Create string of underscores 197 | mov di, work_string 198 | mov al, '_' 199 | mov cx, dx ; Size of string 200 | rep stosb 201 | ret 202 | 203 | 204 | 205 | ; Copy any spaces from the real string into the work string 206 | 207 | fix_spaces: 208 | mov si, real_string 209 | mov di, work_string 210 | .loop: 211 | lodsb 212 | cmp al, 0 213 | je .done 214 | cmp al, ' ' 215 | jne .no_space 216 | mov byte [di], ' ' 217 | .no_space: 218 | inc di 219 | jmp .loop 220 | .done: 221 | ret 222 | 223 | 224 | 225 | ; Here we check the list of wrong chars that the player entered previously, 226 | ; and see if the latest addition is already in there... 227 | 228 | update_tried_chars: 229 | mov si, tried_chars 230 | mov al, bl 231 | call os_find_char_in_string 232 | cmp ax, 0 233 | jne .nothing_to_add ; Skip next bit if char was already in list 234 | 235 | mov si, tried_chars 236 | mov ax, 0 237 | mov byte al, [tried_chars_pos] ; Move into the list 238 | add si, ax 239 | mov byte [si], bl 240 | inc byte [tried_chars_pos] 241 | 242 | inc byte [misses] ; Knock up the score 243 | .nothing_to_add: 244 | ret 245 | 246 | 247 | show_main_box: 248 | pusha 249 | mov bl, BLACK_ON_WHITE 250 | mov dh, 5 251 | mov dl, 2 252 | mov si, 36 253 | mov di, 21 254 | call os_draw_block 255 | 256 | mov dh, 7 257 | mov dl, 4 258 | call os_move_cursor 259 | mov si, help_msg_1 260 | call os_print_string 261 | 262 | mov dh, 8 263 | mov dl, 4 264 | call os_move_cursor 265 | mov si, help_msg_2 266 | call os_print_string 267 | 268 | mov dh, 17 269 | mov dl, 4 270 | call os_move_cursor 271 | mov si, help_msg_3 272 | call os_print_string 273 | 274 | mov dh, 18 275 | mov dl, 4 276 | call os_move_cursor 277 | mov si, help_msg_4 278 | call os_print_string 279 | 280 | mov dh, 12 281 | mov dl, 6 282 | call os_move_cursor 283 | mov si, work_string 284 | call os_print_string 285 | 286 | popa 287 | ret 288 | 289 | 290 | show_tried_chars: 291 | pusha 292 | mov bl, BLACK_ON_WHITE 293 | mov dh, 18 294 | mov dl, 40 295 | mov si, 39 296 | mov di, 23 297 | call os_draw_block 298 | 299 | mov dh, 19 300 | mov dl, 41 301 | call os_move_cursor 302 | 303 | mov si, tried_chars_msg 304 | call os_print_string 305 | 306 | mov dh, 21 307 | mov dl, 41 308 | call os_move_cursor 309 | 310 | mov si, tried_chars 311 | call os_print_string 312 | 313 | popa 314 | ret 315 | 316 | 317 | 318 | show_win_msg: 319 | mov bl, WHITE_ON_GREEN 320 | mov dh, 14 321 | mov dl, 5 322 | mov si, 30 323 | mov di, 15 324 | call os_draw_block 325 | 326 | mov dh, 14 327 | mov dl, 6 328 | call os_move_cursor 329 | 330 | mov si, .win_msg 331 | call os_print_string 332 | 333 | mov dh, 12 334 | mov dl, 6 335 | call os_move_cursor 336 | mov si, real_string 337 | call os_print_string 338 | 339 | ret 340 | 341 | 342 | .win_msg db 'Yay! Hit enter to play again', 0 343 | 344 | 345 | 346 | show_lose_msg: 347 | mov bl, WHITE_ON_LIGHT_RED 348 | mov dh, 14 349 | mov dl, 5 350 | mov si, 30 351 | mov di, 15 352 | call os_draw_block 353 | 354 | mov dh, 14 355 | mov dl, 6 356 | call os_move_cursor 357 | 358 | mov si, .lose_msg 359 | call os_print_string 360 | 361 | mov dh, 12 362 | mov dl, 6 363 | call os_move_cursor 364 | mov si, real_string 365 | call os_print_string 366 | 367 | ret 368 | 369 | 370 | .lose_msg db 'Doh! Hit enter to play again', 0 371 | 372 | 373 | 374 | ; Draw the hangman box and appropriate bits depending on the number of misses 375 | 376 | show_hangman: 377 | pusha 378 | 379 | mov bl, BLACK_ON_WHITE 380 | mov dh, 2 381 | mov dl, 42 382 | mov si, 35 383 | mov di, 17 384 | call os_draw_block 385 | 386 | 387 | cmp byte [misses], 0 388 | je near .0 389 | cmp byte [misses], 1 390 | je near .1 391 | cmp byte [misses], 2 392 | je near .2 393 | cmp byte [misses], 3 394 | je near .3 395 | cmp byte [misses], 4 396 | je near .4 397 | cmp byte [misses], 5 398 | je near .5 399 | cmp byte [misses], 6 400 | je near .6 401 | cmp byte [misses], 7 402 | je near .7 403 | cmp byte [misses], 8 404 | je near .8 405 | cmp byte [misses], 9 406 | je near .9 407 | cmp byte [misses], 10 408 | je near .10 409 | cmp byte [misses], 11 410 | je near .11 411 | 412 | .11: ; Right leg 413 | mov dh, 10 414 | mov dl, 64 415 | call os_move_cursor 416 | mov si, .11_t 417 | call os_print_string 418 | 419 | .10: ; Left leg 420 | mov dh, 10 421 | mov dl, 62 422 | call os_move_cursor 423 | mov si, .10_t 424 | call os_print_string 425 | 426 | .9: ; Torso 427 | mov dh, 9 428 | mov dl, 63 429 | call os_move_cursor 430 | mov si, .9_t 431 | call os_print_string 432 | 433 | .8: ; Arms 434 | mov dh, 8 435 | mov dl, 62 436 | call os_move_cursor 437 | mov si, .8_t 438 | call os_print_string 439 | 440 | .7: ; Head 441 | mov dh, 7 442 | mov dl, 63 443 | call os_move_cursor 444 | mov si, .7_t 445 | call os_print_string 446 | 447 | .6: ; Rope 448 | mov dh, 6 449 | mov dl, 63 450 | call os_move_cursor 451 | mov si, .6_t 452 | call os_print_string 453 | 454 | .5: ; Beam 455 | mov dh, 5 456 | mov dl, 56 457 | call os_move_cursor 458 | mov si, .5_t 459 | call os_print_string 460 | 461 | .4: ; Support for beam 462 | mov dh, 6 463 | mov dl, 57 464 | call os_move_cursor 465 | mov si, .4_t 466 | call os_print_string 467 | 468 | .3: ; Pole 469 | mov dh, 12 470 | mov dl, 56 471 | call os_move_cursor 472 | mov si, .3_t 473 | call os_print_string 474 | mov dh, 11 475 | mov dl, 56 476 | call os_move_cursor 477 | call os_print_string 478 | mov dh, 10 479 | mov dl, 56 480 | call os_move_cursor 481 | call os_print_string 482 | mov dh, 9 483 | mov dl, 56 484 | call os_move_cursor 485 | call os_print_string 486 | mov dh, 8 487 | mov dl, 56 488 | call os_move_cursor 489 | call os_print_string 490 | mov dh, 7 491 | mov dl, 56 492 | call os_move_cursor 493 | call os_print_string 494 | mov dh, 6 495 | mov dl, 56 496 | call os_move_cursor 497 | call os_print_string 498 | 499 | .2: ; Support for pole 500 | mov dh, 13 501 | mov dl, 55 502 | call os_move_cursor 503 | mov si, .2_t 504 | call os_print_string 505 | 506 | .1: ; Ground 507 | mov dh, 14 508 | mov dl, 53 509 | call os_move_cursor 510 | mov si, .1_t 511 | call os_print_string 512 | 513 | 514 | .0: 515 | popa 516 | ret 517 | 518 | 519 | .1_t db '-------------', 0 520 | .2_t db '/|\', 0 521 | .3_t db '|', 0 522 | .4_t db '/', 0 523 | .5_t db '________', 0 524 | .6_t db '|', 0 525 | .7_t db 'O', 0 526 | .8_t db '---', 0 527 | .9_t db '|', 0 528 | .10_t db '/', 0 529 | .11_t db '\', 0 530 | 531 | 532 | 533 | title_msg db 'MikeOS Hangman', 0 534 | footer_msg db 'Press Esc to exit', 0 535 | 536 | hint_msg_1 db 'Short word this time, so you', 0 537 | hint_msg_2 db 'get the first letter for free!', 0 538 | 539 | help_msg_1 db 'Can you guess the city name', 0 540 | help_msg_2 db 'that fits the spaces beneath?', 0 541 | help_msg_3 db 'Press keys to guess letters,', 0 542 | help_msg_4 db 'but you only have 10 chances!', 0 543 | 544 | real_string times 50 db 0 545 | work_string times 50 db 0 546 | 547 | tried_chars_msg db 'Tried characters...', 0 548 | tried_chars_pos db 0 549 | tried_chars times 255 db 0 550 | 551 | misses db 1 552 | 553 | 554 | 555 | cities: 556 | 557 | db 'kabul', 0 558 | db 'tirane', 0 559 | db 'algiers', 0 560 | db 'andorra la vella', 0 561 | db 'luanda', 0 562 | db 'saint johns', 0 563 | db 'buenos aires', 0 564 | db 'yerevan', 0 565 | db 'canberra', 0 566 | db 'adelaide', 0 567 | db 'melbourne', 0 568 | db 'vienna', 0 569 | db 'baku', 0 570 | db 'nassau', 0 571 | db 'manama', 0 572 | db 'dhaka', 0 573 | db 'bridgetown', 0 574 | db 'minsk', 0 575 | db 'brussels', 0 576 | db 'belmopan', 0 577 | db 'porto novo', 0 578 | db 'thimpu', 0 579 | db 'sucre', 0 580 | db 'sarajevo', 0 581 | db 'gaborone', 0 582 | db 'brasilia', 0 583 | db 'bandar seri begawan', 0 584 | db 'sofia', 0 585 | db 'ouagadougou', 0 586 | db 'bujumbura', 0 587 | db 'phnom penh', 0 588 | db 'yaounde', 0 589 | db 'ottawa', 0 590 | db 'praia', 0 591 | db 'bangui', 0 592 | db 'ndjamema', 0 593 | db 'santiago', 0 594 | db 'beijing', 0 595 | db 'bogota', 0 596 | db 'moroni', 0 597 | db 'brazzaville', 0 598 | db 'kinshasa', 0 599 | db 'san jose', 0 600 | db 'yamoussoukro', 0 601 | db 'zagreb', 0 602 | db 'havana', 0 603 | db 'nicosia', 0 604 | db 'prague', 0 605 | db 'copenhagen', 0 606 | db 'djibouti', 0 607 | db 'roseau', 0 608 | db 'santo domingo', 0 609 | db 'dili', 0 610 | db 'quito', 0 611 | db 'cairo', 0 612 | db 'san salvador', 0 613 | db 'malabo', 0 614 | db 'asmara', 0 615 | db 'tallinn', 0 616 | db 'addis ababa', 0 617 | db 'suva', 0 618 | db 'helsinki', 0 619 | db 'paris', 0 620 | db 'libreville', 0 621 | db 'banjul', 0 622 | db 'tbilisi', 0 623 | db 'berlin', 0 624 | db 'accra', 0 625 | db 'athens', 0 626 | db 'saint georges', 0 627 | db 'guatemala city', 0 628 | db 'conakry', 0 629 | db 'bissau', 0 630 | db 'georgetown', 0 631 | db 'port au prince', 0 632 | db 'tegucigalpa', 0 633 | db 'budapest', 0 634 | db 'reykjavik', 0 635 | db 'new delhi', 0 636 | db 'jakarta', 0 637 | db 'baghdad', 0 638 | db 'dublin', 0 639 | db 'jerusalem', 0 640 | db 'rome', 0 641 | db 'kingston', 0 642 | db 'tokyo', 0 643 | db 'amman', 0 644 | db 'astana', 0 645 | db 'nairobi', 0 646 | db 'tarawa atoll', 0 647 | db 'pyongyang', 0 648 | db 'seoul', 0 649 | db 'pristina', 0 650 | db 'kuwait city', 0 651 | db 'bishkek', 0 652 | db 'vientiane', 0 653 | db 'riga', 0 654 | db 'beirut', 0 655 | db 'maseru', 0 656 | db 'monrovia', 0 657 | db 'tripoli', 0 658 | db 'vaduz', 0 659 | db 'vilnius', 0 660 | db 'luxembourg', 0 661 | db 'skopje', 0 662 | db 'antananarivo', 0 663 | db 'lilongwe', 0 664 | db 'kuala lumpur', 0 665 | db 'male', 0 666 | db 'bamako', 0 667 | db 'valletta', 0 668 | db 'majuro', 0 669 | db 'nouakchott', 0 670 | db 'port louis', 0 671 | db 'mexico city', 0 672 | db 'palikir', 0 673 | db 'chisinau', 0 674 | db 'monaco', 0 675 | db 'ulaanbaatar', 0 676 | db 'podgorica', 0 677 | db 'rabat', 0 678 | db 'maputo', 0 679 | db 'rangoon', 0 680 | db 'windhoek', 0 681 | db 'yaren district', 0 682 | db 'kathmandu', 0 683 | db 'amsterdam', 0 684 | db 'the hague', 0 685 | db 'wellington', 0 686 | db 'managua', 0 687 | db 'niamey', 0 688 | db 'abuja', 0 689 | db 'lagos', 0 690 | db 'oslo', 0 691 | db 'bergen', 0 692 | db 'stavanger', 0 693 | db 'muscat', 0 694 | db 'islamabad', 0 695 | db 'karachi', 0 696 | db 'melekeok', 0 697 | db 'panama city', 0 698 | db 'port moresby', 0 699 | db 'asuncion', 0 700 | db 'lima', 0 701 | db 'manila', 0 702 | db 'warsaw', 0 703 | db 'lisbon', 0 704 | db 'doha', 0 705 | db 'bucharest', 0 706 | db 'moscow', 0 707 | db 'kigali', 0 708 | db 'basseterre', 0 709 | db 'castries', 0 710 | db 'kingstown', 0 711 | db 'apia', 0 712 | db 'san marino', 0 713 | db 'sao tome', 0 714 | db 'riyadh', 0 715 | db 'dakar', 0 716 | db 'belgrade', 0 717 | db 'victoria', 0 718 | db 'freetown', 0 719 | db 'singapore', 0 720 | db 'bratislava', 0 721 | db 'ljubljana', 0 722 | db 'honiara', 0 723 | db 'mogadishu', 0 724 | db 'pretoria', 0 725 | db 'bloemfontein', 0 726 | db 'madrid', 0 727 | db 'colombo', 0 728 | db 'khartoum', 0 729 | db 'paramaribo', 0 730 | db 'mbabane', 0 731 | db 'stockholm', 0 732 | db 'bern', 0 733 | db 'geneva', 0 734 | db 'zurich', 0 735 | db 'damascus', 0 736 | db 'taipei', 0 737 | db 'dushanbe', 0 738 | db 'dar es salaam', 0 739 | db 'bangkok', 0 740 | db 'lome', 0 741 | db 'nukualofa', 0 742 | db 'port of spain', 0 743 | db 'tunis', 0 744 | db 'ankara', 0 745 | db 'ashgabat', 0 746 | db 'funafuti', 0 747 | db 'kampala', 0 748 | db 'kiev', 0 749 | db 'abu dhabi', 0 750 | db 'dubai', 0 751 | db 'london', 0 752 | db 'washington', 0 753 | db 'montevideo', 0 754 | db 'tashkent', 0 755 | db 'port vila', 0 756 | db 'vatican city', 0 757 | db 'caracas', 0 758 | db 'hanoi', 0 759 | db 'sanaa', 0 760 | db 'lusaka', 0 761 | db 'harare', 0 762 | db 'st petersburg', 0 763 | db 'odessa', 0 764 | db 'manchester', 0 765 | db 'liverpool', 0 766 | db 'birmingham', 0 767 | db 'frankfurt', 0 768 | db 'munich', 0 769 | db 'dortmund', 0 770 | db 'new york', 0 771 | db 'chicago', 0 772 | db 'san francisco', 0 773 | db 'los angeles', 0 774 | db 'las vegas', 0 775 | db 'boston', 0 776 | db 'new jersey', 0 777 | db 'dallas', 0 778 | db 'atlanta', 0 779 | db 'miami', 0 780 | db 'vancouver', 0 781 | db 'toronto', 0 782 | db 'saopaulo', 0 783 | db 'rio de janeiro', 0 784 | db 'vladivostok', 0 785 | db 'glasgow', 0 786 | db 'edinburgh', 0 787 | db 'lyon', 0 788 | db 'venice', 0 789 | db 'torshavn', 0 790 | db 'nuuk', 0 791 | db 'bristol', 0 792 | db 'york', 0 793 | db 'tel aviv', 0 794 | db 'seattle', 0 795 | db 'stuttgart', 0 796 | db 'osaka', 0 797 | db 'kyoto', 0 798 | db 'sapporo', 0 799 | db 'kagoshima', 0 800 | db 'shanghai', 0 801 | db 'chongqing', 0 802 | db 'hong kong', 0 803 | db 'macao', 0 804 | db 'xian', 0 805 | db 'lhasa', 0 806 | db 'warrington', 0 807 | db 'leeds', 0 808 | db 'luxor', 0 809 | db 'timbuktu', 0 810 | db 'honolulu', 0 811 | db 'bordeaux', 0 812 | db 'cupertino', 0 813 | 814 | 815 | ; ------------------------------------------------------------------ 816 | 817 | -------------------------------------------------------------------------------- /programs/hangman.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mig-hub/mikeOS/685306a87ddf1a41c069ec7670d24c7d2023ff20/programs/hangman.bin -------------------------------------------------------------------------------- /programs/keyboard.asm: -------------------------------------------------------------------------------- 1 | ; ------------------------------------------------------------------ 2 | ; Music keyboard -- Use the keyboard to play notes via the PC speaker 3 | ; Use Z key rightwards for an octave 4 | ; ------------------------------------------------------------------ 5 | 6 | 7 | BITS 16 8 | %INCLUDE "mikedev.inc" 9 | ORG 32768 10 | 11 | 12 | start: 13 | call os_hide_cursor 14 | 15 | call os_clear_screen 16 | 17 | mov ax, mus_kbd_title_msg ; Set up screen 18 | mov bx, mus_kbd_footer_msg 19 | mov cx, WHITE_ON_LIGHT_RED 20 | call os_draw_background 21 | 22 | mov bl, BLACK_ON_WHITE ; White block to draw keyboard on 23 | mov dh, 4 24 | mov dl, 5 25 | mov si, 69 26 | mov di, 21 27 | call os_draw_block 28 | 29 | 30 | 31 | ; Now lots of loops to draw the keyboard 32 | 33 | mov dl, 24 ; Top line of box 34 | mov dh, 6 35 | call os_move_cursor 36 | 37 | mov ah, 0Eh 38 | mov al, 196 39 | 40 | mov cx, 31 41 | .loop1: 42 | int 10h 43 | loop .loop1 44 | 45 | 46 | mov dl, 24 ; Bottom line of box 47 | mov dh, 18 48 | call os_move_cursor 49 | 50 | mov ah, 0Eh 51 | mov al, 196 52 | 53 | mov cx, 31 54 | .loop2: 55 | int 10h 56 | loop .loop2 57 | 58 | 59 | 60 | mov dl, 23 ; Top-left corner 61 | mov dh, 6 62 | call os_move_cursor 63 | 64 | mov al, 218 65 | int 10h 66 | 67 | 68 | mov dl, 55 ; Top-right corner 69 | mov dh, 6 70 | call os_move_cursor 71 | 72 | mov al, 191 73 | int 10h 74 | 75 | 76 | mov dl, 23 ; Bottom-left corner 77 | mov dh, 18 78 | call os_move_cursor 79 | 80 | mov al, 192 81 | int 10h 82 | 83 | 84 | mov dl, 55 ; Bottom-right corner 85 | mov dh, 18 86 | call os_move_cursor 87 | 88 | mov al, 217 89 | int 10h 90 | 91 | 92 | mov dl, 23 ; Left-hand box line 93 | mov dh, 7 94 | mov al, 179 95 | .loop3: 96 | call os_move_cursor 97 | int 10h 98 | inc dh 99 | cmp dh, 18 100 | jne .loop3 101 | 102 | 103 | mov dl, 55 ; Right-hand box line 104 | mov dh, 7 105 | mov al, 179 106 | .loop4: 107 | call os_move_cursor 108 | int 10h 109 | inc dh 110 | cmp dh, 18 111 | jne .loop4 112 | 113 | 114 | mov dl, 23 ; Key-separating lines 115 | .biggerloop: 116 | add dl, 4 117 | mov dh, 7 118 | mov al, 179 119 | .loop5: 120 | call os_move_cursor 121 | int 10h 122 | inc dh 123 | cmp dh, 18 124 | jne .loop5 125 | cmp dl, 51 126 | jne .biggerloop 127 | 128 | 129 | mov al, 194 ; Top of box line joiners 130 | mov dh, 6 131 | mov dl, 27 132 | .loop6: 133 | call os_move_cursor 134 | int 10h 135 | add dl, 4 136 | cmp dl, 55 137 | jne .loop6 138 | 139 | 140 | mov al, 193 ; Bottom of box line joiners 141 | mov dh, 18 142 | mov dl, 27 143 | .loop7: 144 | call os_move_cursor 145 | int 10h 146 | add dl, 4 147 | cmp dl, 55 148 | jne .loop7 149 | 150 | 151 | ; And now for the black keys... 152 | 153 | mov bl, WHITE_ON_BLACK 154 | 155 | mov dh, 6 156 | mov dl, 26 157 | mov si, 3 158 | mov di, 13 159 | call os_draw_block 160 | 161 | mov dh, 6 162 | mov dl, 30 163 | mov si, 3 164 | mov di, 13 165 | call os_draw_block 166 | 167 | mov dh, 6 168 | mov dl, 38 169 | mov si, 3 170 | mov di, 13 171 | call os_draw_block 172 | 173 | mov dh, 6 174 | mov dl, 42 175 | mov si, 3 176 | mov di, 13 177 | call os_draw_block 178 | 179 | mov dh, 6 180 | mov dl, 46 181 | mov si, 3 182 | mov di, 13 183 | call os_draw_block 184 | 185 | 186 | 187 | ; And lastly, draw the labels on the keys indicating which 188 | ; (computer!) keys to press to get notes 189 | 190 | mov ah, 0Eh 191 | 192 | mov dh, 17 193 | mov dl, 25 194 | call os_move_cursor 195 | 196 | mov al, 'Z' 197 | int 10h 198 | 199 | add dl, 4 200 | call os_move_cursor 201 | mov al, 'X' 202 | int 10h 203 | 204 | add dl, 4 205 | call os_move_cursor 206 | mov al, 'C' 207 | int 10h 208 | 209 | add dl, 4 210 | call os_move_cursor 211 | mov al, 'V' 212 | int 10h 213 | 214 | add dl, 4 215 | call os_move_cursor 216 | mov al, 'B' 217 | int 10h 218 | 219 | add dl, 4 220 | call os_move_cursor 221 | mov al, 'N' 222 | int 10h 223 | 224 | add dl, 4 225 | call os_move_cursor 226 | mov al, 'M' 227 | int 10h 228 | 229 | add dl, 4 230 | call os_move_cursor 231 | mov al, ',' 232 | int 10h 233 | 234 | ; Now the accidentals... 235 | 236 | mov dh, 11 237 | mov dl, 27 238 | call os_move_cursor 239 | mov al, 'S' 240 | int 10h 241 | 242 | add dl, 4 243 | call os_move_cursor 244 | mov al, 'D' 245 | int 10h 246 | 247 | add dl, 8 248 | call os_move_cursor 249 | mov al, 'G' 250 | int 10h 251 | 252 | add dl, 4 253 | call os_move_cursor 254 | mov al, 'H' 255 | int 10h 256 | 257 | add dl, 4 258 | call os_move_cursor 259 | mov al, 'J' 260 | int 10h 261 | 262 | ; Phew! We've drawn all the keys now 263 | 264 | .retry: 265 | call os_wait_for_key 266 | 267 | .nokey: ; Matching keys with notes 268 | cmp al, 'z' 269 | jne .s 270 | mov ax, 4000 271 | mov bx, 0 272 | call os_speaker_tone 273 | jmp .retry 274 | .s: 275 | cmp al, 's' 276 | jne .x 277 | mov ax, 3800 278 | mov bx, 0 279 | call os_speaker_tone 280 | jmp .retry 281 | .x: 282 | cmp al, 'x' 283 | jne .d 284 | mov ax, 3600 285 | mov bx, 0 286 | call os_speaker_tone 287 | jmp .retry 288 | .d: 289 | cmp al, 'd' 290 | jne .c 291 | mov ax, 3400 292 | mov bx, 0 293 | call os_speaker_tone 294 | jmp .retry 295 | .c: 296 | cmp al, 'c' 297 | jne .v 298 | mov ax, 3200 299 | mov bx, 0 300 | call os_speaker_tone 301 | jmp .retry 302 | 303 | 304 | .v: 305 | cmp al, 'v' 306 | jne .g 307 | mov ax, 3000 308 | mov bx, 0 309 | call os_speaker_tone 310 | jmp .retry 311 | .g: 312 | cmp al, 'g' 313 | jne .b 314 | mov ax, 2850 315 | mov bx, 0 316 | call os_speaker_tone 317 | jmp .retry 318 | .b: 319 | cmp al, 'b' 320 | jne .h 321 | mov ax, 2700 322 | mov bx, 0 323 | call os_speaker_tone 324 | jmp .retry 325 | .h: 326 | cmp al, 'h' 327 | jne .n 328 | mov ax, 2550 329 | mov bx, 0 330 | call os_speaker_tone 331 | jmp .retry 332 | .n: 333 | cmp al, 'n' 334 | jne .j 335 | mov ax, 2400 336 | mov bx, 0 337 | call os_speaker_tone 338 | jmp .retry 339 | .j: 340 | cmp al, 'j' 341 | jne .m 342 | mov ax, 2250 343 | mov bx, 0 344 | call os_speaker_tone 345 | jmp .retry 346 | .m: 347 | cmp al, 'm' 348 | jne .comma 349 | mov ax, 2100 350 | mov bx, 0 351 | call os_speaker_tone 352 | jmp .retry 353 | 354 | .comma: 355 | cmp al, ',' 356 | jne .space 357 | mov ax, 2000 358 | mov bx, 0 359 | call os_speaker_tone 360 | jmp .retry 361 | 362 | .space: 363 | cmp al, ' ' 364 | jne .esc 365 | call os_speaker_off 366 | jmp .retry 367 | 368 | .esc: 369 | cmp al, 27 370 | je .end 371 | jmp .nowt 372 | 373 | .nowt: 374 | jmp .retry 375 | 376 | .end: 377 | call os_speaker_off 378 | 379 | call os_clear_screen 380 | 381 | call os_show_cursor 382 | 383 | ret ; Back to OS 384 | 385 | 386 | mus_kbd_title_msg db 'MikeOS Music Keyboard (PC speaker sound)', 0 387 | mus_kbd_footer_msg db 'Hit keys to play notes, space to silence a note, and Esc to quit', 0 388 | 389 | 390 | ; ------------------------------------------------------------------ 391 | 392 | -------------------------------------------------------------------------------- /programs/keyboard.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mig-hub/mikeOS/685306a87ddf1a41c069ec7670d24c7d2023ff20/programs/keyboard.bin -------------------------------------------------------------------------------- /programs/mbpp.bas: -------------------------------------------------------------------------------- 1 | REM >>>MIKEBASIC-PLUS-PLUS-LIBRARY<<< 2 | REM Library Version 3.2.3 3 | REM Copyright (C) Joshua Beck. 4 | REM Email: mikeosdeveloper@gmail.com 5 | REM Licenced under the GNU General Public Licence revision 3. 6 | REM Requires MikeOS version 4.3 or greater. 7 | 8 | REM See the wiki at: http://mikebasicplusplus.wikispot.org/ 9 | 10 | PRINT "MB++ Library version 3.2.3" 11 | END 12 | 13 | ANCITEXT: 14 | GOSUB SAVEVAR 15 | GOSUB SAVELOC 16 | ink c 17 | W = X 18 | POKE Y 65430 19 | CURSPOS X Y 20 | POKE X 65431 21 | DO 22 | IF X > W THEN X = 79 23 | if x > 78 then y = y + 1 24 | if x > 78 then peek x 65431 25 | PEEK J 65430 26 | IF Y > J THEN J = 0 27 | IF Y > 23 THEN J = 0 28 | move x y 29 | IF J > 0 THEN PEEK J V 30 | IF J = 0 THEN W = J + 1 31 | IF J < 20 THEN GOSUB ANCITXTS 32 | IF J > 0 THEN PRINT CHR J 33 | x = x + 1 34 | v = v + 1 35 | LOOP UNTIL W > J 36 | GOSUB LOADLOC 37 | GOSUB LOADVAR 38 | RETURN 39 | 40 | ANCITXTS: 41 | IF J = 0 THEN RETURN 42 | IF J = 1 THEN V = V + 1 43 | IF J = 1 THEN J = 255 44 | IF J = 7 THEN J = 255 45 | IF J = 10 THEN Y = Y + 1 46 | IF J = 10 THEN PEEK X 65431 47 | IF J = 10 THEN V = V + 1 48 | IF J = 10 THEN GOTO ANCITEX2 49 | RETURN 50 | 51 | ANICLOSE: 52 | FOR W = 1 TO 4 53 | READ ANICLOSC W J 54 | GOSUB BLOCKBOX 55 | PAUSE 1 56 | NEXT W 57 | RETURN 58 | 59 | ANICLOSC: 60 | 176 177 178 219 61 | 62 | ANIEND: 63 | GOSUB SAVEVAR 64 | FOR W = 1 TO 8 65 | READ ANIENDCH W J 66 | GOSUB BLOCKSCR 67 | PAUSE 1 68 | IF W = 4 THEN PAUSE 4 69 | NEXT W 70 | GOSUB LOADVAR 71 | RETURN 72 | 73 | ANIENDCH: 74 | 176 177 178 219 178 177 176 0 75 | 76 | ANIOPEN: 77 | GOSUB SAVEVAR 78 | FOR W = 1 TO 4 79 | READ ANIOPENCH W J 80 | GOSUB BLOCKBOX 81 | PAUSE 1 82 | NEXT W 83 | GOSUB LOADVAR 84 | RETURN 85 | 86 | ANIOPENCH: 87 | 219 178 177 176 88 | 89 | ANISTART: 90 | GOSUB SAVEVAR 91 | FOR W = 1 TO 11 92 | IF W < 9 THEN READ ANISTARC W J 93 | IF W < 9 THEN GOSUB BLOCKSCR 94 | V = W - 4 95 | IF W > 4 THEN READ ANISTARB V J 96 | IF W > 4 THEN GOSUB BLOCKBOR 97 | PAUSE 1 98 | IF W > 4 AND W < 9 THEN PAUSE 1 99 | IF W = 8 THEN GOSUB TITLE 100 | NEXT W 101 | GOSUB LOADVAR 102 | RETURN 103 | 104 | ANISTARC: 105 | 176 177 178 219 178 177 176 0 106 | ANISTARB: 107 | 219 219 219 219 178 177 176 108 | 109 | ARRAYGET: 110 | POKEINT J 65418 111 | IF X > 99 THEN $E = "ARRAYGET: Array over maximum" 112 | IF X > 99 THEN GOTO ERRBOX 113 | IF X < 0 THEN $E = "ARRAYGET: Number below zero" 114 | IF X < 0 THEN GOTO ERRBOX 115 | J = X 116 | J = J * 2 117 | J = J + 65000 118 | PEEKINT V J 119 | PEEKINT J 65418 120 | RETURN 121 | 122 | ARRAYPUT: 123 | POKEINT J 65418 124 | IF X > 99 THEN $E = "ARRAYGET: Array over maximum" 125 | IF X > 99 THEN GOTO ERRBOX 126 | IF X < 0 THEN $E = "ARRAYGET: Number below zero" 127 | IF X < 0 THEN GOTO ERRBOX 128 | J = X 129 | J = J * 2 130 | J = J + 65000 131 | POKEINT V J 132 | PEEKINT J 65418 133 | RETURN 134 | 135 | ASKBOX: 136 | GOSUB OPENBOX 137 | move 22 11 138 | print $5 139 | move 22 12 140 | print $6 141 | move 22 13 142 | print $7 143 | move 22 14 144 | print $8 145 | move 22 15 146 | print $9 147 | move 27 16 148 | print "--Yes-- --No--" 149 | poke 1 65420 150 | V = 1 151 | gosub askdraw 152 | askloop: 153 | waitkey j 154 | if j = 3 then gosub swleft 155 | if j = 4 then gosub swright 156 | if j = 13 then goto askend 157 | goto askloop 158 | askend: 159 | peek v 65420 160 | j = v 161 | if j = 0 then v = 1 162 | if j = 1 then v = 0 163 | GOSUB CLOSEBOX 164 | return 165 | swleft: 166 | peek v 65420 167 | if v = 0 then return 168 | if v = 1 then v = 0 169 | poke v 65420 170 | gosub askdraw 171 | return 172 | swright: 173 | peek v 65420 174 | if v = 1 then return 175 | if v = 0 then v = 1 176 | poke v 65420 177 | gosub askdraw 178 | return 179 | askdraw: 180 | move 27 16 181 | if v = 0 then ink h 182 | if v = 1 then ink c 183 | print "--Yes--" 184 | move 42 16 185 | if v = 0 then ink c 186 | if v = 1 then ink h 187 | print "--No--" 188 | return 189 | 190 | blockbor: 191 | INK Z 192 | for x = 0 to 79 193 | move x 0 194 | PRINT CHR J ; 195 | move x 2 196 | PRINT CHR J ; 197 | move x 24 198 | PRINT CHR J ; 199 | next x 200 | for x = 1 to 23 201 | move 0 x 202 | PRINT CHR J ; 203 | move 79 x 204 | PRINT CHR J ; 205 | next x 206 | return 207 | 208 | BLOCKBOX: 209 | INK T 210 | FOR X = 8 TO 17 211 | MOVE 20 X 212 | PRINT CHR J 213 | NEXT X 214 | FOR X = 21 TO 58 215 | MOVE X 8 216 | PRINT CHR J 217 | MOVE X 10 218 | PRINT CHR J 219 | MOVE X 17 220 | PRINT CHR J 221 | NEXT X 222 | FOR X = 8 TO 17 223 | MOVE 59 X 224 | PRINT CHR J 225 | NEXT X 226 | RETURN 227 | 228 | BLOCKSCR: 229 | INK Z 230 | MOVE 0 0 231 | FOR X = 0 to 79 232 | FOR Y = 0 to 24 233 | PRINT CHR J ; 234 | NEXT Y 235 | NEXT X 236 | RETURN 237 | 238 | BORDER: 239 | GOSUB SAVEVAR 240 | GOSUB SAVELOC 241 | INK Z 242 | J = 1 243 | Y = 0 244 | FOR W = 1 TO 2 245 | FOR X = 0 TO 2 246 | MOVE Y X 247 | READ BORDERDATA J V 248 | PRINT CHR V ; 249 | J = J + 1 250 | NEXT X 251 | Y = 79 252 | NEXT W 253 | FOR Y = 3 TO 23 254 | MOVE 0 Y 255 | PRINT CHR 179 ; 256 | MOVE 79 Y 257 | PRINT CHR 179 ; 258 | NEXT Y 259 | FOR X = 1 TO 78 260 | MOVE X 0 261 | PRINT CHR 196 ; 262 | MOVE X 2 263 | PRINT CHR 196 ; 264 | MOVE X 24 265 | PRINT CHR 196 ; 266 | NEXT X 267 | MOVE 0 24 268 | PRINT CHR 192 ; 269 | MOVE 79 24 270 | PRINT CHR 217 ; 271 | GOSUB LOADLOC 272 | GOSUB LOADVAR 273 | RETURN 274 | 275 | BORDERDATA: 276 | 218 179 195 191 179 180 277 | 278 | BOX: 279 | INK T 280 | W = 1 281 | X = 20 282 | FOR J = 1 TO 2 283 | FOR Y = 8 TO 17 284 | MOVE X Y 285 | READ BOXDATA W V 286 | PRINT CHR V 287 | W = W + 1 288 | NEXT Y 289 | X = 59 290 | NEXT J 291 | V = 205 292 | FOR X = 21 TO 58 293 | MOVE X 8 294 | PRINT CHR V 295 | MOVE X 10 296 | PRINT CHR V 297 | MOVE X 17 298 | PRINT CHR V 299 | NEXT X 300 | INK 7 301 | move 21 9 302 | print " " 303 | for x = 11 to 16 304 | move 21 x 305 | print " " 306 | next x 307 | INK C 308 | RETURN 309 | 310 | BOXDATA: 311 | 201 186 204 186 186 186 186 186 186 200 312 | 187 186 185 186 186 186 186 186 186 188 313 | 314 | BOXSAVE: 315 | INK 0 316 | V = 64200 317 | j = 64600 318 | for y = 8 to 17 319 | move 20 y 320 | for x = 20 to 59 321 | curschar w 322 | poke w j 323 | CURSCOL W 324 | POKE W V 325 | print " "; 326 | j = j + 1 327 | V = V + 1 328 | next x 329 | next y 330 | return 331 | 332 | BOXREST: 333 | V = 64200 334 | j = 64600 335 | for y = 8 to 17 336 | MOVE 20 Y 337 | for x = 20 to 59 338 | PEEK W V 339 | INK W 340 | peek w j 341 | print chr w ; 342 | j = j + 1 343 | V = V + 1 344 | next x 345 | next y 346 | return 347 | 348 | CLOSEBOX: 349 | POKE V 65418 350 | CURSOR OFF 351 | GOSUB ANICLOSE 352 | INK 7 353 | H = H / 16 354 | GOSUB BOXREST 355 | GOSUB LOADLOC 356 | GOSUB LOADVAR 357 | PEEK V 65418 358 | RETURN 359 | 360 | CONTENT: 361 | RETURN 362 | 363 | cserial: 364 | gosub savevar 365 | v = 0 366 | serial rec x 367 | if x = 4 then v = 1 368 | if x = 5 then v = 2 369 | if v > 0 then goto cserialc 370 | serial send 5 371 | serial rec x 372 | if x > 31 then x = 5 373 | if x = 6 then x = 3 374 | if x = 0 then v = 6 375 | if v > 0 then goto cserialc 376 | v = 4 377 | cserialc: 378 | poke v 65418 379 | gosub loadvar 380 | peek v 65418 381 | return 382 | 383 | DINBOX: 384 | $E = "INPBOX: Invalid input type." 385 | IF V > 1 THEN GOTO ERRBOX 386 | IF V < 0 THEN GOTO ERRBOX 387 | GOSUB OPENBOX 388 | if $5 = "" then goto dinboxnf 389 | move 22 11 390 | print $5 391 | move 22 12 392 | print ">" 393 | move 23 12 394 | cursor on 395 | if v = 0 then input a 396 | if v = 1 then input $7 397 | dinboxnf: 398 | if $6 = "" then goto dinboxns 399 | move 22 13 400 | print $6 401 | move 22 14 402 | print ">" 403 | move 23 14 404 | if v = 0 then input b 405 | if v = 1 then input $8 406 | dinboxns: 407 | GOSUB CLOSEBOX 408 | return 409 | 410 | ENDPROG: 411 | gosub aniend 412 | cls 413 | cursor on 414 | FOR X = 64000 TO 65535 415 | POKE 0 X 416 | NEXT X 417 | end 418 | 419 | ERRBOX: 420 | $J = $T 421 | $T = "Error" 422 | GOSUB OPENBOX 423 | POKEINT V 65418 424 | LEN $E V 425 | IF V > 38 THEN $E = "Error text too long!" 426 | IF V > 38 THEN GOTO FATALERR 427 | PEEKINT V 65418 428 | move 22 12 429 | print $E 430 | MOVE 22 14 431 | PRINT "Press escape to end program." 432 | MOVE 22 15 433 | print "Press any other key to continue." 434 | cursor on 435 | move 53 15 436 | waitkey j 437 | if j = 27 then gosub endprog 438 | GOSUB CLOSEBOX 439 | $T = $J 440 | return 441 | 442 | FATALERR: 443 | MOVE 2 1 444 | INK 12 445 | PRINT "Fatal: " ; 446 | PRINT $E ; 447 | WAITKEY K 448 | GOSUB ENDPROG 449 | 450 | INPBOX: 451 | $E = "INPBOX: Invalid input type." 452 | IF V > 1 THEN GOTO ERRBOX 453 | IF V < 0 THEN GOTO ERRBOX 454 | GOSUB OPENBOX 455 | move 22 12 456 | print $5 457 | move 22 13 458 | print $6 459 | move 22 14 460 | print ">" 461 | move 23 14 462 | cursor on 463 | if v = 1 then input $I 464 | if v = 0 then input v 465 | GOSUB CLOSEBOX 466 | return 467 | 468 | LOADLOC: 469 | POKEINT X 64164 470 | POKEINT Y 64166 471 | PEEK X 65428 472 | PEEK Y 65429 473 | MOVE X Y 474 | PEEK X 65438 475 | INK X 476 | PEEKINT X 64164 477 | PEEKINT Y 64166 478 | RETURN 479 | 480 | LOADVAR: 481 | POKEINT J 65426 482 | PEEK J 65421 483 | IF J = 0 THEN $E = "Can't load variables, none stored!" 484 | IF J = 0 THEN GOSUB FATALERR 485 | J = J + 65198 486 | PEEKINT Y J 487 | J = J - 2 488 | PEEKINT X J 489 | J = J - 2 490 | PEEKINT V J 491 | J = J - 2 492 | PEEKINT W J 493 | J = J - 65202 494 | POKE J 65421 495 | J = J + 65200 496 | PEEKINT J J 497 | RETURN 498 | 499 | MENUBOX: 500 | GOSUB OPENBOX 501 | V = 11 502 | GOSUB MENUDRAW 503 | MENULOOP: 504 | DO 505 | WAITKEY W 506 | IF W = 1 AND V = 11 THEN LOOP ENDLESS 507 | IF W = 2 AND V = 15 THEN LOOP ENDLESS 508 | IF W = 1 THEN V = V - 1 509 | IF W = 2 THEN V = V + 1 510 | IF W < 3 THEN GOSUB MENUDRAW 511 | IF W = 13 THEN GOTO MENUEND 512 | IF W = 27 THEN V = 16 513 | IF W = 27 THEN GOTO MENUEND 514 | LOOP ENDLESS 515 | MENUDRAW: 516 | J = W 517 | W = V 518 | GOSUB MENUITEM 519 | IF $J = "" AND J = 1 THEN V = V + 1 520 | IF $J = "" AND J = 2 THEN V = V - 1 521 | IF $J = "" THEN W = 0 522 | IF $J = "" THEN RETURN 523 | FOR W = 11 TO 15 524 | INK C 525 | MOVE 22 W 526 | IF W = V THEN INK H 527 | GOSUB MENUITEM 528 | X = & $J 529 | Y = INK 530 | INK 0 531 | DO 532 | PEEK J X 533 | IF J > 32 THEN INK Y 534 | IF J > 0 THEN PRINT CHR J ; 535 | X = X + 1 536 | LOOP UNTIL J = 0 537 | NEXT W 538 | MOVE 22 16 539 | INK C 540 | PRINT "Press enter to select an option." 541 | RETURN 542 | MENUITEM: 543 | $J = "" 544 | IF W = 11 THEN $J = $5 545 | IF W = 12 THEN $J = $6 546 | IF W = 13 THEN $J = $7 547 | IF W = 14 THEN $J = $8 548 | IF W = 15 THEN $J = $9 549 | RETURN 550 | MENUEND: 551 | LOOP UNTIL V = V 552 | W = V 553 | GOSUB MENUITEM 554 | $I = $J 555 | V = V - 10 556 | GOSUB CLOSEBOX 557 | RETURN 558 | 559 | MESBOX: 560 | GOSUB OPENBOX 561 | move 22 11 562 | print $5 563 | move 22 12 564 | print $6 565 | move 22 13 566 | print $7 567 | move 22 14 568 | print $8 569 | move 22 15 570 | print $9 571 | move 22 16 572 | print "Press any key to continue..." 573 | waitkey j 574 | GOSUB CLOSEBOX 575 | return 576 | 577 | NUMBOX: 578 | GOSUB OPENBOX 579 | if $5 = "" then goto numboxa 580 | move 22 11 581 | print $5 582 | move 22 12 583 | print a 584 | numboxa: 585 | if $6 = "" then goto numboxb 586 | move 22 13 587 | print $6 588 | move 22 14 589 | print b 590 | numboxb: 591 | move 22 16 592 | print "Press any key to continue..." 593 | waitkey j 594 | GOSUB CLOSEBOX 595 | return 596 | 597 | OPENBOX: 598 | IF $T = "Error" THEN GOTO ERRNOVERIFY 599 | POKEINT V 65418 600 | GOSUB SAVEVAR 601 | FOR X = 1 TO 5 602 | IF X = 1 THEN LEN $5 V 603 | IF X = 2 THEN LEN $6 V 604 | IF X = 3 THEN LEN $7 V 605 | IF X = 4 THEN LEN $8 V 606 | IF X = 5 THEN LEN $9 V 607 | IF V > 37 AND X = 1 THEN $E = "String $5 too long!" 608 | IF V > 37 AND X = 2 THEN $E = "String $6 too long!" 609 | IF V > 37 AND X = 3 THEN $E = "String $7 too long!" 610 | IF V > 37 AND X = 4 THEN $E = "String $8 too long!" 611 | IF V > 37 AND X = 5 THEN $E = "String $9 too long!" 612 | IF V > 37 THEN GOTO ERRBOX 613 | NEXT X 614 | GOSUB LOADVAR 615 | ERRNOVERIFY: 616 | GOSUB SAVEVAR 617 | GOSUB SAVELOC 618 | POKEINT V 65418 619 | GOSUB BOXSAVE 620 | IF C < 0 THEN C = 7 621 | IF C > 15 THEN C = 7 622 | H = H * 16 623 | H = H + C 624 | CURSOR OFF 625 | INK C 626 | MOVE 22 9 627 | PRINT $T 628 | GOSUB ANIOPEN 629 | GOSUB BOX 630 | MOVE 22 9 631 | PRINT $T 632 | PEEKINT V 65418 633 | RETURN 634 | 635 | pictotxt: 636 | GOSUB SAVEVAR 637 | for x = 0 to 19 638 | for y = 0 to 76 639 | peek w v 640 | if w = 0 then w = 32 641 | poke w v 642 | v = v + 1 643 | next y 644 | poke 10 v 645 | v = v + 1 646 | poke 1 v 647 | v = v + 1 648 | poke 1 v 649 | v = v + 1 650 | next x 651 | GOSUB LOADVAR 652 | return 653 | 654 | REFRESH: 655 | GOSUB SAVEVAR 656 | cls 657 | gosub border 658 | gosub title 659 | GOSUB LOADVAR 660 | gosub content 661 | return 662 | 663 | rserial: 664 | gosub savevar 665 | do 666 | serial rec w 667 | if w = 5 then serial send 6 668 | loop until w = 4 669 | serial send 6 670 | do 671 | serial rec w 672 | if w > 32 then w = 0 673 | loop until w > 0 674 | if w = 20 then goto rserialc 675 | gosub loadvar 676 | $E = "Serial: Invalid protocol!" 677 | goto errbox 678 | rserialc: 679 | serial rec w 680 | poke w 65418 681 | v = w + x 682 | v = v - 1 683 | for w = x to v 684 | serial rec j 685 | poke j w 686 | next w 687 | gosub loadvar 688 | peek v 65418 689 | return 690 | 691 | SAVELOC: 692 | POKEINT X 64164 693 | POKEINT Y 64166 694 | CURSPOS X Y 695 | POKE X 65428 696 | POKE Y 65429 697 | X = INK 698 | POKE X 65438 699 | PEEKINT X 64164 700 | PEEKINT Y 64166 701 | RETURN 702 | 703 | SAVEVAR: 704 | POKEINT Y 65426 705 | PEEK Y 65421 706 | IF Y > 198 THEN $E = "Variable storage area full!" 707 | IF Y > 198 THEN GOSUB FATALERR 708 | Y = Y + 65200 709 | POKEINT J Y 710 | Y = Y + 2 711 | POKEINT W Y 712 | Y = Y + 2 713 | POKEINT V Y 714 | Y = Y + 2 715 | POKEINT X Y 716 | Y = Y + 2 717 | Y = Y - 65200 718 | POKE Y 65421 719 | PEEKINT Y 65426 720 | POKEINT X 65426 721 | PEEK X 65421 722 | X = X + 65200 723 | POKEINT Y X 724 | X = X + 2 725 | X = X - 65200 726 | POKE X 65421 727 | PEEKINT X 65426 728 | RETURN 729 | 730 | SETTITLE: 731 | GOSUB SAVEVAR 732 | GOSUB SAVELOC 733 | LEN $T J 734 | IF J = 0 THEN RETURN 735 | IF J > 78 THEN RETURN 736 | POKE Z 65439 737 | INK Z 738 | MOVE 1 1 739 | PRINT " " ; 740 | PRINT $T ; 741 | FOR X = J TO 76 742 | PRINT " " ; 743 | NEXT X 744 | Y = & $T 745 | J = J + 65441 746 | FOR X = 65440 TO J 747 | PEEK W Y 748 | POKE W X 749 | Y = Y + 1 750 | NEXT X 751 | FOR X = X TO 65514 752 | POKE 0 X 753 | NEXT X 754 | GOSUB LOADLOC 755 | GOSUB LOADVAR 756 | RETURN 757 | 758 | sserial: 759 | if v > 255 then $E = "Serial: Packet size too big!" 760 | if v > 255 then goto errbox 761 | gosub savevar 762 | do 763 | serial send 4 764 | serial rec w 765 | if w > 32 then w = 0 766 | loop until w = 6 767 | serial send 20 768 | serial send v 769 | v = v + x 770 | v = v - 1 771 | for w = x to v 772 | peek j w 773 | serial send j 774 | next w 775 | gosub loadvar 776 | return 777 | 778 | STARTPRG: 779 | FOR X = 64000 TO 65535 780 | POKE 0 X 781 | NEXT X 782 | GOSUB SAVEVAR 783 | V = 12288 784 | GOSUB XMEM 785 | POKE 7 65439 786 | C = 7 787 | H = 14 788 | T = 7 789 | Z = 7 790 | INK 7 791 | $9 = "" 792 | GOSUB LOADVAR 793 | RETURN 794 | 795 | TITLE: 796 | GOSUB SAVEVAR 797 | GOSUB SAVELOC 798 | PEEK J 65439 799 | INK J 800 | MOVE 1 1 801 | PRINT " " ; 802 | X = 65440 803 | DO 804 | PEEK J X 805 | IF J < 32 AND J > 0 THEN J = 32 806 | PRINT CHR J ; 807 | X = X + 1 808 | LOOP UNTIL J = 0 809 | CURSPOS X Y 810 | FOR X = X TO 78 811 | PRINT " " ; 812 | NEXT X 813 | GOSUB LOADLOC 814 | GOSUB LOADVAR 815 | RETURN 816 | 817 | XMEM: 818 | GOSUB SAVEVAR 819 | POKEINT V 65436 820 | Y = 65168 821 | FOR X = 1 TO 32 822 | READ XMEMASM X W 823 | POKE W Y 824 | Y = Y + 1 825 | NEXT X 826 | GOSUB LOADVAR 827 | RETURN 828 | 829 | XMEMASM: 830 | 6 161 156 255 142 192 160 142 255 139 62 144 255 170 7 195 831 | 30 139 54 144 255 161 156 255 142 216 172 31 162 142 255 195 832 | 833 | XGET: 834 | POKEINT X 65424 835 | CALL 65184 836 | PEEK V 65422 837 | RETURN 838 | 839 | XPUT: 840 | POKEINT X 65424 841 | POKE V 65422 842 | CALL 65168 843 | RETURN 844 | -------------------------------------------------------------------------------- /programs/memedit.bas: -------------------------------------------------------------------------------- 1 | rem Memory Manipulator (MEMEDIT.BAS), version 3.1.1 2 | rem An advanced memory modification tool for MikeOS 3 | rem Copyright (C) Joshua Beck 4 | rem Email: mikeosdeveloper@gmail.com 5 | rem Licenced under the GNU General Public Licence v3, see LICENCE 6 | 7 | rem Requires the MB++ library, version 3.2.3 recommended 8 | include "mbpp.bas" 9 | 10 | parameters: 11 | if $1 = "" then goto init 12 | size $1 13 | if r = 1 then print "File does not exist." 14 | if r = 1 then end 15 | x = ramstart 16 | x = x / 16 17 | x = x + 1 18 | x = x * 16 19 | y = 65535 - x 20 | if s > y then print "File too big." 21 | if s > y then end 22 | load $1 x 23 | d = x 24 | f = x 25 | 26 | init: 27 | gosub startprg 28 | z = 9 29 | $T = "Memory Manipulator" 30 | gosub settitle 31 | cls 32 | cursor off 33 | c = 7 34 | h = 9 35 | t = 1 36 | z = 1 37 | gosub anistart 38 | gosub refresh 39 | 40 | a = 5 41 | b = 4 42 | gosub update_screen 43 | gosub highlight_on 44 | 45 | x = ramstart 46 | y = progstart 47 | v = 0 - x 48 | x = x - y 49 | 50 | $T = " About" 51 | $5 = "Memory Manipulator, version 3.1.1" 52 | $6 = "Copyright (C) Joshua Beck 2012" 53 | $7 = "Licenced under the GNU GPLv3" 54 | $8 = "Program Memory: " + x + " bytes" 55 | $9 = "Avaliable Memory: " + v + " bytes" 56 | gosub mesbox 57 | goto main 58 | 59 | main: 60 | do 61 | waitkey k 62 | if k = 1 then gosub go_up 63 | if k = 2 then gosub go_down 64 | if k = 3 then gosub go_left 65 | if k = 4 then gosub go_right 66 | if k = 13 then gosub new_value 67 | if k = 27 then gosub endprog 68 | if k > 96 and k < 123 then k = k - 32 69 | if k = 'G' then gosub go_location 70 | if k = 'L' then gosub load_file 71 | if k = 'O' then gosub save_file 72 | if k = 'Q' then gosub page_up 73 | if k = 'Z' then gosub page_down 74 | loop endless 75 | 76 | go_up: 77 | if b = 4 then goto scroll_up 78 | gosub highlight_off 79 | b = b - 1 80 | d = d - 16 81 | gosub highlight_on 82 | return 83 | 84 | go_down: 85 | if b = 19 then goto scroll_down 86 | gosub highlight_off 87 | b = b + 1 88 | d = d + 16 89 | gosub highlight_on 90 | return 91 | 92 | go_left: 93 | if a = 5 then goto back_line 94 | gosub highlight_off 95 | a = a - 3 96 | d = d - 1 97 | gosub highlight_on 98 | return 99 | 100 | go_right: 101 | if a = 50 then goto forward_line 102 | gosub highlight_off 103 | a = a + 3 104 | d = d + 1 105 | gosub highlight_on 106 | return 107 | 108 | scroll_up: 109 | gosub highlight_off 110 | f = f - 16 111 | d = d - 16 112 | gosub update_screen 113 | gosub highlight_on 114 | return 115 | 116 | scroll_down: 117 | gosub highlight_off 118 | f = f + 16 119 | d = d + 16 120 | gosub update_screen 121 | gosub highlight_on 122 | return 123 | 124 | back_line: 125 | if b = 4 then goto sback_line 126 | gosub highlight_off 127 | b = b - 1 128 | a = 50 129 | d = d - 1 130 | gosub highlight_on 131 | return 132 | 133 | forward_line: 134 | if b = 19 then goto sforward_line 135 | gosub highlight_off 136 | b = b + 1 137 | a = 5 138 | d = d + 1 139 | gosub highlight_on 140 | return 141 | 142 | sback_line: 143 | gosub highlight_off 144 | a = 50 145 | f = f - 16 146 | d = d - 1 147 | gosub update_screen 148 | gosub highlight_on 149 | return 150 | 151 | sforward_line: 152 | gosub highlight_off 153 | a = 5 154 | f = f + 16 155 | d = d + 1 156 | gosub update_screen 157 | gosub highlight_on 158 | return 159 | 160 | page_up: 161 | gosub highlight_off 162 | f = f - 256 163 | d = d - 256 164 | gosub update_screen 165 | gosub highlight_on 166 | return 167 | 168 | page_down: 169 | gosub highlight_off 170 | f = f + 256 171 | d = d + 256 172 | gosub update_screen 173 | gosub highlight_on 174 | return 175 | 176 | go_location: 177 | t = 2 178 | $T = "Goto - Location" 179 | $5 = "Enter a hexdecimal memory address to" 180 | $6 = "go to between 0000 and FFFF." 181 | v = 1 182 | gosub inpbox 183 | $4 = $I 184 | 185 | if $4 = "" then return 186 | gosub highlight_off 187 | gosub hexstr_to_num 188 | w = d - f 189 | d = v 190 | v = v - w 191 | f = v 192 | gosub update_screen 193 | gosub highlight_on 194 | return 195 | 196 | new_value: 197 | gosub highlight_off 198 | move a b 199 | print " " 200 | move a b 201 | w = a - 5 / 3 + 59 202 | move w b 203 | print " " 204 | move a b 205 | v = 0 206 | cursor on 207 | 208 | do 209 | waitkey k 210 | if k = 27 then goto bad_number 211 | v = 16 212 | if k > 47 and k < 58 then v = k - 48 213 | if k > 64 and k < 71 then v = k - 55 214 | if k > 96 and k < 103 then v = k - 87 215 | loop until v < 16 216 | print chr k ; 217 | v = v * 16 218 | 219 | do 220 | waitkey k 221 | if k = 27 then goto bad_number 222 | j = 16 223 | if k > 47 and k < 58 then j = k - 48 224 | if k > 64 and k < 71 then j = k - 55 225 | if k > 96 and k < 103 then j = k - 87 226 | if j < 16 then print chr k ; 227 | loop until j < 16 228 | v = v + j 229 | 230 | poke v d 231 | cursor off 232 | gosub update_screen 233 | gosub highlight_on 234 | return 235 | 236 | bad_number: 237 | loop until k = 27 238 | getkey k 239 | cursor off 240 | gosub update_screen 241 | gosub highlight_on 242 | return 243 | 244 | load_file: 245 | t = 14 246 | $T = "Load" 247 | $5 = "Enter a filename to load at the" 248 | $6 = "selected location (blank to cancel)" 249 | v = 1 250 | gosub inpbox 251 | $4 = $I 252 | if $4 = "" then return 253 | 254 | load $4 d 255 | if r = 1 then $E = "File does not exist!" 256 | if r = 1 then goto errbox 257 | 258 | gosub highlight_off 259 | gosub update_screen 260 | gosub highlight_on 261 | return 262 | 263 | save_file: 264 | t = 13 265 | $T = "Save" 266 | $5 = "What filename do you want to use?" 267 | $6 = "How many bytes to save (hex)?" 268 | v = 1 269 | gosub dinbox 270 | 271 | if $8 = "" then return 272 | $4 = $8 273 | gosub hexstr_to_num 274 | delete $7 275 | save $7 d v 276 | 277 | if r = 1 then $E = "Read-only disk!" 278 | if r = 1 then goto errbox 279 | return 280 | 281 | update_screen: 282 | ink 7 283 | w = f 284 | for y = 4 to 19 285 | move 5 y 286 | for x = 1 to 16 287 | peek v w 288 | w = w + 1 289 | print hex v ; 290 | print " " ; 291 | next x 292 | next y 293 | 294 | w = f 295 | for y = 4 to 19 296 | move 59 y 297 | for x = 1 to 16 298 | peek v w 299 | print chr v ; 300 | w = w + 1 301 | next x 302 | next y 303 | return 304 | 305 | highlight_on: 306 | move a b 307 | ink 232 308 | curschar v 309 | print chr v ; 310 | curschar v 311 | print chr v ; 312 | w = a - 5 / 3 + 59 313 | move w b 314 | curschar v 315 | print chr v 316 | 317 | ink 9 318 | move 74 1 319 | v = d / 256 320 | print hex v ; 321 | v = d % 256 322 | print hex v ; 323 | move 74 1 324 | for x = 1 to 4 325 | curschar v 326 | print chr v ; 327 | next x 328 | return 329 | 330 | highlight_off: 331 | move a b 332 | ink 7 333 | curschar v 334 | print chr v ; 335 | curschar v 336 | print chr v ; 337 | w = a - 5 / 3 + 59 338 | move w b 339 | curschar v 340 | print chr v 341 | return 342 | 343 | hexstr_to_num: 344 | w = & $4 345 | v = 0 346 | do 347 | peek j w 348 | gosub digit_convert 349 | if j < 16 then v = v * 16 350 | if j < 16 then v = v + j 351 | w = w + 1 352 | loop until j = 16 353 | return 354 | 355 | digit_convert: 356 | if j < 16 then j = 16 357 | if j > 47 and j < 58 then j = j - 48 358 | if j > 64 and j < 71 then j = j - 55 359 | if j > 96 and j < 103 then j = j - 87 360 | if j > 15 then j = 16 361 | return 362 | 363 | content: 364 | gosub savevar 365 | move 59 1 366 | ink 9 367 | print "Selected Byte: 0000" 368 | ink 3 369 | move 5 3 370 | print "0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF" 371 | move 5 20 372 | print "0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF" 373 | for y = 0 to 15 374 | v = y * 16 375 | w = y + 4 376 | move 2 w 377 | print hex v 378 | move 76 w 379 | print hex v 380 | move 2 w 381 | curschar v 382 | print chr v ; 383 | curschar v 384 | print chr v ; 385 | move 76 w 386 | curschar v 387 | print chr v ; 388 | curschar v 389 | print chr v ; 390 | next y 391 | ink 1 392 | move 0 21 393 | print chr 195 ; 394 | for x = 1 to 78 395 | print chr 196 ; 396 | next x 397 | print chr 180 ; 398 | ink 3 399 | move 2 22 400 | print "Use the arrow keys to move around, G for GOTO, Enter to change a value," 401 | move 2 23 402 | print "Q for page up, Z for page down, O to Save and L to load files into memory." 403 | return 404 | 405 | 406 | -------------------------------------------------------------------------------- /programs/mikedev.inc: -------------------------------------------------------------------------------- 1 | ; ------------------------------------------------------------------ 2 | ; Include file for MikeOS program development (API version 16) 3 | ; ------------------------------------------------------------------ 4 | 5 | ; ------------------------------------------------------------------ 6 | ; IMPORTANT LOCATIONS 7 | 8 | os_main equ 0000h ; Where the OS code starts 9 | 10 | 11 | ; ------------------------------------------------------------------ 12 | ; COLOURS (eg for os_draw_background and os_draw_block) 13 | 14 | %DEFINE BLACK_ON_WHITE 11110000b 15 | %DEFINE WHITE_ON_BLACK 00001111b 16 | %DEFINE WHITE_ON_LIGHT_RED 11001111b 17 | %DEFINE WHITE_ON_GREEN 00101111b 18 | %DEFINE RED_ON_LIGHT_GREEN 10100100b 19 | 20 | 21 | ; ------------------------------------------------------------------ 22 | ; KEYS 23 | 24 | %DEFINE KEY_UP 72 25 | %DEFINE KEY_DOWN 80 26 | %DEFINE KEY_LEFT 75 27 | %DEFINE KEY_RIGHT 77 28 | 29 | %DEFINE KEY_ESC 27 30 | %DEFINE KEY_ENTER 13 31 | 32 | 33 | ; ------------------------------------------------------------------ 34 | ; SYSTEM CALLS 35 | 36 | ; Screen control 37 | 38 | os_clear_screen equ 0009h ; (Nothing used) 39 | os_print_string equ 0003h ; SI = zero-terminated string location 40 | os_move_cursor equ 0006h ; DH, DL = row, column 41 | os_print_horiz_line equ 000Ch ; AX = 1 for double line, else single 42 | os_print_newline equ 000Fh ; (Nothing used) 43 | os_draw_background equ 002Ah ; AX, BX = strings, CX = colour 44 | os_draw_block equ 00B4h ; BL = colour, DH/DL/SI/DI = pos 45 | os_input_dialog equ 00A8h ; AX = input string, BX = msg string 46 | os_dialog_box equ 003Ch ; AX, BX, CX = strings, DX = type 47 | ; OUT: AX = 0 for OK, 1 for cancel 48 | ; (only multi choice for DX = 1) 49 | os_list_dialog equ 00ABh ; IN: AX = comma-separated list of 50 | ; option strings, BX, CX = help to 51 | ; display at top of list 52 | ; OUT: AX = number (starting from 1) 53 | ; of option selected, or carry if Esc 54 | os_file_selector equ 005Ah ; Returns filename in AX 55 | os_get_cursor_pos equ 0069h ; OUT: DH = row, DL = column 56 | os_print_space equ 006Ch ; (Nothing used) 57 | os_dump_string equ 006Fh ; SI = string location 58 | os_print_digit equ 0072h ; AX = digit to print 59 | os_print_1hex equ 0075h ; Display low nibble of AL in hex 60 | os_print_2hex equ 0078h ; Display AL in hex 61 | os_print_4hex equ 007Bh ; Display AX in hex 62 | os_show_cursor equ 008Ah ; (Nothing used) 63 | os_hide_cursor equ 008Dh ; (Nothing used) 64 | os_dump_registers equ 0090h ; Shows contents of AX, BX, CX, DX 65 | 66 | 67 | ; Keyboard handling 68 | 69 | os_wait_for_key equ 0012h ; Returns AL = key pressed 70 | os_check_for_key equ 0015h ; Returns AL = key pressed 71 | 72 | 73 | ; File handling 74 | 75 | os_get_file_list equ 0042h ; AX = string to store filenames 76 | os_load_file equ 0021h ; IN: AX = filename string location, 77 | ; CX = location to load file 78 | ; OUT: BX = file size in bytes, 79 | ; carry clear if OK, set if missing 80 | os_write_file equ 0096h ; AX = filename, BX = data location, 81 | ; CX = number of bytes to save 82 | os_file_exists equ 0099h ; AX = filename, carry clear if exists 83 | os_create_file equ 009Ch ; AX = filename 84 | os_remove_file equ 009Fh ; AX = filename 85 | os_rename_file equ 00A2h ; AX = filename, BX = new filename 86 | os_get_file_size equ 00A5h ; AX = filename, OUT: BX = bytes 87 | ; (64K max) 88 | 89 | 90 | ; Sound 91 | 92 | os_speaker_tone equ 001Bh ; AX = note frequency 93 | os_speaker_off equ 001Eh ; (Nothing used) 94 | 95 | 96 | ; String handling 97 | 98 | os_int_to_string equ 0018h ; AX = unsigned integer, out AX = string 99 | os_sint_to_string equ 00C0h ; AX = signed integer, out AX = string 100 | os_string_reverse equ 00AEh ; SI = string location 101 | os_string_length equ 002Dh ; AX = string loc, returns AX = length 102 | os_string_uppercase equ 0030h ; AX = zero-terminated string 103 | os_string_lowercase equ 0033h ; AX = zero-terminated string 104 | os_input_string equ 0036h ; AX = string location 105 | os_string_copy equ 0039h ; SI = source, DI = dest strings 106 | os_string_join equ 003Fh ; AX, BX = source strings, CX = dest 107 | os_string_compare equ 0045h ; SI, DI = strings, carry set if same 108 | os_string_strincmp equ 0093h ; As above, but with CL = chars to check 109 | os_string_chomp equ 0048h ; AX = string location 110 | os_string_strip equ 004Bh ; SI = string, AX = char to remove 111 | os_string_truncate equ 004Eh ; SI = string, AX = number of chars 112 | os_set_time_fmt equ 0084h ; AL = format 113 | os_set_date_fmt equ 0087h ; AX = format 114 | os_get_time_string equ 0054h ; BX = string location for eg '20:41' 115 | os_get_date_string equ 005Dh ; BX = string loc for eg '12/31/2007' 116 | os_find_char_in_string equ 0066h ; IN: SI = string, AL = char to find 117 | os_long_int_to_string equ 007Eh ; DX:AX = num, BX = base, DI = string 118 | os_string_to_int equ 00B1h ; SI = string (up to 65535), AX = int 119 | os_string_charchange equ 00BAh ; SI = string, AL = old char, BL = new 120 | os_string_parse equ 00C3h ; SI = string; output: AX/BX/CX/DX = 121 | ; substrings (or 0 if not present) 122 | os_string_tokenize equ 00CFh ; SI = string, AL = sep char; returns 123 | ; DI = next token 124 | 125 | 126 | ; Math routines 127 | 128 | os_get_random equ 00B7h ; IN: AX, BX = low, high; OUT: CX = num 129 | os_bcd_to_int equ 0051h ; AL = BCD number, returns AX = integer 130 | os_long_int_negate equ 0081h ; DX:AX = number 131 | 132 | 133 | ; Ports 134 | 135 | os_port_byte_out equ 00C9h ; IN: DX = port, AL = byte 136 | os_port_byte_in equ 00CCh ; IN: DX = port; OUT: AL = byte 137 | os_serial_port_enable equ 00BDh ; AX = 0 for 9600 baud, 1 for 1200 138 | os_send_via_serial equ 0060h ; AL = byte to send 139 | os_get_via_serial equ 0063h ; Returns AL = byte received 140 | ; OUT: AX = location, or 0 if not found 141 | 142 | 143 | ; Misc OS functions 144 | 145 | os_run_basic equ 00C6h ; AX = code location in RAM, BX = size, 146 | ; SI = parameter string (or 0 if none) 147 | os_get_api_version equ 0057h ; Returns API version in AL 148 | os_pause equ 0024h ; AX = 10ths of second to wait 149 | os_fatal_error equ 0027h ; AX = error string location 150 | 151 | 152 | ; ------------------------------------------------------------------ 153 | 154 | -------------------------------------------------------------------------------- /programs/monitor.asm: -------------------------------------------------------------------------------- 1 | ; ------------------------------------------------------------------ 2 | ; Machine code monitor -- by Yutaka Saito and Mike Saunders 3 | ; 4 | ; Accepts code in hex format, ORGed to 36864 (4K after where 5 | ; this program is loaded) 6 | ; ------------------------------------------------------------------ 7 | 8 | 9 | BITS 16 10 | %INCLUDE "mikedev.inc" 11 | ORG 32768 12 | 13 | 14 | ; This line determines where the machine code will 15 | ; be generated -- if you change it, you will need to 16 | ; ORG the code you enter at the new address 17 | 18 | CODELOC equ 36864 19 | 20 | 21 | mov si, helpmsg1 ; Print help text 22 | call os_print_string 23 | 24 | mov si, helpmsg2 25 | call os_print_string 26 | 27 | mov si, helpmsg3 28 | call os_print_string 29 | 30 | main_loop: 31 | mov si, helpmsg4 32 | call os_print_string 33 | 34 | .noinput: 35 | call os_print_newline 36 | 37 | mov si, prompt ; Print prompt 38 | call os_print_string 39 | 40 | mov ax, input ; Get hex string 41 | call os_input_string 42 | 43 | mov ax, input 44 | call os_string_length 45 | cmp ax, 0 46 | je .noinput 47 | 48 | mov si, input ; Convert to machine code... 49 | mov di, run 50 | 51 | 52 | .more: 53 | cmp byte [si], '$' ; If char in string is '$', end of code 54 | je .done 55 | cmp byte [si], ' ' ; If space, move on to next char 56 | je .space 57 | cmp byte [si], 'r' ; If 'r' entered, re-run existing code 58 | je .runprog 59 | cmp byte [si], 'x' ; Or if 'x' entered, return to OS 60 | jne .noexit 61 | call os_print_newline 62 | ret 63 | .noexit: 64 | mov al, [si] 65 | and al, 0F0h 66 | cmp al, 40h 67 | je .H_A_to_F 68 | .H_1_to_9: 69 | mov al, [si] 70 | sub al, 30h 71 | mov ah, al 72 | sal ah, 4 73 | jmp .H_end 74 | .H_A_to_F: 75 | mov al, [si] 76 | sub al, 37h 77 | mov ah, al 78 | sal ah, 4 79 | .H_end: 80 | inc si 81 | mov al, [si] 82 | and al, 0F0h 83 | cmp al, 40h 84 | je .L_A_to_F 85 | .L_1_to_9: 86 | mov al, [si] 87 | sub al, 30h 88 | jmp .L_end 89 | .L_A_to_F: 90 | mov al, [si] 91 | sub al, 37h 92 | .L_end: 93 | or al, ah 94 | mov [di], al 95 | inc di 96 | .space: 97 | inc si 98 | jmp .more 99 | .done: 100 | mov byte [di], 0 ; Write terminating zero 101 | 102 | mov si, run ; Copy machine code to location for execution 103 | mov di, CODELOC 104 | mov cx, 255 105 | cld 106 | rep movsb 107 | 108 | 109 | .runprog: 110 | call os_print_newline 111 | 112 | call CODELOC ; Run program 113 | 114 | call os_print_newline 115 | 116 | jmp main_loop 117 | 118 | 119 | input times 255 db 0 ; Code entered by user (in ASCII) 120 | run times 255 db 0 ; Translated machine code to execute 121 | 122 | helpmsg1 db 'MIKEOS MACHINE CODE MONITOR', 10, 13, 0 123 | helpmsg2 db '(See the User Handbook for a quick guide)', 13, 10, 13, 10, 0 124 | helpmsg3 db 'Enter instructions in hex, terminated by $ character', 10, 13, 0 125 | helpmsg4 db 'Commands: r = re-run previous code, x = exit', 10, 13, 0 126 | 127 | prompt db '= ', 0 128 | 129 | 130 | ; ------------------------------------------------------------------ 131 | 132 | -------------------------------------------------------------------------------- /programs/monitor.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mig-hub/mikeOS/685306a87ddf1a41c069ec7670d24c7d2023ff20/programs/monitor.bin -------------------------------------------------------------------------------- /programs/muncher.bas: -------------------------------------------------------------------------------- 1 | rem ** Muncher for MikeOS ** 2 | rem Created by Justin Tokarchuk 3 | rem ------------------------------ 4 | 5 | rem VARS 6 | rem j = score multiplier 7 | rem x, y = coords 8 | rem e = body 9 | rem s = score 10 | rem i = multipliers 11 | rem n = wallpiece counter, gets reloaded by bonus engine 12 | 13 | cursor off 14 | goto logo 15 | 16 | 17 | waitforenter: 18 | waitkey x 19 | if x = 13 then goto pregame 20 | if x = 27 then cursor on 21 | if x = 27 then END 22 | goto waitforenter 23 | 24 | logo: 25 | cls 26 | cursor off 27 | move 0 7 28 | print " ## ## ## ## ## ## ###### ## ## ######## ######## ###" 29 | print " ### ### ## ## ### ## ## ## ## ## ## ## ## ###" 30 | print " #### #### ## ## #### ## ## ## ## ## ## ## ###" 31 | print " ## ### ## ## ## ## ## ## ## ######### ###### ######## # " 32 | print " ## ## ## ## ## #### ## ## ## ## ## ## " 33 | print " ## ## ## ## ## ### ## ## ## ## ## ## ## ###" 34 | print " ## ## ####### ## ## ###### ## ## ######## ## ## ###" 35 | print "" 36 | print " ======================================================================" 37 | print "" 38 | print " Press ENTER to play, ESC to quit. " 39 | gosub changelook 40 | 41 | goto waitforenter 42 | 43 | changelook: 44 | for b = 0 to 24 45 | for a = 0 to 78 46 | move a b 47 | curschar c 48 | if c = '#' then c = 219 49 | if c = '=' then c = 220 50 | print chr c ; 51 | next a 52 | next b 53 | return 54 | 55 | pregame: 56 | cls 57 | n = 0 58 | 59 | cls 60 | cursor off 61 | gosub setwalls 62 | 63 | 64 | rem ** Place user in middle of screen. ** 65 | x = 40 66 | y = 12 67 | move x y 68 | 69 | rem ** dirs = up (1), down (2), left (3), right (4) 70 | rem ** start moving left 71 | 72 | d = 3 73 | 74 | rem ** score 75 | s = 0 76 | 77 | rem ** Body character. 78 | e = 35 79 | 80 | 81 | gosub addapple 82 | 83 | game: 84 | print chr e ; 85 | gosub printscore 86 | pause 1 87 | if d = 1 then pause 1 88 | if d = 2 then pause 1 89 | 90 | getkey k 91 | 92 | rem ** controls 93 | if k = 'w' then d = 1 94 | if k = 'W' then d = 1 95 | if k = 'a' then d = 3 96 | if k = 'A' then d = 3 97 | if k = 's' then d = 2 98 | if k = 'S' then d = 2 99 | if k = 'd' then d = 4 100 | if k = 'D' then d = 4 101 | 102 | 103 | rem if they press ESC exit game 104 | if k = 27 then goto finish 105 | 106 | if d = 1 then gosub moveupdown 107 | if d = 2 then gosub moveupdown 108 | if d = 3 then gosub moveleft 109 | if d = 4 then gosub moveright 110 | 111 | move x y 112 | 113 | curschar c 114 | rem ***did we collide with wall*** 115 | if x = 79 then goto finish 116 | if c = 'x' then goto finish 117 | if c = 178 then goto finish 118 | if c = e then goto finish 119 | if c = '@' then gosub getbonus 120 | goto game 121 | 122 | moveupdown: 123 | move x y 124 | print " " 125 | if d = 1 then y = y - 1 126 | if d = 2 then y = y + 1 127 | return 128 | 129 | 130 | moveleft: 131 | print " " ; 132 | move x y 133 | print " " 134 | x = x - 1 135 | return 136 | 137 | moveright: 138 | if x = q AND y = r then gosub getbonus 139 | move x y 140 | print " " 141 | x = x + 1 142 | return 143 | 144 | setwalls: 145 | a = 178 146 | 147 | move 0 0 148 | for x = 0 to 78 149 | print chr a ; 150 | next x 151 | 152 | move 0 23 153 | for x = 0 to 78 154 | print chr a ; 155 | next x 156 | 157 | for y = 0 to 23 158 | move 0 y 159 | print chr a ; 160 | next y 161 | 162 | for y = 0 to 23 163 | move 78 y 164 | print chr a ; 165 | next y 166 | 167 | return 168 | 169 | printscore: 170 | move 0 24 171 | print "Score: " ; 172 | print s ; 173 | move x y 174 | return 175 | 176 | addapple: 177 | rand q 1 77 178 | rand r 1 22 179 | g = 64 180 | if q = x then goto addapple 181 | if r = y then goto addapple 182 | move q r 183 | print chr g 184 | 185 | rem generate random number of wallpieces 186 | if s < 500 then rand g 1 2 187 | if s > 499 then rand g 2 5 188 | if s > 999 then rand g 5 10 189 | if s > 1999 then rand g 10 20 190 | morewallz: 191 | if s > 0 then gosub wallpiece 192 | g = g - 1 193 | if g > 0 then goto morewallz 194 | move x y 195 | return 196 | 197 | wallpiece: 198 | rem ** now add a wall piece ** 199 | rand l 1 77 200 | rand m 1 22 201 | rem Don't put it on a character or the apple please! 202 | if l = q then goto wallpiece 203 | if l = x then goto wallpiece 204 | if m = r then goto wallpiece 205 | if m = y then goto wallpiece 206 | 207 | rem is the wall piece too close to the character? 208 | if l > x then a = l - x 209 | if l < x then a = x - l 210 | if m > y then b = m - y 211 | if m < y then b = y - m 212 | if a < 7 then goto wallpiece 213 | if b < 4 then goto wallpiece 214 | move l m 215 | if c = 'x' then gosub wallpiece 216 | print "x" ; 217 | 218 | return 219 | 220 | getbonus: 221 | move x y 222 | g = 1 223 | print chr g 224 | pause 1 225 | move x y 226 | g = 2 227 | print chr g 228 | pause 1 229 | move x y 230 | g = 1 231 | print chr g 232 | pause 1 233 | move x y 234 | print " " 235 | rem *i = intermediate number for score bonus 236 | if s > 250 then j = 2 237 | if s > 1000 then j = 3 238 | if s > 3000 then j = 5 239 | if s > 5000 then j = 10 240 | gosub addapple 241 | j = 1 242 | i = 150 * j 243 | s = s + i 244 | return 245 | 246 | finish: 247 | 248 | cls 249 | cursor off 250 | move 0 2 251 | print " ###### ### ## ## ####### " 252 | print " ## ## ## ## ### ### ## " 253 | print " ## ## ## #### #### ## " 254 | print " ## #### ## ## ## ### ## ###### " 255 | print " ## ## ######### ## ## ## " 256 | print " ## ## ## ## ## ## ## " 257 | print " ###### ## ## ## ## ####### " 258 | print "" 259 | print " ####### ## ## ######## ######## " 260 | print " ## ## ## ## ## ## ## " 261 | print " ## ## ## ## ## ## ## " 262 | print " ## ## ## ## ###### ######## " 263 | print " ## ## ## ## ## ## ## " 264 | print " ## ## ## ## ## ## ## " 265 | print " ####### ### ######## ## ## " 266 | print "" 267 | print " Your Score Was: " ; 268 | print s 269 | print "" 270 | print " Play Again? (Y/N)" 271 | gosub changelook 272 | 273 | goto escloop 274 | 275 | escloop: 276 | waitkey x 277 | cursor on 278 | if x = 'n' then end 279 | if x = 'N' then end 280 | if x = 27 then end 281 | if x = 'y' then goto logo 282 | if x = 'Y' then goto logo 283 | goto escloop 284 | 285 | -------------------------------------------------------------------------------- /programs/sample.pcx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mig-hub/mikeOS/685306a87ddf1a41c069ec7670d24c7d2023ff20/programs/sample.pcx -------------------------------------------------------------------------------- /programs/serial.asm: -------------------------------------------------------------------------------- 1 | ; ------------------------------------------------------------------ 2 | ; Minicom-like program for MikeOS 3 | ; ------------------------------------------------------------------ 4 | 5 | 6 | ; With this program and an appropriate serial (null modem) cable, you 7 | ; can log in to Linux machines. You will need your Linux box to establish 8 | ; a serial terminal in /etc/inittab, with something like this: 9 | ; 10 | ; T0:2345:respawn:/sbin/getty/ -L ttyS0 9600 vt100 11 | ; 12 | ; Connect the serial cable to your MikeOS machine and Linux machine. 13 | ; Start MikeOS and run SERIAL.BIN, then start your Linux box with the 14 | ; above serial terminal entry. On the MikeOS machine, you will see a 15 | ; familiar Linux login prompt -- you're ready to go! Note that very few 16 | ; VT100 terminal features are implemented at present, so complicated 17 | ; programs (eg Emacs) will not display correctly. 18 | ; 19 | ; Press the F8 key to exit. 20 | 21 | 22 | BITS 16 23 | 24 | %INCLUDE "mikedev.inc" 25 | ORG 32768 26 | 27 | 28 | start: 29 | mov ax, warnmsg_1 30 | mov bx, warnmsg_2 31 | mov cx, 0 32 | mov dx, 1 33 | call os_dialog_box 34 | cmp ax, 0 35 | je .proceed 36 | 37 | call os_clear_screen 38 | ret 39 | 40 | 41 | .proceed: 42 | call os_clear_screen 43 | 44 | mov ax, 0 ; 9600 baud mode 45 | call os_serial_port_enable 46 | 47 | mov si, start_msg 48 | call os_print_string 49 | 50 | 51 | main_loop: 52 | mov dx, 0 ; Set port to COM1 53 | mov ax, 0 54 | mov ah, 03h ; Check COM1 status 55 | int 14h 56 | 57 | bt ax, 8 ; Data received? 58 | jc received_byte 59 | 60 | mov ax, 0 ; If not, have we something to send? 61 | call os_check_for_key 62 | 63 | cmp ax, 4200h ; F8 key pressed? 64 | je finish ; Quit if so 65 | 66 | cmp al, 0 ; If no other key pressed, go back 67 | je main_loop 68 | 69 | call os_send_via_serial ; Otherwise send it 70 | jmp main_loop 71 | 72 | received_byte: ; Print data received 73 | call os_get_via_serial 74 | 75 | cmp al, 1Bh ; 'Esc' character received? 76 | je esc_received 77 | 78 | mov ah, 0Eh ; Otherwise print char 79 | int 10h 80 | jmp main_loop 81 | 82 | finish: 83 | mov si, finish_msg 84 | call os_print_string 85 | 86 | call os_wait_for_key 87 | 88 | ret 89 | 90 | 91 | 92 | esc_received: 93 | call os_get_via_serial ; Get next character... 94 | cmp al, '[' ; Is it a screen control code? 95 | jne main_loop 96 | 97 | mov bl, al ; Store for now 98 | 99 | call os_get_via_serial ; If control code, parse it 100 | 101 | cmp al, 'H' 102 | je near move_to_home 103 | 104 | cmp al, 'J' 105 | je near erase_to_bottom 106 | 107 | cmp al, 'K' 108 | je near erase_to_end_of_line 109 | 110 | 111 | ; If it wasn't a control char that 112 | ; we can parse yet, print the whole 113 | ; thing for debugging purposes 114 | 115 | mov cl, al ; Store second char 116 | mov al, bl ; Get first 117 | 118 | mov ah, 0Eh ; Print them 119 | int 10h 120 | mov al, cl 121 | int 10h 122 | 123 | jmp main_loop 124 | 125 | 126 | 127 | move_to_home: 128 | mov dx, 0 129 | call os_move_cursor 130 | jmp main_loop 131 | 132 | 133 | erase_to_bottom: 134 | call os_get_cursor_pos 135 | 136 | push dx ; Store where we are 137 | 138 | call erase_sub 139 | 140 | inc dh ; Move to start of next line 141 | mov dl, 0 142 | call os_move_cursor 143 | 144 | mov ah, 0Ah ; Get ready to print 80 spaces 145 | mov al, ' ' 146 | mov bx, 0 147 | mov cx, 80 148 | .more: 149 | int 10h 150 | inc dh ; Next line... 151 | call os_move_cursor 152 | cmp dh, 25 ; Reached bottom of screen? 153 | jne .more 154 | 155 | pop dx ; Put cursor back to where we started 156 | call os_move_cursor 157 | 158 | jmp main_loop 159 | 160 | 161 | 162 | erase_to_end_of_line: 163 | call erase_sub 164 | jmp main_loop 165 | 166 | 167 | erase_sub: 168 | call os_get_cursor_pos 169 | 170 | push dx ; Store where we are 171 | 172 | mov ah, 80 ; Calculate how many spaces 173 | sub ah, dl ; we need to print... 174 | 175 | mov cx, 0 ; And drop into CL 176 | mov cl, ah 177 | 178 | mov ah, 0Ah ; Print spaces CL number of times 179 | mov al, ' ' 180 | mov bx, 0 181 | int 10h 182 | 183 | pop dx 184 | call os_move_cursor 185 | 186 | ret 187 | 188 | 189 | warnmsg_1 db 'Serial terminal program -- may lock up', 0 190 | warnmsg_2 db 'if you have no serial ports! Proceed?', 0 191 | 192 | start_msg db 'MikeOS minicom -- Press F8 to quit', 13, 10, 'Connecting via serial at 9600 baud...', 13, 10, 13, 10, 0 193 | finish_msg db 13, 10, 13, 10, 'Exiting MikeOS minicom; press a key to return to MikeOS', 13, 10, 0 194 | 195 | 196 | ; ------------------------------------------------------------------ 197 | 198 | -------------------------------------------------------------------------------- /programs/serial.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mig-hub/mikeOS/685306a87ddf1a41c069ec7670d24c7d2023ff20/programs/serial.bin -------------------------------------------------------------------------------- /programs/sudoku.bas: -------------------------------------------------------------------------------- 1 | rem *** MikeOS Sudoku 1.0 *** 2 | 3 | 4 | cls 5 | 6 | a = 0 7 | b = 0 8 | c = 78 9 | d = 24 10 | gosub draw_box 11 | 12 | $1 = "Easy,Medium,Hard" 13 | $2 = "MikeOS Sudoku" 14 | $3 = "Choose a difficulty level..." 15 | listbox $1 $2 $3 z 16 | 17 | if z = 0 then goto finish 18 | 19 | 20 | rem *** Copy level information into RAM *** 21 | d = RAMSTART 22 | for c = 1 to 81 23 | if z = 1 then read level_easy c a 24 | if z = 2 then read level_medium c a 25 | if z = 3 then read level_hard c a 26 | poke a d 27 | d = d + 1 28 | next c 29 | 30 | 31 | rem *** X and Y vars are cursor position *** 32 | x = 0 33 | y = 0 34 | 35 | 36 | cursor off 37 | gosub setup_screen 38 | 39 | main_loop: 40 | gosub update_screen 41 | 42 | rem *** Move cursor according to keypresses, skipping divider lines *** 43 | waitkey k 44 | if k = 27 then goto finish 45 | if k = 4 and x < 16 then x = x + 2 46 | if k = 3 and x > 0 then x = x - 2 47 | if k = 2 and y < 10 then y = y + 1 48 | if k = 2 and y = 3 then y = y + 1 49 | if k = 2 and y = 7 then y = y + 1 50 | if k = 1 and y > 0 then y = y - 1 51 | if k = 1 and y = 3 then y = y - 1 52 | if k = 1 and y = 7 then y = y - 1 53 | if k = 13 then gosub enter_pressed 54 | if k = 104 then gosub show_help 55 | goto main_loop 56 | 57 | 58 | finish: 59 | cursor on 60 | cls 61 | end 62 | 63 | 64 | enter_pressed: 65 | move 40 14 66 | print "Enter a number: " ; 67 | input a 68 | 69 | if a > 9 then goto invalid 70 | 71 | rem *** These lines convert our coordinates in the grid into the *** 72 | rem *** corresponding point in the Sudoku numbers in RAM *** 73 | b = x / 2 74 | c = RAMSTART 75 | c = c + b 76 | d = y * 9 77 | c = c + d 78 | if y > 2 and y < 7 then c = c - 9 79 | if y > 7 then c = c - 18 80 | poke a c 81 | 82 | move 40 14 83 | print " " 84 | 85 | gosub check_completed 86 | return 87 | 88 | invalid: 89 | move 40 16 90 | print "Invalid number!" 91 | waitkey a 92 | move 40 14 93 | print " " 94 | move 40 16 95 | print " " 96 | return 97 | 98 | 99 | check_completed: 100 | d = 0 101 | u = 0 102 | 103 | rem *** First, go through the rows, looking for uniques *** 104 | a = RAMSTART 105 | 106 | for p = 0 to 8 107 | z = a 108 | 109 | for b = 1 to 9 110 | for c = 0 to 8 111 | peek m a 112 | if m = b then d = d + 1 113 | if m = b then goto donehere 114 | a = a + 1 115 | next c 116 | donehere: 117 | a = z 118 | next b 119 | 120 | if d = 9 then u = u + 1 121 | d = 0 122 | a = a + 9 123 | next p 124 | 125 | 126 | rem *** And then through columns *** 127 | a = RAMSTART 128 | d = 0 129 | 130 | for p = 0 to 8 131 | z = a 132 | 133 | for b = 1 to 9 134 | for c = 0 to 8 135 | peek m a 136 | if m = b then d = d + 1 137 | if m = b then goto bdonehere2 138 | a = a + 9 139 | next c 140 | 141 | bdonehere2: 142 | a = z 143 | next b 144 | 145 | if d = 9 then u = u + 1 146 | d = 0 147 | a = a + 1 148 | next p 149 | 150 | 151 | rem *** And through first column of boxes *** 152 | 153 | for g = 0 to 2 154 | a = RAMSTART 155 | d = 0 156 | b = g * 27 157 | a = a + b 158 | 159 | z = a 160 | 161 | for b = 1 to 9 162 | for c = 0 to 8 163 | if c = 3 then a = a + 6 164 | if c = 6 then a = a + 6 165 | peek m a 166 | if m = b then d = d + 1 167 | if m = b then goto bdonehere3 168 | a = a + 1 169 | next c 170 | 171 | bdonehere3: 172 | a = z 173 | next b 174 | 175 | if d = 9 then u = u + 1 176 | d = 0 177 | a = a + 1 178 | next g 179 | 180 | 181 | rem *** Second column *** 182 | for g = 0 to 2 183 | a = RAMSTART 184 | d = 0 185 | b = g * 27 186 | a = a + b 187 | a = a + 3 188 | 189 | z = a 190 | 191 | for b = 1 to 9 192 | for c = 0 to 8 193 | if c = 3 then a = a + 6 194 | if c = 6 then a = a + 6 195 | peek m a 196 | if m = b then d = d + 1 197 | if m = b then goto bdonehere4 198 | a = a + 1 199 | next c 200 | 201 | bdonehere4: 202 | a = z 203 | next b 204 | 205 | if d = 9 then u = u + 1 206 | d = 0 207 | a = a + 1 208 | next g 209 | 210 | 211 | rem *** Third column *** 212 | for g = 0 to 2 213 | a = RAMSTART 214 | d = 0 215 | b = g * 27 216 | a = a + b 217 | a = a + 6 218 | 219 | z = a 220 | 221 | for b = 1 to 9 222 | for c = 0 to 8 223 | if c = 3 then a = a + 6 224 | if c = 6 then a = a + 6 225 | peek m a 226 | if m = b then d = d + 1 227 | if m = b then goto bdonehere5 228 | a = a + 1 229 | next c 230 | 231 | bdonehere5: 232 | a = z 233 | next b 234 | 235 | if d = 9 then u = u + 1 236 | d = 0 237 | a = a + 1 238 | next g 239 | 240 | if u = 27 then goto win 241 | return 242 | 243 | 244 | win: 245 | move 45 12 246 | ink 14 247 | print "PUZZLE COMPLETE!" 248 | move 44 14 249 | ink 7 250 | print "Press a key to end" 251 | waitkey x 252 | cursor on 253 | cls 254 | end 255 | 256 | 257 | setup_screen: 258 | cls 259 | 260 | rem *** Outer border *** 261 | a = 0 262 | b = 0 263 | c = 78 264 | d = 24 265 | gosub draw_box 266 | 267 | 268 | rem *** Sudoku grid lines *** 269 | ink 8 270 | 271 | a = 13 272 | b = 8 273 | c = 31 274 | d = 20 275 | gosub draw_box 276 | a = 13 277 | b = 8 278 | c = 31 279 | d = 12 280 | gosub draw_box 281 | a = 19 282 | b = 8 283 | c = 25 284 | d = 12 285 | gosub draw_box 286 | a = 13 287 | b = 12 288 | c = 31 289 | d = 16 290 | gosub draw_box 291 | a = 19 292 | b = 12 293 | c = 25 294 | d = 16 295 | gosub draw_box 296 | a = 19 297 | b = 16 298 | c = 25 299 | d = 20 300 | gosub draw_box 301 | 302 | ink 7 303 | move 3 2 304 | print "MikeOS Sudoku - Press H for help, or Esc to quit" 305 | move 3 4 306 | print "Cursor keys navigate, Enter inputs a number, zero blanks a square" 307 | return 308 | 309 | 310 | update_screen: 311 | rem *** Cursor *** 312 | ink 14 313 | 314 | rem *** First, blank out area where cursor could be *** 315 | move 14 6 316 | print " " 317 | move 14 7 318 | print " " 319 | 320 | for a = 9 to 21 321 | move 11 a 322 | print " " 323 | next a 324 | 325 | a = x + 14 326 | move a 6 327 | print "|" ; 328 | move a 7 329 | print "v" ; 330 | b = y + 9 331 | move 11 b 332 | print "->" ; 333 | ink 7 334 | 335 | 336 | rem *** Numbers *** 337 | a = 14 338 | b = 9 339 | 340 | m = RAMSTART 341 | 342 | for c = 1 to 81 343 | peek d m 344 | 345 | move a b 346 | if d > 0 then print d ; 347 | if d = 0 then print " " ; 348 | a = a + 2 349 | 350 | rem *** Handle wrapping *** 351 | if a = 32 then b = b + 1 352 | if a = 32 then a = 14 353 | if b = 12 then b = 13 354 | if b = 16 then b = 17 355 | 356 | m = m + 1 357 | next c 358 | return 359 | 360 | 361 | show_help: 362 | cls 363 | 364 | print "" 365 | print "" 366 | print " Sudoku is a puzzle game. You have a grid of 9 x 9 squares," 367 | print " which is divided into smaller 3 x 3 sections. Your goal is" 368 | print " to fill the grid so that every row has the numbers 1 to 9," 369 | print " every column has the numbers 1 to 9, and every small 3 x 3" 370 | print " section has the numbers 1 to 9." 371 | print "" 372 | print " Press a key to return to the game..." 373 | 374 | a = 0 375 | b = 0 376 | c = 78 377 | d = 24 378 | gosub draw_box 379 | 380 | waitkey z 381 | gosub setup_screen 382 | return 383 | return 384 | 385 | 386 | rem *** Level data *** 387 | level_easy: 388 | 0 5 0 0 8 1 0 0 7 389 | 4 6 0 0 0 0 3 5 0 390 | 0 0 1 3 4 0 0 6 0 391 | 0 0 4 8 0 6 0 0 9 392 | 8 0 7 0 5 0 2 0 6 393 | 6 0 0 1 0 2 7 0 0 394 | 0 1 0 0 3 4 6 0 0 395 | 0 8 6 0 0 0 0 2 3 396 | 2 0 0 7 6 0 0 9 0 397 | 398 | level_medium: 399 | 0 7 0 0 2 0 0 3 0 400 | 8 0 0 0 0 0 0 0 9 401 | 0 0 5 0 9 0 4 0 0 402 | 0 5 0 0 8 0 0 4 0 403 | 3 0 1 9 0 7 6 0 2 404 | 0 9 0 0 6 0 0 8 0 405 | 0 0 9 0 7 0 8 0 0 406 | 1 0 0 0 0 0 0 0 6 407 | 0 4 0 0 5 0 0 7 0 408 | 409 | level_hard: 410 | 0 0 0 1 6 8 0 0 0 411 | 0 0 0 4 7 9 1 0 0 412 | 0 0 0 0 0 0 0 0 0 413 | 2 0 0 0 0 6 4 0 7 414 | 1 0 0 3 0 0 5 0 9 415 | 0 0 9 0 0 7 0 8 0 416 | 0 0 0 0 0 0 2 0 0 417 | 0 0 8 0 0 0 7 0 3 418 | 0 0 5 6 4 3 0 0 0 419 | 420 | 421 | rem *** draw_box routine *** 422 | rem *** Takes coords in A, B, C and D vars. Uses Z internally *** 423 | draw_box: 424 | move a b 425 | for z = a to c 426 | print "-" ; 427 | next z 428 | move a d 429 | for z = a to c 430 | print "-" ; 431 | next z 432 | for z = b to d 433 | move a z 434 | print "|" ; 435 | next z 436 | for z = b to d 437 | move c z 438 | print "|" ; 439 | next z 440 | move a b 441 | print "+" ; 442 | move a d 443 | print "+" ; 444 | move c b 445 | print "+" ; 446 | move c d 447 | print "+" ; 448 | return 449 | 450 | -------------------------------------------------------------------------------- /programs/viewer.asm: -------------------------------------------------------------------------------- 1 | ; ------------------------------------------------------------------ 2 | ; Program to display text files and PCX images (320x200, 8-bit only) 3 | ; ------------------------------------------------------------------ 4 | 5 | 6 | BITS 16 7 | %INCLUDE "mikedev.inc" 8 | ORG 32768 9 | 10 | 11 | main_start: 12 | call draw_background 13 | 14 | call os_file_selector ; Get filename 15 | 16 | jc near close ; Quit if Esc pressed in dialog box 17 | 18 | mov bx, ax ; Save filename for now 19 | 20 | mov di, ax 21 | 22 | call os_string_length 23 | add di, ax ; DI now points to last char in filename 24 | 25 | dec di 26 | dec di 27 | dec di ; ...and now to first char of extension! 28 | 29 | mov si, txt_extension 30 | mov cx, 3 31 | rep cmpsb ; Does the extension contain 'TXT'? 32 | je near valid_txt_extension ; Skip ahead if so 33 | 34 | dec di 35 | 36 | mov si, bas_extension 37 | mov cx, 3 38 | rep cmpsb ; Does the extension contain 'BAS'? 39 | je near valid_txt_extension ; Skip ahead if so 40 | 41 | dec di 42 | 43 | mov si, pcx_extension 44 | mov cx, 3 45 | rep cmpsb ; Does the extension contain 'PCX'? 46 | je valid_pcx_extension ; Skip ahead if so 47 | 48 | ; Otherwise show error dialog 49 | mov dx, 0 ; One button for dialog box 50 | mov ax, err_string 51 | mov bx, 0 52 | mov cx, 0 53 | call os_dialog_box 54 | 55 | jmp main_start ; And retry 56 | 57 | 58 | valid_pcx_extension: 59 | mov ax, bx 60 | mov cx, 36864 ; Load PCX at 36864 (4K after program start) 61 | call os_load_file 62 | 63 | 64 | mov ah, 0 ; Switch to graphics mode 65 | mov al, 13h 66 | int 10h 67 | 68 | 69 | mov ax, 0A000h ; ES = video memory 70 | mov es, ax 71 | 72 | 73 | mov si, 36864+80h ; Move source to start of image data 74 | ; (First 80h bytes is header) 75 | 76 | mov di, 0 ; Start our loop at top of video RAM 77 | 78 | decode: 79 | mov cx, 1 80 | lodsb 81 | cmp al, 192 ; Single pixel or string? 82 | jb single 83 | and al, 63 ; String, so 'mod 64' it 84 | mov cl, al ; Result in CL for following 'rep' 85 | lodsb ; Get byte to put on screen 86 | single: 87 | rep stosb ; And show it (or all of them) 88 | cmp di, 64001 89 | jb decode 90 | 91 | 92 | mov dx, 3c8h ; Palette index register 93 | mov al, 0 ; Start at colour 0 94 | out dx, al ; Tell VGA controller that... 95 | inc dx ; ...3c9h = palette data register 96 | 97 | mov cx, 768 ; 256 colours, 3 bytes each 98 | setpal: 99 | lodsb ; Grab the next byte. 100 | shr al, 2 ; Palettes divided by 4, so undo 101 | out dx, al ; Send to VGA controller 102 | loop setpal 103 | 104 | 105 | call os_wait_for_key 106 | 107 | mov ax, 3 ; Back to text mode 108 | mov bx, 0 109 | int 10h 110 | mov ax, 1003h ; No blinking text! 111 | int 10h 112 | 113 | mov ax, 2000h ; Reset ES back to original value 114 | mov es, ax 115 | call os_clear_screen 116 | jmp main_start 117 | 118 | 119 | draw_background: 120 | mov ax, title_msg ; Set up screen 121 | mov bx, footer_msg 122 | mov cx, BLACK_ON_WHITE 123 | call os_draw_background 124 | ret 125 | 126 | 127 | 128 | ; Meanwhile, if it's a text file... 129 | 130 | valid_txt_extension: 131 | mov ax, bx 132 | mov cx, 36864 ; Load file 4K after program start 133 | call os_load_file 134 | 135 | 136 | ; Now BX contains the number of bytes in the file, so let's add 137 | ; the load offset to get the last byte of the file in RAM 138 | 139 | add bx, 36864 140 | 141 | 142 | mov cx, 0 ; Lines to skip when rendering 143 | mov word [skiplines], 0 144 | 145 | 146 | pusha 147 | mov ax, txt_title_msg ; Set up screen 148 | mov bx, txt_footer_msg 149 | mov cx, 11110000b ; Black text on white background 150 | call os_draw_background 151 | popa 152 | 153 | 154 | 155 | txt_start: 156 | pusha 157 | 158 | mov bl, 11110000b ; Black text on white background 159 | mov dh, 2 160 | mov dl, 0 161 | mov si, 80 162 | mov di, 23 163 | call os_draw_block ; Overwrite old text for scrolling 164 | 165 | mov dh, 2 ; Move cursor to near top 166 | mov dl, 0 167 | call os_move_cursor 168 | 169 | popa 170 | 171 | 172 | mov si, 36864 ; Start of text data 173 | mov ah, 0Eh ; BIOS char printing routine 174 | 175 | 176 | redraw: 177 | cmp cx, 0 ; How many lines to skip? 178 | je loopy 179 | dec cx 180 | 181 | skip_loop: 182 | lodsb ; Read bytes until newline, to skip a line 183 | cmp al, 10 184 | jne skip_loop 185 | jmp redraw 186 | 187 | 188 | loopy: 189 | lodsb ; Get character from file data 190 | 191 | cmp al, 10 ; Return to start of line if carriage return character 192 | jne skip_return 193 | call os_get_cursor_pos 194 | mov dl, 0 195 | call os_move_cursor 196 | 197 | skip_return: 198 | int 10h ; Print the character 199 | 200 | cmp si, bx ; Have we printed all in the file? 201 | je finished 202 | 203 | call os_get_cursor_pos ; Are we at the bottom of the display area? 204 | cmp dh, 23 205 | je get_input 206 | 207 | jmp loopy 208 | 209 | 210 | get_input: ; Get cursor keys and Q 211 | call os_wait_for_key 212 | cmp ah, KEY_UP 213 | je go_up 214 | cmp ah, KEY_DOWN 215 | je go_down 216 | cmp al, 'q' 217 | je main_start 218 | cmp al, 'Q' 219 | je main_start 220 | jmp get_input 221 | 222 | 223 | go_up: 224 | cmp word [skiplines], 0 ; Don't scroll up if we're at the top 225 | jle txt_start 226 | dec word [skiplines] ; Otherwise decrement the lines we need to skip 227 | mov word cx, [skiplines] 228 | jmp txt_start 229 | 230 | go_down: 231 | inc word [skiplines] ; Increment the lines we need to skip 232 | mov word cx, [skiplines] 233 | jmp txt_start 234 | 235 | 236 | finished: ; We get here when we've printed the final character 237 | call os_wait_for_key 238 | cmp ah, 48h 239 | je go_up ; Can only scroll up at this point 240 | cmp al, 'q' 241 | je main_start 242 | cmp al, 'Q' 243 | je main_start 244 | jmp finished 245 | 246 | 247 | close: 248 | call os_clear_screen 249 | ret 250 | 251 | 252 | txt_extension db 'TXT', 0 253 | bas_extension db 'BAS', 0 254 | pcx_extension db 'PCX', 0 255 | 256 | err_string db 'Please select a TXT, BAS or PCX file!', 0 257 | 258 | title_msg db 'MikeOS File Viewer', 0 259 | footer_msg db 'Select a TXT, BAS or PCX file to view, or press Esc to exit', 0 260 | 261 | txt_title_msg db 'MikeOS Text File Viewer', 0 262 | txt_footer_msg db 'Use arrow keys to scroll and Q to quit', 0 263 | 264 | skiplines dw 0 265 | 266 | 267 | ; ------------------------------------------------------------------ 268 | 269 | -------------------------------------------------------------------------------- /programs/viewer.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mig-hub/mikeOS/685306a87ddf1a41c069ec7670d24c7d2023ff20/programs/viewer.bin -------------------------------------------------------------------------------- /source/bootload/bootload.asm: -------------------------------------------------------------------------------- 1 | ; ================================================================== 2 | ; The Mike Operating System bootloader 3 | ; Copyright (C) 2006 - 2014 MikeOS Developers -- see doc/LICENSE.TXT 4 | ; 5 | ; Based on a free boot loader by E Dehling. It scans the FAT12 6 | ; floppy for KERNEL.BIN (the MikeOS kernel), loads it and executes it. 7 | ; This must grow no larger than 512 bytes (one sector), with the final 8 | ; two bytes being the boot signature (AA55h). Note that in FAT12, 9 | ; a cluster is the same as a sector: 512 bytes. 10 | ; ================================================================== 11 | 12 | 13 | BITS 16 14 | 15 | jmp short bootloader_start ; Jump past disk description section 16 | nop ; Pad out before disk description 17 | 18 | 19 | ; ------------------------------------------------------------------ 20 | ; Disk description table, to make it a valid floppy 21 | ; Note: some of these values are hard-coded in the source! 22 | ; Values are those used by IBM for 1.44 MB, 3.5" diskette 23 | 24 | OEMLabel db "MIKEBOOT" ; Disk label 25 | BytesPerSector dw 512 ; Bytes per sector 26 | SectorsPerCluster db 1 ; Sectors per cluster 27 | ReservedForBoot dw 1 ; Reserved sectors for boot record 28 | NumberOfFats db 2 ; Number of copies of the FAT 29 | RootDirEntries dw 224 ; Number of entries in root dir 30 | ; (224 * 32 = 7168 = 14 sectors to read) 31 | LogicalSectors dw 2880 ; Number of logical sectors 32 | MediumByte db 0F0h ; Medium descriptor byte 33 | SectorsPerFat dw 9 ; Sectors per FAT 34 | SectorsPerTrack dw 18 ; Sectors per track (36/cylinder) 35 | Sides dw 2 ; Number of sides/heads 36 | HiddenSectors dd 0 ; Number of hidden sectors 37 | LargeSectors dd 0 ; Number of LBA sectors 38 | DriveNo dw 0 ; Drive No: 0 39 | Signature db 41 ; Drive signature: 41 for floppy 40 | VolumeID dd 00000000h ; Volume ID: any number 41 | VolumeLabel db "MIKEOS "; Volume Label: any 11 chars 42 | FileSystem db "FAT12 " ; File system type: don't change! 43 | 44 | 45 | ; ------------------------------------------------------------------ 46 | ; Main bootloader code 47 | 48 | bootloader_start: 49 | mov ax, 07C0h ; Set up 4K of stack space above buffer 50 | add ax, 544 ; 8k buffer = 512 paragraphs + 32 paragraphs (loader) 51 | cli ; Disable interrupts while changing stack 52 | mov ss, ax 53 | mov sp, 4096 54 | sti ; Restore interrupts 55 | 56 | mov ax, 07C0h ; Set data segment to where we're loaded 57 | mov ds, ax 58 | 59 | ; NOTE: A few early BIOSes are reported to improperly set DL 60 | 61 | cmp dl, 0 62 | je no_change 63 | mov [bootdev], dl ; Save boot device number 64 | mov ah, 8 ; Get drive parameters 65 | int 13h 66 | jc fatal_disk_error 67 | and cx, 3Fh ; Maximum sector number 68 | mov [SectorsPerTrack], cx ; Sector numbers start at 1 69 | movzx dx, dh ; Maximum head number 70 | add dx, 1 ; Head numbers start at 0 - add 1 for total 71 | mov [Sides], dx 72 | 73 | no_change: 74 | mov eax, 0 ; Needed for some older BIOSes 75 | 76 | 77 | ; First, we need to load the root directory from the disk. Technical details: 78 | ; Start of root = ReservedForBoot + NumberOfFats * SectorsPerFat = logical 19 79 | ; Number of root = RootDirEntries * 32 bytes/entry / 512 bytes/sector = 14 80 | ; Start of user data = (start of root) + (number of root) = logical 33 81 | 82 | floppy_ok: ; Ready to read first block of data 83 | mov ax, 19 ; Root dir starts at logical sector 19 84 | call l2hts 85 | 86 | mov si, buffer ; Set ES:BX to point to our buffer (see end of code) 87 | mov bx, ds 88 | mov es, bx 89 | mov bx, si 90 | 91 | mov ah, 2 ; Params for int 13h: read floppy sectors 92 | mov al, 14 ; And read 14 of them 93 | 94 | pusha ; Prepare to enter loop 95 | 96 | 97 | read_root_dir: 98 | popa ; In case registers are altered by int 13h 99 | pusha 100 | 101 | stc ; A few BIOSes do not set properly on error 102 | int 13h ; Read sectors using BIOS 103 | 104 | jnc search_dir ; If read went OK, skip ahead 105 | call reset_floppy ; Otherwise, reset floppy controller and try again 106 | jnc read_root_dir ; Floppy reset OK? 107 | 108 | jmp reboot ; If not, fatal double error 109 | 110 | 111 | search_dir: 112 | popa 113 | 114 | mov ax, ds ; Root dir is now in [buffer] 115 | mov es, ax ; Set DI to this info 116 | mov di, buffer 117 | 118 | mov cx, word [RootDirEntries] ; Search all (224) entries 119 | mov ax, 0 ; Searching at offset 0 120 | 121 | 122 | next_root_entry: 123 | xchg cx, dx ; We use CX in the inner loop... 124 | 125 | mov si, kern_filename ; Start searching for kernel filename 126 | mov cx, 11 127 | rep cmpsb 128 | je found_file_to_load ; Pointer DI will be at offset 11 129 | 130 | add ax, 32 ; Bump searched entries by 1 (32 bytes per entry) 131 | 132 | mov di, buffer ; Point to next entry 133 | add di, ax 134 | 135 | xchg dx, cx ; Get the original CX back 136 | loop next_root_entry 137 | 138 | mov si, file_not_found ; If kernel is not found, bail out 139 | call print_string 140 | jmp reboot 141 | 142 | 143 | found_file_to_load: ; Fetch cluster and load FAT into RAM 144 | mov ax, word [es:di+0Fh] ; Offset 11 + 15 = 26, contains 1st cluster 145 | mov word [cluster], ax 146 | 147 | mov ax, 1 ; Sector 1 = first sector of first FAT 148 | call l2hts 149 | 150 | mov di, buffer ; ES:BX points to our buffer 151 | mov bx, di 152 | 153 | mov ah, 2 ; int 13h params: read (FAT) sectors 154 | mov al, 9 ; All 9 sectors of 1st FAT 155 | 156 | pusha ; Prepare to enter loop 157 | 158 | 159 | read_fat: 160 | popa ; In case registers are altered by int 13h 161 | pusha 162 | 163 | stc 164 | int 13h ; Read sectors using the BIOS 165 | 166 | jnc read_fat_ok ; If read went OK, skip ahead 167 | call reset_floppy ; Otherwise, reset floppy controller and try again 168 | jnc read_fat ; Floppy reset OK? 169 | 170 | ; ****************************************************************** 171 | fatal_disk_error: 172 | ; ****************************************************************** 173 | mov si, disk_error ; If not, print error message and reboot 174 | call print_string 175 | jmp reboot ; Fatal double error 176 | 177 | 178 | read_fat_ok: 179 | popa 180 | 181 | mov ax, 2000h ; Segment where we'll load the kernel 182 | mov es, ax 183 | mov bx, 0 184 | 185 | mov ah, 2 ; int 13h floppy read params 186 | mov al, 1 187 | 188 | push ax ; Save in case we (or int calls) lose it 189 | 190 | 191 | ; Now we must load the FAT from the disk. Here's how we find out where it starts: 192 | ; FAT cluster 0 = media descriptor = 0F0h 193 | ; FAT cluster 1 = filler cluster = 0FFh 194 | ; Cluster start = ((cluster number) - 2) * SectorsPerCluster + (start of user) 195 | ; = (cluster number) + 31 196 | 197 | load_file_sector: 198 | mov ax, word [cluster] ; Convert sector to logical 199 | add ax, 31 200 | 201 | call l2hts ; Make appropriate params for int 13h 202 | 203 | mov ax, 2000h ; Set buffer past what we've already read 204 | mov es, ax 205 | mov bx, word [pointer] 206 | 207 | pop ax ; Save in case we (or int calls) lose it 208 | push ax 209 | 210 | stc 211 | int 13h 212 | 213 | jnc calculate_next_cluster ; If there's no error... 214 | 215 | call reset_floppy ; Otherwise, reset floppy and retry 216 | jmp load_file_sector 217 | 218 | 219 | ; In the FAT, cluster values are stored in 12 bits, so we have to 220 | ; do a bit of maths to work out whether we're dealing with a byte 221 | ; and 4 bits of the next byte -- or the last 4 bits of one byte 222 | ; and then the subsequent byte! 223 | 224 | calculate_next_cluster: 225 | mov ax, [cluster] 226 | mov dx, 0 227 | mov bx, 3 228 | mul bx 229 | mov bx, 2 230 | div bx ; DX = [cluster] mod 2 231 | mov si, buffer 232 | add si, ax ; AX = word in FAT for the 12 bit entry 233 | mov ax, word [ds:si] 234 | 235 | or dx, dx ; If DX = 0 [cluster] is even; if DX = 1 then it's odd 236 | 237 | jz even ; If [cluster] is even, drop last 4 bits of word 238 | ; with next cluster; if odd, drop first 4 bits 239 | 240 | odd: 241 | shr ax, 4 ; Shift out first 4 bits (they belong to another entry) 242 | jmp short next_cluster_cont 243 | 244 | 245 | even: 246 | and ax, 0FFFh ; Mask out final 4 bits 247 | 248 | 249 | next_cluster_cont: 250 | mov word [cluster], ax ; Store cluster 251 | 252 | cmp ax, 0FF8h ; FF8h = end of file marker in FAT12 253 | jae end 254 | 255 | add word [pointer], 512 ; Increase buffer pointer 1 sector length 256 | jmp load_file_sector 257 | 258 | 259 | end: ; We've got the file to load! 260 | pop ax ; Clean up the stack (AX was pushed earlier) 261 | mov dl, byte [bootdev] ; Provide kernel with boot device info 262 | 263 | jmp 2000h:0000h ; Jump to entry point of loaded kernel! 264 | 265 | 266 | ; ------------------------------------------------------------------ 267 | ; BOOTLOADER SUBROUTINES 268 | 269 | reboot: 270 | mov ax, 0 271 | int 16h ; Wait for keystroke 272 | mov ax, 0 273 | int 19h ; Reboot the system 274 | 275 | 276 | print_string: ; Output string in SI to screen 277 | pusha 278 | 279 | mov ah, 0Eh ; int 10h teletype function 280 | 281 | .repeat: 282 | lodsb ; Get char from string 283 | cmp al, 0 284 | je .done ; If char is zero, end of string 285 | int 10h ; Otherwise, print it 286 | jmp short .repeat 287 | 288 | .done: 289 | popa 290 | ret 291 | 292 | 293 | reset_floppy: ; IN: [bootdev] = boot device; OUT: carry set on error 294 | push ax 295 | push dx 296 | mov ax, 0 297 | mov dl, byte [bootdev] 298 | stc 299 | int 13h 300 | pop dx 301 | pop ax 302 | ret 303 | 304 | 305 | l2hts: ; Calculate head, track and sector settings for int 13h 306 | ; IN: logical sector in AX, OUT: correct registers for int 13h 307 | push bx 308 | push ax 309 | 310 | mov bx, ax ; Save logical sector 311 | 312 | mov dx, 0 ; First the sector 313 | div word [SectorsPerTrack] 314 | add dl, 01h ; Physical sectors start at 1 315 | mov cl, dl ; Sectors belong in CL for int 13h 316 | mov ax, bx 317 | 318 | mov dx, 0 ; Now calculate the head 319 | div word [SectorsPerTrack] 320 | mov dx, 0 321 | div word [Sides] 322 | mov dh, dl ; Head/side 323 | mov ch, al ; Track 324 | 325 | pop ax 326 | pop bx 327 | 328 | mov dl, byte [bootdev] ; Set correct device 329 | 330 | ret 331 | 332 | 333 | ; ------------------------------------------------------------------ 334 | ; STRINGS AND VARIABLES 335 | 336 | kern_filename db "KERNEL BIN" ; MikeOS kernel filename 337 | 338 | disk_error db "Floppy error! Press any key...", 0 339 | file_not_found db "KERNEL.BIN not found!", 0 340 | 341 | bootdev db 0 ; Boot device number 342 | cluster dw 0 ; Cluster of the file we want to load 343 | pointer dw 0 ; Pointer into Buffer, for loading kernel 344 | 345 | 346 | ; ------------------------------------------------------------------ 347 | ; END OF BOOT SECTOR AND BUFFER START 348 | 349 | times 510-($-$$) db 0 ; Pad remainder of boot sector with zeros 350 | dw 0AA55h ; Boot signature (DO NOT CHANGE!) 351 | 352 | 353 | buffer: ; Disk buffer begins (8k after this, stack starts) 354 | 355 | 356 | ; ================================================================== 357 | 358 | -------------------------------------------------------------------------------- /source/bootload/bootload.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mig-hub/mikeOS/685306a87ddf1a41c069ec7670d24c7d2023ff20/source/bootload/bootload.bin -------------------------------------------------------------------------------- /source/features/cli.asm: -------------------------------------------------------------------------------- 1 | ; ================================================================== 2 | ; MikeOS -- The Mike Operating System kernel 3 | ; Copyright (C) 2006 - 2014 MikeOS Developers -- see doc/LICENSE.TXT 4 | ; 5 | ; COMMAND LINE INTERFACE 6 | ; ================================================================== 7 | 8 | 9 | os_command_line: 10 | call os_clear_screen 11 | 12 | mov si, version_msg 13 | call os_print_string 14 | mov si, help_text 15 | call os_print_string 16 | 17 | 18 | get_cmd: ; Main processing loop 19 | mov di, input ; Clear input buffer each time 20 | mov al, 0 21 | mov cx, 256 22 | rep stosb 23 | 24 | mov di, command ; And single command buffer 25 | mov cx, 32 26 | rep stosb 27 | 28 | mov si, prompt ; Main loop; prompt for input 29 | call os_print_string 30 | 31 | mov ax, input ; Get command string from user 32 | call os_input_string 33 | 34 | call os_print_newline 35 | 36 | mov ax, input ; Remove trailing spaces 37 | call os_string_chomp 38 | 39 | mov si, input ; If just enter pressed, prompt again 40 | cmp byte [si], 0 41 | je get_cmd 42 | 43 | mov si, input ; Separate out the individual command 44 | mov al, ' ' 45 | call os_string_tokenize 46 | 47 | mov word [param_list], di ; Store location of full parameters 48 | 49 | mov si, input ; Store copy of command for later modifications 50 | mov di, command 51 | call os_string_copy 52 | 53 | 54 | 55 | ; First, let's check to see if it's an internal command... 56 | 57 | mov ax, input 58 | call os_string_uppercase 59 | 60 | mov si, input 61 | 62 | mov di, exit_string ; 'EXIT' entered? 63 | call os_string_compare 64 | jc near exit 65 | 66 | mov di, help_string ; 'HELP' entered? 67 | call os_string_compare 68 | jc near print_help 69 | 70 | mov di, cls_string ; 'CLS' entered? 71 | call os_string_compare 72 | jc near clear_screen 73 | 74 | mov di, dir_string ; 'DIR' entered? 75 | call os_string_compare 76 | jc near list_directory 77 | 78 | mov di, ver_string ; 'VER' entered? 79 | call os_string_compare 80 | jc near print_ver 81 | 82 | mov di, time_string ; 'TIME' entered? 83 | call os_string_compare 84 | jc near print_time 85 | 86 | mov di, date_string ; 'DATE' entered? 87 | call os_string_compare 88 | jc near print_date 89 | 90 | mov di, cat_string ; 'CAT' entered? 91 | call os_string_compare 92 | jc near cat_file 93 | 94 | mov di, del_string ; 'DEL' entered? 95 | call os_string_compare 96 | jc near del_file 97 | 98 | mov di, copy_string ; 'COPY' entered? 99 | call os_string_compare 100 | jc near copy_file 101 | 102 | mov di, ren_string ; 'REN' entered? 103 | call os_string_compare 104 | jc near ren_file 105 | 106 | mov di, size_string ; 'SIZE' entered? 107 | call os_string_compare 108 | jc near size_file 109 | 110 | 111 | ; If the user hasn't entered any of the above commands, then we 112 | ; need to check for an executable file -- .BIN or .BAS, and the 113 | ; user may not have provided the extension 114 | 115 | mov ax, command 116 | call os_string_uppercase 117 | call os_string_length 118 | 119 | 120 | ; If the user has entered, say, MEGACOOL.BIN, we want to find that .BIN 121 | ; bit, so we get the length of the command, go four characters back to 122 | ; the full stop, and start searching from there 123 | 124 | mov si, command 125 | add si, ax 126 | 127 | sub si, 4 128 | 129 | mov di, bin_extension ; Is there a .BIN extension? 130 | call os_string_compare 131 | jc bin_file 132 | 133 | mov di, bas_extension ; Or is there a .BAS extension? 134 | call os_string_compare 135 | jc bas_file 136 | 137 | jmp no_extension 138 | 139 | 140 | bin_file: 141 | mov ax, command 142 | mov bx, 0 143 | mov cx, 32768 144 | call os_load_file 145 | jc total_fail 146 | 147 | execute_bin: 148 | mov si, command 149 | mov di, kern_file_string 150 | mov cx, 6 151 | call os_string_strincmp 152 | jc no_kernel_allowed 153 | 154 | mov ax, 0 ; Clear all registers 155 | mov bx, 0 156 | mov cx, 0 157 | mov dx, 0 158 | mov word si, [param_list] 159 | mov di, 0 160 | 161 | call 32768 ; Call the external program 162 | 163 | jmp get_cmd ; When program has finished, start again 164 | 165 | 166 | 167 | bas_file: 168 | mov ax, command 169 | mov bx, 0 170 | mov cx, 32768 171 | call os_load_file 172 | jc total_fail 173 | 174 | mov ax, 32768 175 | mov word si, [param_list] 176 | call os_run_basic 177 | 178 | jmp get_cmd 179 | 180 | 181 | 182 | no_extension: 183 | mov ax, command 184 | call os_string_length 185 | 186 | mov si, command 187 | add si, ax 188 | 189 | mov byte [si], '.' 190 | mov byte [si+1], 'B' 191 | mov byte [si+2], 'I' 192 | mov byte [si+3], 'N' 193 | mov byte [si+4], 0 194 | 195 | mov ax, command 196 | mov bx, 0 197 | mov cx, 32768 198 | call os_load_file 199 | jc try_bas_ext 200 | 201 | jmp execute_bin 202 | 203 | 204 | try_bas_ext: 205 | mov ax, command 206 | call os_string_length 207 | 208 | mov si, command 209 | add si, ax 210 | sub si, 4 211 | 212 | mov byte [si], '.' 213 | mov byte [si+1], 'B' 214 | mov byte [si+2], 'A' 215 | mov byte [si+3], 'S' 216 | mov byte [si+4], 0 217 | 218 | jmp bas_file 219 | 220 | 221 | 222 | total_fail: 223 | mov si, invalid_msg 224 | call os_print_string 225 | 226 | jmp get_cmd 227 | 228 | 229 | no_kernel_allowed: 230 | mov si, kern_warn_msg 231 | call os_print_string 232 | 233 | jmp get_cmd 234 | 235 | 236 | ; ------------------------------------------------------------------ 237 | 238 | print_help: 239 | mov si, help_text 240 | call os_print_string 241 | jmp get_cmd 242 | 243 | 244 | ; ------------------------------------------------------------------ 245 | 246 | clear_screen: 247 | call os_clear_screen 248 | jmp get_cmd 249 | 250 | 251 | ; ------------------------------------------------------------------ 252 | 253 | print_time: 254 | mov bx, tmp_string 255 | call os_get_time_string 256 | mov si, bx 257 | call os_print_string 258 | call os_print_newline 259 | jmp get_cmd 260 | 261 | 262 | ; ------------------------------------------------------------------ 263 | 264 | print_date: 265 | mov bx, tmp_string 266 | call os_get_date_string 267 | mov si, bx 268 | call os_print_string 269 | call os_print_newline 270 | jmp get_cmd 271 | 272 | 273 | ; ------------------------------------------------------------------ 274 | 275 | print_ver: 276 | mov si, version_msg 277 | call os_print_string 278 | jmp get_cmd 279 | 280 | 281 | ; ------------------------------------------------------------------ 282 | 283 | kern_warning: 284 | mov si, kern_warn_msg 285 | call os_print_string 286 | jmp get_cmd 287 | 288 | 289 | ; ------------------------------------------------------------------ 290 | 291 | list_directory: 292 | mov cx, 0 ; Counter 293 | 294 | mov ax, dirlist ; Get list of files on disk 295 | call os_get_file_list 296 | 297 | mov si, dirlist 298 | mov ah, 0Eh ; BIOS teletype function 299 | 300 | .repeat: 301 | lodsb ; Start printing filenames 302 | cmp al, 0 ; Quit if end of string 303 | je .done 304 | 305 | cmp al, ',' ; If comma in list string, don't print it 306 | jne .nonewline 307 | pusha 308 | call os_print_newline ; But print a newline instead 309 | popa 310 | jmp .repeat 311 | 312 | .nonewline: 313 | int 10h 314 | jmp .repeat 315 | 316 | .done: 317 | call os_print_newline 318 | jmp get_cmd 319 | 320 | 321 | ; ------------------------------------------------------------------ 322 | 323 | cat_file: 324 | mov word si, [param_list] 325 | call os_string_parse 326 | cmp ax, 0 ; Was a filename provided? 327 | jne .filename_provided 328 | 329 | mov si, nofilename_msg ; If not, show error message 330 | call os_print_string 331 | jmp get_cmd 332 | 333 | .filename_provided: 334 | call os_file_exists ; Check if file exists 335 | jc .not_found 336 | 337 | mov cx, 32768 ; Load file into second 32K 338 | call os_load_file 339 | 340 | mov word [file_size], bx 341 | 342 | cmp bx, 0 ; Nothing in the file? 343 | je get_cmd 344 | 345 | mov si, 32768 346 | mov ah, 0Eh ; int 10h teletype function 347 | .loop: 348 | lodsb ; Get byte from loaded file 349 | 350 | cmp al, 0Ah ; Move to start of line if we get a newline char 351 | jne .not_newline 352 | 353 | call os_get_cursor_pos 354 | mov dl, 0 355 | call os_move_cursor 356 | 357 | .not_newline: 358 | int 10h ; Display it 359 | dec bx ; Count down file size 360 | cmp bx, 0 ; End of file? 361 | jne .loop 362 | 363 | jmp get_cmd 364 | 365 | .not_found: 366 | mov si, notfound_msg 367 | call os_print_string 368 | jmp get_cmd 369 | 370 | 371 | ; ------------------------------------------------------------------ 372 | 373 | del_file: 374 | mov word si, [param_list] 375 | call os_string_parse 376 | cmp ax, 0 ; Was a filename provided? 377 | jne .filename_provided 378 | 379 | mov si, nofilename_msg ; If not, show error message 380 | call os_print_string 381 | jmp get_cmd 382 | 383 | .filename_provided: 384 | call os_remove_file 385 | jc .failure 386 | 387 | mov si, .success_msg 388 | call os_print_string 389 | mov si, ax 390 | call os_print_string 391 | call os_print_newline 392 | jmp get_cmd 393 | 394 | .failure: 395 | mov si, .failure_msg 396 | call os_print_string 397 | jmp get_cmd 398 | 399 | 400 | .success_msg db 'Deleted file: ', 0 401 | .failure_msg db 'Could not delete file - does not exist or write protected', 13, 10, 0 402 | 403 | 404 | ; ------------------------------------------------------------------ 405 | 406 | size_file: 407 | mov word si, [param_list] 408 | call os_string_parse 409 | cmp ax, 0 ; Was a filename provided? 410 | jne .filename_provided 411 | 412 | mov si, nofilename_msg ; If not, show error message 413 | call os_print_string 414 | jmp get_cmd 415 | 416 | .filename_provided: 417 | call os_get_file_size 418 | jc .failure 419 | 420 | mov si, .size_msg 421 | call os_print_string 422 | 423 | mov ax, bx 424 | call os_int_to_string 425 | mov si, ax 426 | call os_print_string 427 | call os_print_newline 428 | jmp get_cmd 429 | 430 | 431 | .failure: 432 | mov si, notfound_msg 433 | call os_print_string 434 | jmp get_cmd 435 | 436 | 437 | .size_msg db 'Size (in bytes) is: ', 0 438 | 439 | 440 | ; ------------------------------------------------------------------ 441 | 442 | copy_file: 443 | mov word si, [param_list] 444 | call os_string_parse 445 | mov word [.tmp], bx 446 | 447 | cmp bx, 0 ; Were two filenames provided? 448 | jne .filename_provided 449 | 450 | mov si, nofilename_msg ; If not, show error message 451 | call os_print_string 452 | jmp get_cmd 453 | 454 | .filename_provided: 455 | mov dx, ax ; Store first filename temporarily 456 | mov ax, bx 457 | call os_file_exists 458 | jnc .already_exists 459 | 460 | mov ax, dx 461 | mov cx, 32768 462 | call os_load_file 463 | jc .load_fail 464 | 465 | mov cx, bx 466 | mov bx, 32768 467 | mov word ax, [.tmp] 468 | call os_write_file 469 | jc .write_fail 470 | 471 | mov si, .success_msg 472 | call os_print_string 473 | jmp get_cmd 474 | 475 | .load_fail: 476 | mov si, notfound_msg 477 | call os_print_string 478 | jmp get_cmd 479 | 480 | .write_fail: 481 | mov si, writefail_msg 482 | call os_print_string 483 | jmp get_cmd 484 | 485 | .already_exists: 486 | mov si, exists_msg 487 | call os_print_string 488 | jmp get_cmd 489 | 490 | 491 | .tmp dw 0 492 | .success_msg db 'File copied successfully', 13, 10, 0 493 | 494 | 495 | ; ------------------------------------------------------------------ 496 | 497 | ren_file: 498 | mov word si, [param_list] 499 | call os_string_parse 500 | 501 | cmp bx, 0 ; Were two filenames provided? 502 | jne .filename_provided 503 | 504 | mov si, nofilename_msg ; If not, show error message 505 | call os_print_string 506 | jmp get_cmd 507 | 508 | .filename_provided: 509 | mov cx, ax ; Store first filename temporarily 510 | mov ax, bx ; Get destination 511 | call os_file_exists ; Check to see if it exists 512 | jnc .already_exists 513 | 514 | mov ax, cx ; Get first filename back 515 | call os_rename_file 516 | jc .failure 517 | 518 | mov si, .success_msg 519 | call os_print_string 520 | jmp get_cmd 521 | 522 | .already_exists: 523 | mov si, exists_msg 524 | call os_print_string 525 | jmp get_cmd 526 | 527 | .failure: 528 | mov si, .failure_msg 529 | call os_print_string 530 | jmp get_cmd 531 | 532 | 533 | .success_msg db 'File renamed successfully', 13, 10, 0 534 | .failure_msg db 'Operation failed - file not found or invalid filename', 13, 10, 0 535 | 536 | 537 | ; ------------------------------------------------------------------ 538 | 539 | exit: 540 | ret 541 | 542 | 543 | ; ------------------------------------------------------------------ 544 | 545 | input times 256 db 0 546 | command times 32 db 0 547 | 548 | dirlist times 1024 db 0 549 | tmp_string times 15 db 0 550 | 551 | file_size dw 0 552 | param_list dw 0 553 | 554 | bin_extension db '.BIN', 0 555 | bas_extension db '.BAS', 0 556 | 557 | prompt db '> ', 0 558 | 559 | help_text db 'Commands: DIR, COPY, REN, DEL, CAT, SIZE, CLS, HELP, TIME, DATE, VER, EXIT', 13, 10, 0 560 | invalid_msg db 'No such command or program', 13, 10, 0 561 | nofilename_msg db 'No filename or not enough filenames', 13, 10, 0 562 | notfound_msg db 'File not found', 13, 10, 0 563 | writefail_msg db 'Could not write file. Write protected or invalid filename?', 13, 10, 0 564 | exists_msg db 'Target file already exists!', 13, 10, 0 565 | 566 | version_msg db 'MikeOS ', MIKEOS_VER, 13, 10, 0 567 | 568 | exit_string db 'EXIT', 0 569 | help_string db 'HELP', 0 570 | cls_string db 'CLS', 0 571 | dir_string db 'DIR', 0 572 | time_string db 'TIME', 0 573 | date_string db 'DATE', 0 574 | ver_string db 'VER', 0 575 | cat_string db 'CAT', 0 576 | del_string db 'DEL', 0 577 | ren_string db 'REN', 0 578 | copy_string db 'COPY', 0 579 | size_string db 'SIZE', 0 580 | 581 | kern_file_string db 'KERNEL', 0 582 | kern_warn_msg db 'Cannot execute kernel file!', 13, 10, 0 583 | 584 | 585 | ; ================================================================== 586 | 587 | -------------------------------------------------------------------------------- /source/features/keyboard.asm: -------------------------------------------------------------------------------- 1 | ; ================================================================== 2 | ; MikeOS -- The Mike Operating System kernel 3 | ; Copyright (C) 2006 - 2014 MikeOS Developers -- see doc/LICENSE.TXT 4 | ; 5 | ; KEYBOARD HANDLING ROUTINES 6 | ; ================================================================== 7 | 8 | ; ------------------------------------------------------------------ 9 | ; os_wait_for_key -- Waits for keypress and returns key 10 | ; IN: Nothing; OUT: AX = key pressed, other regs preserved 11 | 12 | os_wait_for_key: 13 | pusha 14 | 15 | mov ax, 0 16 | mov ah, 10h ; BIOS call to wait for key 17 | int 16h 18 | 19 | mov [.tmp_buf], ax ; Store resulting keypress 20 | 21 | popa ; But restore all other regs 22 | mov ax, [.tmp_buf] 23 | ret 24 | 25 | 26 | .tmp_buf dw 0 27 | 28 | 29 | ; ------------------------------------------------------------------ 30 | ; os_check_for_key -- Scans keyboard for input, but doesn't wait 31 | ; IN: Nothing; OUT: AX = 0 if no key pressed, otherwise scan code 32 | 33 | os_check_for_key: 34 | pusha 35 | 36 | mov ax, 0 37 | mov ah, 1 ; BIOS call to check for key 38 | int 16h 39 | 40 | jz .nokey ; If no key, skip to end 41 | 42 | mov ax, 0 ; Otherwise get it from buffer 43 | int 16h 44 | 45 | mov [.tmp_buf], ax ; Store resulting keypress 46 | 47 | popa ; But restore all other regs 48 | mov ax, [.tmp_buf] 49 | ret 50 | 51 | .nokey: 52 | popa 53 | mov ax, 0 ; Zero result if no key pressed 54 | ret 55 | 56 | 57 | .tmp_buf dw 0 58 | 59 | 60 | ; ================================================================== 61 | 62 | -------------------------------------------------------------------------------- /source/features/math.asm: -------------------------------------------------------------------------------- 1 | ; ================================================================== 2 | ; MikeOS -- The Mike Operating System kernel 3 | ; Copyright (C) 2006 - 2014 MikeOS Developers -- see doc/LICENSE.TXT 4 | ; 5 | ; MATH ROUTINES 6 | ; ================================================================== 7 | 8 | ; ------------------------------------------------------------------ 9 | ; os_seed_random -- Seed the random number generator based on clock 10 | ; IN: Nothing; OUT: Nothing (registers preserved) 11 | 12 | os_seed_random: 13 | push bx 14 | push ax 15 | 16 | mov bx, 0 17 | mov al, 0x02 ; Minute 18 | out 0x70, al 19 | in al, 0x71 20 | 21 | mov bl, al 22 | shl bx, 8 23 | mov al, 0 ; Second 24 | out 0x70, al 25 | in al, 0x71 26 | mov bl, al 27 | 28 | mov word [os_random_seed], bx ; Seed will be something like 0x4435 (if it 29 | ; were 44 minutes and 35 seconds after the hour) 30 | pop ax 31 | pop bx 32 | ret 33 | 34 | 35 | os_random_seed dw 0 36 | 37 | 38 | ; ------------------------------------------------------------------ 39 | ; os_get_random -- Return a random integer between low and high (inclusive) 40 | ; IN: AX = low integer, BX = high integer 41 | ; OUT: CX = random integer 42 | 43 | os_get_random: 44 | push dx 45 | push bx 46 | push ax 47 | 48 | sub bx, ax ; We want a number between 0 and (high-low) 49 | call .generate_random 50 | mov dx, bx 51 | add dx, 1 52 | mul dx 53 | mov cx, dx 54 | 55 | pop ax 56 | pop bx 57 | pop dx 58 | add cx, ax ; Add the low offset back 59 | ret 60 | 61 | 62 | .generate_random: 63 | push dx 64 | push bx 65 | 66 | mov ax, [os_random_seed] 67 | mov dx, 0x7383 ; The magic number (random.org) 68 | mul dx ; DX:AX = AX * DX 69 | mov [os_random_seed], ax 70 | 71 | pop bx 72 | pop dx 73 | ret 74 | 75 | 76 | ; ------------------------------------------------------------------ 77 | ; os_bcd_to_int -- Converts binary coded decimal number to an integer 78 | ; IN: AL = BCD number; OUT: AX = integer value 79 | 80 | os_bcd_to_int: 81 | pusha 82 | 83 | mov bl, al ; Store entire number for now 84 | 85 | and ax, 0Fh ; Zero-out high bits 86 | mov cx, ax ; CH/CL = lower BCD number, zero extended 87 | 88 | shr bl, 4 ; Move higher BCD number into lower bits, zero fill msb 89 | mov al, 10 90 | mul bl ; AX = 10 * BL 91 | 92 | add ax, cx ; Add lower BCD to 10*higher 93 | mov [.tmp], ax 94 | 95 | popa 96 | mov ax, [.tmp] ; And return it in AX! 97 | ret 98 | 99 | 100 | .tmp dw 0 101 | 102 | 103 | ; ------------------------------------------------------------------ 104 | ; os_long_int_negate -- Multiply value in DX:AX by -1 105 | ; IN: DX:AX = long integer; OUT: DX:AX = -(initial DX:AX) 106 | 107 | os_long_int_negate: 108 | neg ax 109 | adc dx, 0 110 | neg dx 111 | ret 112 | 113 | 114 | ; ================================================================== 115 | 116 | -------------------------------------------------------------------------------- /source/features/misc.asm: -------------------------------------------------------------------------------- 1 | ; ================================================================== 2 | ; MikeOS -- The Mike Operating System kernel 3 | ; Copyright (C) 2006 - 2014 MikeOS Developers -- see doc/LICENSE.TXT 4 | ; 5 | ; MISCELLANEOUS ROUTINES 6 | ; ================================================================== 7 | 8 | ; ------------------------------------------------------------------ 9 | ; os_get_api_version -- Return current version of MikeOS API 10 | ; IN: Nothing; OUT: AL = API version number 11 | 12 | os_get_api_version: 13 | mov al, MIKEOS_API_VER 14 | ret 15 | 16 | 17 | ; ------------------------------------------------------------------ 18 | ; os_pause -- Delay execution for specified 110ms chunks 19 | ; IN: AX = 100 millisecond chunks to wait (max delay is 32767, 20 | ; which multiplied by 55ms = 1802 seconds = 30 minutes) 21 | 22 | os_pause: 23 | pusha 24 | cmp ax, 0 25 | je .time_up ; If delay = 0 then bail out 26 | 27 | mov cx, 0 28 | mov [.counter_var], cx ; Zero the counter variable 29 | 30 | mov bx, ax 31 | mov ax, 0 32 | mov al, 2 ; 2 * 55ms = 110mS 33 | mul bx ; Multiply by number of 110ms chunks required 34 | mov [.orig_req_delay], ax ; Save it 35 | 36 | mov ah, 0 37 | int 1Ah ; Get tick count 38 | 39 | mov [.prev_tick_count], dx ; Save it for later comparison 40 | 41 | .checkloop: 42 | mov ah,0 43 | int 1Ah ; Get tick count again 44 | 45 | cmp [.prev_tick_count], dx ; Compare with previous tick count 46 | 47 | jne .up_date ; If it's changed check it 48 | jmp .checkloop ; Otherwise wait some more 49 | 50 | .time_up: 51 | popa 52 | ret 53 | 54 | .up_date: 55 | mov ax, [.counter_var] ; Inc counter_var 56 | inc ax 57 | mov [.counter_var], ax 58 | 59 | cmp ax, [.orig_req_delay] ; Is counter_var = required delay? 60 | jge .time_up ; Yes, so bail out 61 | 62 | mov [.prev_tick_count], dx ; No, so update .prev_tick_count 63 | 64 | jmp .checkloop ; And go wait some more 65 | 66 | 67 | .orig_req_delay dw 0 68 | .counter_var dw 0 69 | .prev_tick_count dw 0 70 | 71 | 72 | ; ------------------------------------------------------------------ 73 | ; os_fatal_error -- Display error message and halt execution 74 | ; IN: AX = error message string location 75 | 76 | os_fatal_error: 77 | mov bx, ax ; Store string location for now 78 | 79 | mov dh, 0 80 | mov dl, 0 81 | call os_move_cursor 82 | 83 | pusha 84 | mov ah, 09h ; Draw red bar at top 85 | mov bh, 0 86 | mov cx, 240 87 | mov bl, 01001111b 88 | mov al, ' ' 89 | int 10h 90 | popa 91 | 92 | mov dh, 0 93 | mov dl, 0 94 | call os_move_cursor 95 | 96 | mov si, .msg_inform ; Inform of fatal error 97 | call os_print_string 98 | 99 | mov si, bx ; Program-supplied error message 100 | call os_print_string 101 | 102 | jmp $ ; Halt execution 103 | 104 | 105 | .msg_inform db '>>> FATAL OPERATING SYSTEM ERROR', 13, 10, 0 106 | 107 | 108 | ; ================================================================== 109 | 110 | -------------------------------------------------------------------------------- /source/features/ports.asm: -------------------------------------------------------------------------------- 1 | ; ================================================================== 2 | ; MikeOS -- The Mike Operating System kernel 3 | ; Copyright (C) 2006 - 2014 MikeOS Developers -- see doc/LICENSE.TXT 4 | ; 5 | ; PORT INPUT AND OUTPUT ROUTINES 6 | ; ================================================================== 7 | 8 | ; ------------------------------------------------------------------ 9 | ; os_port_byte_out -- Send byte to a port 10 | ; IN: DX = port address, AL = byte to send 11 | 12 | os_port_byte_out: 13 | pusha 14 | 15 | out dx, al 16 | 17 | popa 18 | ret 19 | 20 | 21 | ; ------------------------------------------------------------------ 22 | ; os_port_byte_in -- Receive byte from a port 23 | ; IN: DX = port address 24 | ; OUT: AL = byte from port 25 | 26 | os_port_byte_in: 27 | pusha 28 | 29 | in al, dx 30 | mov word [.tmp], ax 31 | 32 | popa 33 | mov ax, [.tmp] 34 | ret 35 | 36 | 37 | .tmp dw 0 38 | 39 | 40 | ; ------------------------------------------------------------------ 41 | ; os_serial_port_enable -- Set up the serial port for transmitting data 42 | ; IN: AX = 0 for normal mode (9600 baud), or 1 for slow mode (1200 baud) 43 | 44 | os_serial_port_enable: 45 | pusha 46 | 47 | mov dx, 0 ; Configure serial port 1 48 | cmp ax, 1 49 | je .slow_mode 50 | 51 | mov ah, 0 52 | mov al, 11100011b ; 9600 baud, no parity, 8 data bits, 1 stop bit 53 | jmp .finish 54 | 55 | .slow_mode: 56 | mov ah, 0 57 | mov al, 10000011b ; 1200 baud, no parity, 8 data bits, 1 stop bit 58 | 59 | .finish: 60 | int 14h 61 | 62 | popa 63 | ret 64 | 65 | 66 | ; ------------------------------------------------------------------ 67 | ; os_send_via_serial -- Send a byte via the serial port 68 | ; IN: AL = byte to send via serial; OUT: AH = Bit 7 clear on success 69 | 70 | os_send_via_serial: 71 | pusha 72 | 73 | mov ah, 01h 74 | mov dx, 0 ; COM1 75 | 76 | int 14h 77 | 78 | mov [.tmp], ax 79 | 80 | popa 81 | 82 | mov ax, [.tmp] 83 | 84 | ret 85 | 86 | 87 | .tmp dw 0 88 | 89 | 90 | ; ------------------------------------------------------------------ 91 | ; os_get_via_serial -- Get a byte from the serial port 92 | ; OUT: AL = byte that was received; OUT: AH = Bit 7 clear on success 93 | 94 | os_get_via_serial: 95 | pusha 96 | 97 | mov ah, 02h 98 | mov dx, 0 ; COM1 99 | 100 | int 14h 101 | 102 | mov [.tmp], ax 103 | 104 | popa 105 | 106 | mov ax, [.tmp] 107 | 108 | ret 109 | 110 | 111 | .tmp dw 0 112 | 113 | 114 | ; ================================================================== 115 | 116 | -------------------------------------------------------------------------------- /source/features/sound.asm: -------------------------------------------------------------------------------- 1 | ; ================================================================== 2 | ; MikeOS -- The Mike Operating System kernel 3 | ; Copyright (C) 2006 - 2014 MikeOS Developers -- see doc/LICENSE.TXT 4 | ; 5 | ; PC SPEAKER SOUND ROUTINES 6 | ; ================================================================== 7 | 8 | ; ------------------------------------------------------------------ 9 | ; os_speaker_tone -- Generate PC speaker tone (call os_speaker_off to turn off) 10 | ; IN: AX = note frequency; OUT: Nothing (registers preserved) 11 | 12 | os_speaker_tone: 13 | pusha 14 | 15 | mov cx, ax ; Store note value for now 16 | 17 | mov al, 182 18 | out 43h, al 19 | mov ax, cx ; Set up frequency 20 | out 42h, al 21 | mov al, ah 22 | out 42h, al 23 | 24 | in al, 61h ; Switch PC speaker on 25 | or al, 03h 26 | out 61h, al 27 | 28 | popa 29 | ret 30 | 31 | 32 | ; ------------------------------------------------------------------ 33 | ; os_speaker_off -- Turn off PC speaker 34 | ; IN/OUT: Nothing (registers preserved) 35 | 36 | os_speaker_off: 37 | pusha 38 | 39 | in al, 61h 40 | and al, 0FCh 41 | out 61h, al 42 | 43 | popa 44 | ret 45 | 46 | 47 | ; ================================================================== 48 | 49 | -------------------------------------------------------------------------------- /source/kernel.asm: -------------------------------------------------------------------------------- 1 | ; ================================================================== 2 | ; MikeOS -- The Mike Operating System kernel 3 | ; Copyright (C) 2006 - 2014 MikeOS Developers -- see doc/LICENSE.TXT 4 | ; 5 | ; This is loaded from the drive by BOOTLOAD.BIN, as KERNEL.BIN. 6 | ; First we have the system call vectors, which start at a static point 7 | ; for programs to use. Following that is the main kernel code and 8 | ; then additional system call code is included. 9 | ; ================================================================== 10 | 11 | 12 | BITS 16 13 | 14 | %DEFINE MIKEOS_VER '4.5' ; OS version number 15 | %DEFINE MIKEOS_API_VER 16 ; API version for programs to check 16 | 17 | 18 | ; This is the location in RAM for kernel disk operations, 24K 19 | ; after the point where the kernel has loaded; it's 8K in size, 20 | ; because external programs load after it at the 32K point: 21 | 22 | disk_buffer equ 24576 23 | 24 | 25 | ; ------------------------------------------------------------------ 26 | ; OS CALL VECTORS -- Static locations for system call vectors 27 | ; Note: these cannot be moved, or it'll break the calls! 28 | 29 | ; The comments show exact locations of instructions in this section, 30 | ; and are used in programs/mikedev.inc so that an external program can 31 | ; use a MikeOS system call without having to know its exact position 32 | ; in the kernel source code... 33 | 34 | os_call_vectors: 35 | jmp os_main ; 0000h -- Called from bootloader 36 | jmp os_print_string ; 0003h 37 | jmp os_move_cursor ; 0006h 38 | jmp os_clear_screen ; 0009h 39 | jmp os_print_horiz_line ; 000Ch 40 | jmp os_print_newline ; 000Fh 41 | jmp os_wait_for_key ; 0012h 42 | jmp os_check_for_key ; 0015h 43 | jmp os_int_to_string ; 0018h 44 | jmp os_speaker_tone ; 001Bh 45 | jmp os_speaker_off ; 001Eh 46 | jmp os_load_file ; 0021h 47 | jmp os_pause ; 0024h 48 | jmp os_fatal_error ; 0027h 49 | jmp os_draw_background ; 002Ah 50 | jmp os_string_length ; 002Dh 51 | jmp os_string_uppercase ; 0030h 52 | jmp os_string_lowercase ; 0033h 53 | jmp os_input_string ; 0036h 54 | jmp os_string_copy ; 0039h 55 | jmp os_dialog_box ; 003Ch 56 | jmp os_string_join ; 003Fh 57 | jmp os_get_file_list ; 0042h 58 | jmp os_string_compare ; 0045h 59 | jmp os_string_chomp ; 0048h 60 | jmp os_string_strip ; 004Bh 61 | jmp os_string_truncate ; 004Eh 62 | jmp os_bcd_to_int ; 0051h 63 | jmp os_get_time_string ; 0054h 64 | jmp os_get_api_version ; 0057h 65 | jmp os_file_selector ; 005Ah 66 | jmp os_get_date_string ; 005Dh 67 | jmp os_send_via_serial ; 0060h 68 | jmp os_get_via_serial ; 0063h 69 | jmp os_find_char_in_string ; 0066h 70 | jmp os_get_cursor_pos ; 0069h 71 | jmp os_print_space ; 006Ch 72 | jmp os_dump_string ; 006Fh 73 | jmp os_print_digit ; 0072h 74 | jmp os_print_1hex ; 0075h 75 | jmp os_print_2hex ; 0078h 76 | jmp os_print_4hex ; 007Bh 77 | jmp os_long_int_to_string ; 007Eh 78 | jmp os_long_int_negate ; 0081h 79 | jmp os_set_time_fmt ; 0084h 80 | jmp os_set_date_fmt ; 0087h 81 | jmp os_show_cursor ; 008Ah 82 | jmp os_hide_cursor ; 008Dh 83 | jmp os_dump_registers ; 0090h 84 | jmp os_string_strincmp ; 0093h 85 | jmp os_write_file ; 0096h 86 | jmp os_file_exists ; 0099h 87 | jmp os_create_file ; 009Ch 88 | jmp os_remove_file ; 009Fh 89 | jmp os_rename_file ; 00A2h 90 | jmp os_get_file_size ; 00A5h 91 | jmp os_input_dialog ; 00A8h 92 | jmp os_list_dialog ; 00ABh 93 | jmp os_string_reverse ; 00AEh 94 | jmp os_string_to_int ; 00B1h 95 | jmp os_draw_block ; 00B4h 96 | jmp os_get_random ; 00B7h 97 | jmp os_string_charchange ; 00BAh 98 | jmp os_serial_port_enable ; 00BDh 99 | jmp os_sint_to_string ; 00C0h 100 | jmp os_string_parse ; 00C3h 101 | jmp os_run_basic ; 00C6h 102 | jmp os_port_byte_out ; 00C9h 103 | jmp os_port_byte_in ; 00CCh 104 | jmp os_string_tokenize ; 00CFh 105 | 106 | 107 | ; ------------------------------------------------------------------ 108 | ; START OF MAIN KERNEL CODE 109 | 110 | os_main: 111 | cli ; Clear interrupts 112 | mov ax, 0 113 | mov ss, ax ; Set stack segment and pointer 114 | mov sp, 0FFFFh 115 | sti ; Restore interrupts 116 | 117 | cld ; The default direction for string operations 118 | ; will be 'up' - incrementing address in RAM 119 | 120 | mov ax, 2000h ; Set all segments to match where kernel is loaded 121 | mov ds, ax ; After this, we don't need to bother with 122 | mov es, ax ; segments ever again, as MikeOS and its programs 123 | mov fs, ax ; live entirely in 64K 124 | mov gs, ax 125 | 126 | cmp dl, 0 127 | je no_change 128 | mov [bootdev], dl ; Save boot device number 129 | push es 130 | mov ah, 8 ; Get drive parameters 131 | int 13h 132 | pop es 133 | and cx, 3Fh ; Maximum sector number 134 | mov [SecsPerTrack], cx ; Sector numbers start at 1 135 | movzx dx, dh ; Maximum head number 136 | add dx, 1 ; Head numbers start at 0 - add 1 for total 137 | mov [Sides], dx 138 | 139 | no_change: 140 | mov ax, 1003h ; Set text output with certain attributes 141 | mov bx, 0 ; to be bright, and not blinking 142 | int 10h 143 | 144 | call os_seed_random ; Seed random number generator 145 | 146 | 147 | ; Let's see if there's a file called AUTORUN.BIN and execute 148 | ; it if so, before going to the program launcher menu 149 | 150 | mov ax, autorun_bin_file_name 151 | call os_file_exists 152 | jc no_autorun_bin ; Skip next three lines if AUTORUN.BIN doesn't exist 153 | 154 | mov cx, 32768 ; Otherwise load the program into RAM... 155 | call os_load_file 156 | jmp execute_bin_program ; ...and move on to the executing part 157 | 158 | 159 | ; Or perhaps there's an AUTORUN.BAS file? 160 | 161 | no_autorun_bin: 162 | mov ax, autorun_bas_file_name 163 | call os_file_exists 164 | jc option_screen ; Skip next section if AUTORUN.BAS doesn't exist 165 | 166 | mov cx, 32768 ; Otherwise load the program into RAM 167 | call os_load_file 168 | call os_clear_screen 169 | mov ax, 32768 170 | call os_run_basic ; Run the kernel's BASIC interpreter 171 | 172 | jmp app_selector ; And go to the app selector menu when BASIC ends 173 | 174 | 175 | ; Now we display a dialog box offering the user a choice of 176 | ; a menu-driven program selector, or a command-line interface 177 | 178 | option_screen: 179 | mov ax, os_init_msg ; Set up the welcome screen 180 | mov bx, os_version_msg 181 | mov cx, 10011111b ; Colour: white text on light blue 182 | call os_draw_background 183 | 184 | mov ax, dialog_string_1 ; Ask if user wants app selector or command-line 185 | mov bx, dialog_string_2 186 | mov cx, dialog_string_3 187 | mov dx, 1 ; We want a two-option dialog box (OK or Cancel) 188 | call os_dialog_box 189 | 190 | cmp ax, 1 ; If OK (option 0) chosen, start app selector 191 | jne near app_selector 192 | 193 | call os_clear_screen ; Otherwise clean screen and start the CLI 194 | call os_command_line 195 | 196 | jmp option_screen ; Offer menu/CLI choice after CLI has exited 197 | 198 | 199 | ; Data for the above code... 200 | 201 | os_init_msg db 'Welcome to MikeOS', 0 202 | os_version_msg db 'Version ', MIKEOS_VER, 0 203 | 204 | dialog_string_1 db 'Thanks for trying out MikeOS!', 0 205 | dialog_string_2 db 'Please select an interface: OK for the', 0 206 | dialog_string_3 db 'program menu, Cancel for command line.', 0 207 | 208 | 209 | 210 | app_selector: 211 | mov ax, os_init_msg ; Draw main screen layout 212 | mov bx, os_version_msg 213 | mov cx, 10011111b ; Colour: white text on light blue 214 | call os_draw_background 215 | 216 | call os_file_selector ; Get user to select a file, and store 217 | ; the resulting string location in AX 218 | ; (other registers are undetermined) 219 | 220 | jc option_screen ; Return to the CLI/menu choice screen if Esc pressed 221 | 222 | mov si, ax ; Did the user try to run 'KERNEL.BIN'? 223 | mov di, kern_file_name 224 | call os_string_compare 225 | jc no_kernel_execute ; Show an error message if so 226 | 227 | 228 | ; Next, we need to check that the program we're attempting to run is 229 | ; valid -- in other words, that it has a .BIN extension 230 | 231 | push si ; Save filename temporarily 232 | 233 | mov bx, si 234 | mov ax, si 235 | call os_string_length 236 | 237 | mov si, bx 238 | add si, ax ; SI now points to end of filename... 239 | 240 | dec si 241 | dec si 242 | dec si ; ...and now to start of extension! 243 | 244 | mov di, bin_ext 245 | mov cx, 3 246 | rep cmpsb ; Are final 3 chars 'BIN'? 247 | jne not_bin_extension ; If not, it might be a '.BAS' 248 | 249 | pop si ; Restore filename 250 | 251 | 252 | mov ax, si 253 | mov cx, 32768 ; Where to load the program file 254 | call os_load_file ; Load filename pointed to by AX 255 | 256 | 257 | execute_bin_program: 258 | call os_clear_screen ; Clear screen before running 259 | 260 | mov ax, 0 ; Clear all registers 261 | mov bx, 0 262 | mov cx, 0 263 | mov dx, 0 264 | mov si, 0 265 | mov di, 0 266 | 267 | call 32768 ; Call the external program code, 268 | ; loaded at second 32K of segment 269 | ; (program must end with 'ret') 270 | 271 | call os_clear_screen ; When finished, clear screen 272 | jmp app_selector ; and go back to the program list 273 | 274 | 275 | no_kernel_execute: ; Warn about trying to executing kernel! 276 | mov ax, kerndlg_string_1 277 | mov bx, kerndlg_string_2 278 | mov cx, kerndlg_string_3 279 | mov dx, 0 ; One button for dialog box 280 | call os_dialog_box 281 | 282 | jmp app_selector ; Start over again... 283 | 284 | 285 | not_bin_extension: 286 | pop si ; We pushed during the .BIN extension check 287 | 288 | push si ; Save it again in case of error... 289 | 290 | mov bx, si 291 | mov ax, si 292 | call os_string_length 293 | 294 | mov si, bx 295 | add si, ax ; SI now points to end of filename... 296 | 297 | dec si 298 | dec si 299 | dec si ; ...and now to start of extension! 300 | 301 | mov di, bas_ext 302 | mov cx, 3 303 | rep cmpsb ; Are final 3 chars 'BAS'? 304 | jne not_bas_extension ; If not, error out 305 | 306 | 307 | pop si 308 | 309 | mov ax, si 310 | mov cx, 32768 ; Where to load the program file 311 | call os_load_file ; Load filename pointed to by AX 312 | 313 | call os_clear_screen ; Clear screen before running 314 | 315 | mov ax, 32768 316 | mov si, 0 ; No params to pass 317 | call os_run_basic ; And run our BASIC interpreter on the code! 318 | 319 | mov si, basic_finished_msg 320 | call os_print_string 321 | call os_wait_for_key 322 | 323 | call os_clear_screen 324 | jmp app_selector ; and go back to the program list 325 | 326 | 327 | not_bas_extension: 328 | pop si 329 | 330 | mov ax, ext_string_1 331 | mov bx, ext_string_2 332 | mov cx, 0 333 | mov dx, 0 ; One button for dialog box 334 | call os_dialog_box 335 | 336 | jmp app_selector ; Start over again... 337 | 338 | 339 | ; And now data for the above code... 340 | 341 | kern_file_name db 'KERNEL.BIN', 0 342 | 343 | autorun_bin_file_name db 'AUTORUN.BIN', 0 344 | autorun_bas_file_name db 'AUTORUN.BAS', 0 345 | 346 | bin_ext db 'BIN' 347 | bas_ext db 'BAS' 348 | 349 | kerndlg_string_1 db 'Cannot load and execute MikeOS kernel!', 0 350 | kerndlg_string_2 db 'KERNEL.BIN is the core of MikeOS, and', 0 351 | kerndlg_string_3 db 'is not a normal program.', 0 352 | 353 | ext_string_1 db 'Invalid filename extension! You can', 0 354 | ext_string_2 db 'only execute .BIN or .BAS programs.', 0 355 | 356 | basic_finished_msg db '>>> BASIC program finished -- press a key', 0 357 | 358 | 359 | ; ------------------------------------------------------------------ 360 | ; SYSTEM VARIABLES -- Settings for programs and system calls 361 | 362 | 363 | ; Time and date formatting 364 | 365 | fmt_12_24 db 0 ; Non-zero = 24-hr format 366 | 367 | fmt_date db 0, '/' ; 0, 1, 2 = M/D/Y, D/M/Y or Y/M/D 368 | ; Bit 7 = use name for months 369 | ; If bit 7 = 0, second byte = separator character 370 | 371 | 372 | ; ------------------------------------------------------------------ 373 | ; FEATURES -- Code to pull into the kernel 374 | 375 | 376 | %INCLUDE "features/cli.asm" 377 | %INCLUDE "features/disk.asm" 378 | %INCLUDE "features/keyboard.asm" 379 | %INCLUDE "features/math.asm" 380 | %INCLUDE "features/misc.asm" 381 | %INCLUDE "features/ports.asm" 382 | %INCLUDE "features/screen.asm" 383 | %INCLUDE "features/sound.asm" 384 | %INCLUDE "features/string.asm" 385 | %INCLUDE "features/basic.asm" 386 | 387 | 388 | ; ================================================================== 389 | ; END OF KERNEL 390 | ; ================================================================== 391 | 392 | -------------------------------------------------------------------------------- /source/kernel.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mig-hub/mikeOS/685306a87ddf1a41c069ec7670d24c7d2023ff20/source/kernel.bin -------------------------------------------------------------------------------- /test-linux.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # This script starts the QEMU PC emulator, booting from the 4 | # MikeOS floppy disk image 5 | 6 | qemu-system-i386 -soundhw pcspk -fda disk_images/mikeos.flp 7 | 8 | --------------------------------------------------------------------------------