Add test/example programs for monolithium.
authorcoderain <coderain@sdf.org>
Fri, 17 Feb 2017 02:35:25 +0000 (03:35 +0100)
committercoderain <coderain@sdf.org>
Fri, 17 Feb 2017 02:35:25 +0000 (03:35 +0100)
.gitignore
tests/.gitignore [new file with mode: 0644]
tests/Makefile [new file with mode: 0644]
tests/hello.asm [new file with mode: 0644]
tests/mkfat.sh [new file with mode: 0755]

index da918ee1c9d7279188030e8fc9ae5023b08a7a6b..e360b303a37e23adcc8db1a22c179f0d641813e3 100644 (file)
@@ -10,3 +10,5 @@
 !kernel/*
 !library
 !library/*
+!tests
+!tests/*
diff --git a/tests/.gitignore b/tests/.gitignore
new file mode 100644 (file)
index 0000000..fd3565e
--- /dev/null
@@ -0,0 +1,7 @@
+*
+
+# Include the following files:
+!.gitignore
+!Makefile
+!mkfat.sh
+!*.asm
diff --git a/tests/Makefile b/tests/Makefile
new file mode 100644 (file)
index 0000000..9a2a8ba
--- /dev/null
@@ -0,0 +1,42 @@
+#
+# Makefile
+#
+# Copyright (C) 2017 Aleksandar Andrejevic <theflash@sdf.lonestar.org>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+# Compilers and tools
+ASM = nasm
+
+# Flags
+ASMFLAGS = -faout
+
+# Input and output files
+SOURCES = $(wildcard *.asm)
+OBJECTS = $(patsubst %.asm, %.prg, $(SOURCES))
+
+.PHONY: all clean
+
+all: floppy.img
+
+%.prg: %.asm Makefile
+       $(ASM) $(ASMFLAGS) -o $@ $<
+
+floppy.img: $(OBJECTS) mkfat.sh Makefile
+       ./mkfat.sh 2>/dev/null
+
+clean:
+       find $(OBJDIR) -name \*.prg -delete
+       rm floppy.img
diff --git a/tests/hello.asm b/tests/hello.asm
new file mode 100644 (file)
index 0000000..6e98b51
--- /dev/null
@@ -0,0 +1,71 @@
+;
+; hello.asm
+;
+; Copyright (C) 2017 Aleksandar Andrejevic <theflash@sdf.lonestar.org>
+;
+; This program is free software: you can redistribute it and/or modify
+; it under the terms of the GNU Affero General Public License as
+; published by the Free Software Foundation, either version 3 of the
+; License, or (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; GNU Affero General Public License for more details.
+;
+; You should have received a copy of the GNU Affero General Public License
+; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+;
+
+bits 32
+
+section .text
+
+start:                  push 0
+                        push 0
+                        push handle
+                        push name
+                        call open_file
+                        add esp, 16
+                        push 4
+                        push address
+                        push 12
+                        push framebuffer
+                        push 0xC9000004
+                        push dword [handle]
+                        call device_ioctl
+                        add esp, 24
+                        or eax, eax
+                        jnz .stop
+                        mov edi, dword [address]
+                        lea esi, [edi + 160]
+                        mov ecx, 960
+                        cld
+                        rep movsd
+                        mov eax, 0x07200720
+                        mov ecx, 40
+                        rep stosd
+                        sub edi, 160
+                        mov esi, message
+                        mov ecx, 13
+                        rep movsw
+.stop:                  xor eax, eax
+                        not eax
+                        push eax
+                        push eax
+                        call sleep
+                        add esp, 8
+                        jmp .stop
+
+%include "../library/src/syscall.asm"
+
+section .data
+
+handle:                 DD 0
+name:                   DB '@Video0', 0
+framebuffer:            DD 0x10000000
+                        DD 0
+                        DD 80 * 25 * 2
+address:                DD 0
+message:                DB 'H', 7, 'e', 7, 'l', 7, 'l', 7, 'o', 7, ',', 7, ' ',
+                        DB  7, 'w', 7, 'o', 7, 'r', 7, 'l', 7, 'd', 7, '!', 7
diff --git a/tests/mkfat.sh b/tests/mkfat.sh
new file mode 100755 (executable)
index 0000000..c1891f4
--- /dev/null
@@ -0,0 +1,154 @@
+#!/bin/bash
+#
+# mkfat.sh
+#
+# Copyright (C) 2017 Aleksandar Andrejevic <theflash@sdf.lonestar.org>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+OUTPUT_FILE=floppy.img
+
+function get_free_cluster()
+{
+    local cluster=2
+
+    while [[ "$cluster" -lt 3072 ]]
+    do
+        local cluster_pair=`dd if=$OUTPUT_FILE skip=$((0x200 + 3 * (cluster / 2))) bs=1 count=3 2>/dev/null | xxd -p`
+
+        if [[ "${cluster_pair:3:1}${cluster_pair:0:2}" == "000" ]] && [[ "$cluster" -ne 2 ]]
+        then
+            echo "Found a free cluster: $cluster" > /dev/stderr
+            echo $cluster
+            return
+        elif [[ "${cluster_pair:4:2}${cluster_pair:2:1}" == "000" ]]
+        then
+            echo "Found a free cluster: $((cluster + 1))" > /dev/stderr
+            echo $((cluster + 1))
+            return
+        fi
+
+        cluster=$((cluster + 2))
+    done
+
+    echo 'Ran out of the free clusters.' > /dev/stderr
+    rm $OUTPUT_FILE
+    exit 1
+}
+
+function set_next_cluster()
+{
+    echo "Setting the next cluster of $1 to $2" > /dev/stderr
+
+    local cluster=$1
+    local value=$(printf "%03X" $2)
+    local cluster_pair=`dd if=$OUTPUT_FILE skip=$((0x200 + 3 * (cluster / 2))) bs=1 count=3 2>/dev/null | xxd -p`
+
+    if [[ "$((cluster % 2))" -eq 0 ]]
+    then
+        cluster_pair="${value:1:2}${cluster_pair:2:1}${value:0:1}${cluster_pair:4:2}"
+    else
+        cluster_pair="${cluster_pair:0:2}${value:2:1}${cluster_pair:3:1}${value:0:2}"
+    fi
+
+    echo $cluster_pair | xxd -r -p | dd conv=notrunc \
+                                        iflag=fullblock \
+                                        oflag=seek_bytes \
+                                        of=$OUTPUT_FILE \
+                                        seek=$((0x200 + 3 * (cluster / 2))) \
+                                        bs=3 \
+                                        count=1 \
+                                        2>/dev/null
+    echo $cluster_pair | xxd -r -p | dd conv=notrunc \
+                                        iflag=fullblock \
+                                        oflag=seek_bytes \
+                                        of=$OUTPUT_FILE \
+                                        seek=$((0x1400 + 3 * (cluster / 2))) \
+                                        bs=3 \
+                                        count=1 \
+                                        2>/dev/null
+}
+
+dd if=/dev/zero of=$OUTPUT_FILE bs=512 count=2880 2>/dev/null
+/sbin/mkfs.vfat $OUTPUT_FILE 2>&1 >/dev/null
+
+echo "Created empty FAT12 disk image $OUTPUT_FILE" > /dev/stderr
+
+for file in *.prg
+do
+    [[ -f $file ]] || break
+    echo "Copying $file to the disk image..." > /dev/stderr
+
+    size=`stat --printf '%s' $file`
+    clusters=$(((size + 511) / 512))
+    dosname=$(printf '%-8s%-3s' `echo ${file%%.*} | tr 'a-z' 'A-Z'` `echo ${file##*.} | tr 'a-z' 'A-Z'`)
+
+    for ((dirent = 0; dirent < 16; dirent++))
+    do
+        if [[ `dd if=$OUTPUT_FILE skip=$((dirent * 32 + 0x2600)) bs=1 count=1 2>/dev/null | xxd -p` == "00" ]]
+        then
+            break
+        fi
+    done
+
+    if [[ $dirent -ge 224 ]]
+    then
+        echo 'Too many files, sorry.' > /dev/stderr
+        exit 1
+    fi
+
+    echo "$file will be placed in directory entry number $dirent" > /dev/stderr
+
+    if [[ $clusters -ne 0 ]]
+    then
+        first_cluster=`get_free_cluster`
+        if [[ $? -ne 0 ]]
+        then
+            echo 'No more free clusters...'
+            exit 1
+        fi
+    else
+        first_cluster=0
+    fi
+
+    (
+        echo -en "${dosname}\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+        printf '%02X%02X' $((first_cluster % 256)) $((first_cluster / 256)) | xxd -r -p | tr -d '\n'
+        printf "%02X%02X%02X%02X" \
+               $((size % 256)) \
+               $(((size / 256) % 256)) \
+               $(((size / 65536) % 256)) \
+               $(((size / 16777216) % 256)) | xxd -r -p | tr -d '\n'
+    ) | dd conv=notrunc iflag=fullblock of=$OUTPUT_FILE seek=$((304 + dirent)) bs=32 count=1 2>/dev/null
+
+    current_cluster=$first_cluster
+
+    for ((i = 0; i < $clusters; i++))
+    do
+        echo "Writing cluster #$i of $file to cluster $current_cluster" > /dev/stderr
+        dd conv=notrunc if=$file of=$OUTPUT_FILE skip=$i seek=$((31 + current_cluster)) bs=512 count=1 2>/dev/null
+
+        set_next_cluster $current_cluster 4095
+
+        if [[ "$i" -ne "$((clusters - 1))" ]]
+        then
+            next_cluster=`get_free_cluster`
+            set_next_cluster $current_cluster $next_cluster
+            current_cluster=$next_cluster
+        fi
+    done
+done
+
+echo "All done!" > /dev/stderr