Guo Hui 6 anni fa
parent
commit
db1d7066fc

+ 1 - 0
Natsu.sln

@@ -11,6 +11,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Natsu.Compiler", "src\Natsu
 		{9D224463-2FCE-4C20-B036-7600FC66969A} = {9D224463-2FCE-4C20-B036-7600FC66969A}
 		{20176878-F31F-4D92-918C-9FD58CDD7480} = {20176878-F31F-4D92-918C-9FD58CDD7480}
 		{7374FA7F-5B76-40C8-8F8F-EB9CA53A8C2F} = {7374FA7F-5B76-40C8-8F8F-EB9CA53A8C2F}
+		{A18A0788-13D2-49A3-908D-6DBBCB5A739C} = {A18A0788-13D2-49A3-908D-6DBBCB5A739C}
 		{ADE6DF88-5CAF-4BD5-86E5-4C9F8DF09CDF} = {ADE6DF88-5CAF-4BD5-86E5-4C9F8DF09CDF}
 		{C4408589-968A-43B3-83A6-AF02D1BAA293} = {C4408589-968A-43B3-83A6-AF02D1BAA293}
 		{8309558E-335D-4662-B56B-11AFD5E1C1C3} = {8309558E-335D-4662-B56B-11AFD5E1C1C3}

+ 4 - 2
src/Chino.Interop/Chino/IO/IO.cs

@@ -38,7 +38,9 @@ public static partial class Interop
         [MethodImpl(MethodImplOptions.InternalCall)]
         public static extern bool StdinReady();
 
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        public static extern unsafe int ReadStdin(byte* buffer, int bufferSize);
+        public static unsafe int ReadStdin(byte* buffer, int bufferSize)
+        {
+            return Read(StdinHandle, new Span<byte>(buffer, bufferSize));
+        }
     }
 }

+ 2 - 2
src/Chino.Interop/Chino/Text/Text.cs

@@ -28,7 +28,7 @@ public static partial class Interop
         /// On failure, returns a negative value.
         /// </returns>
         [MethodImpl(MethodImplOptions.InternalCall)]
-        public static extern unsafe int SNPrintF(byte* str, int size, string format, string arg1);
+        public static extern unsafe int SNPrintF(byte* str, int size, byte[] format, byte[] arg1);
 
         /// <summary>
         /// Takes a string and applies a formatting to it to transform
@@ -49,6 +49,6 @@ public static partial class Interop
         /// On failure, returns a negative value.
         /// </returns>
         [MethodImpl(MethodImplOptions.InternalCall)]
-        public static extern unsafe int SNPrintF(byte* str, int size, string format, int arg1);
+        public static extern unsafe int SNPrintF(byte* str, int size, byte[] format, int arg1);
     }
 }

+ 0 - 1
src/Chino.Kernel/KernelProgram.cs

@@ -19,7 +19,6 @@ namespace Chino.Kernel
                 var host = new KernelServiceHost();
 
                 var terminal = Terminal.Default;
-
                 terminal.Foreground(TerminalColor.White)
                     .WriteLine("Hello Chino OS!");
                 host.Run();

+ 29 - 0
src/Chino.Kernel/Services/ConsoleHostService.cs

@@ -0,0 +1,29 @@
+using Chino.IO;
+using Chino.IO.Devices;
+using Chino.Objects;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Chino.Services
+{
+    public sealed class ConsoleHostService
+    {
+        public static ConsoleHostService Current { get; } = new ConsoleHostService();
+
+        public Accessor<Device> Stdin { get; }
+
+        public Accessor<Device> Stdout { get; }
+
+        public Accessor<Device> Stderr { get; }
+
+        public ConsoleHostService()
+        {
+            var defaultConsole = ConsoleDevice.DefaultDevicePath;
+
+            Stdin = ObjectManager.OpenObject<Device>(AccessMask.GenericRead, new ObjectAttributes { Name = defaultConsole });
+            Stdout = ObjectManager.OpenObject<Device>(AccessMask.GenericWrite, new ObjectAttributes { Name = defaultConsole });
+            Stderr = ObjectManager.OpenObject<Device>(AccessMask.GenericWrite, new ObjectAttributes { Name = defaultConsole });
+        }
+    }
+}

+ 8 - 0
src/Native/CMakeLists.txt

@@ -14,12 +14,19 @@ endif()
 set(SRCS natsu.fcall.cpp
          natsu.runtime.cpp
          natsu.gc.cpp
+         natsu.array.cpp
+         natsu.buffer.cpp
+         natsu.console.cpp
+         natsu.debug.cpp
+         natsu.math.cpp
+         natsu.string.cpp
          natsu.unicode.cpp
          natsu.threading.cpp
          chino.runtime.cpp
          main.cpp
          Generated/${CHINO_APP}.cpp
          Generated/System.Private.CoreLib.cpp
+         Generated/System.Console.cpp
          Generated/System.Collections.cpp
          Generated/System.Diagnostics.Debug.cpp
          Generated/System.Runtime.cpp
@@ -28,6 +35,7 @@ set(SRCS natsu.fcall.cpp
          Generated/Chino.IO.cpp
          Generated/Chino.Threading.cpp
          Generated/Chino.Kernel.cpp
+         Generated/Chino.Interop.cpp
          Generated/BitFields.cpp)
 
 add_executable(chino ${SRCS} ${ASM_SRCS})

+ 72 - 1
src/Native/chino.runtime.cpp

@@ -1,4 +1,5 @@
 #include "Chino.Kernel.h"
+#include "Chino.Interop.h"
 #include <cmath>
 #include <cstring>
 
@@ -13,11 +14,81 @@
 
 using namespace natsu;
 using namespace Chino_Core::Chino;
+using namespace Chino_Core::Chino::Objects;
+using namespace Chino_IO::Chino::IO;
+using namespace Chino_IO::Chino::IO::Devices;
 using namespace Chino_Kernel::Chino;
 using namespace Chino_Kernel::Chino::Services;
-using namespace System_Runtime::System;
+using namespace Chino_Interop;
+using namespace Chino_Interop::Chino;
+using namespace System_Private_CoreLib::System;
+
+namespace
+{
+gc_obj_ref<SafeFileHandle> make_handle(gc_obj_ref<> obj)
+{
+    auto handle = make_object<SafeFileHandle>();
+    handle->_accessor = obj.cast<IDisposable>();
+    return handle;
+}
+
+gc_obj_ref<Accessor_1<Device>> get_device(gc_obj_ref<SafeFileHandle> handle)
+{
+    check_null_obj_ref(handle);
+    auto accessor = handle->_accessor.cast<Accessor_1<Device>>();
+    check_null_obj_ref(accessor);
+    return accessor;
+}
+}
 
 void KernelServiceHost::UserAppMain(gc_obj_ref<KernelServiceHost> _this)
 {
     CHINO_APP_MODULE::CHINO_APP_NAMESPACE::Program::_s_Main(nullptr);
 }
+
+gc_obj_ref<SafeFileHandle> Interop_IO::_s_get_StdinHandle()
+{
+    return make_handle(ConsoleHostService::get_Stdin(ConsoleHostService::_s_get_Current()));
+}
+
+gc_obj_ref<SafeFileHandle> Interop_IO::_s_get_StdoutHandle()
+{
+    return make_handle(ConsoleHostService::get_Stdout(ConsoleHostService::_s_get_Current()));
+}
+
+gc_obj_ref<SafeFileHandle> Interop_IO::_s_get_StderrHandle()
+{
+    return make_handle(ConsoleHostService::get_Stderr(ConsoleHostService::_s_get_Current()));
+}
+
+bool Interop_IO::_s_IsConsoleHandle(gc_obj_ref<SafeFileHandle> handle)
+{
+    return (bool)ops::isinst<ConsoleDevice>(get_device(handle)->_object);
+}
+
+bool Interop_IO::_s_StdinReady()
+{
+    return true;
+}
+
+int32_t Interop_IO::_s_Read(gc_obj_ref<SafeFileHandle> handle, Span_1<uint8_t> buffer)
+{
+    auto device = get_device(handle);
+    return vtable<Device>(device->_object).Read_System__Span_1_System__Byte(device->_object, buffer);
+}
+
+void Interop_IO::_s_Write(gc_obj_ref<SafeFileHandle> handle, ReadOnlySpan_1<uint8_t> buffer)
+{
+    auto device = get_device(handle);
+    return vtable<Device>(device->_object).Write_System__ReadOnlySpan_1_System__Byte(device->_object, buffer);
+}
+
+int32_t Interop_Text::_s_SNPrintF(gc_ptr<uint8_t> str, int32_t size, gc_obj_ref<SZArray_1<uint8_t>> format, gc_obj_ref<SZArray_1<uint8_t>> arg1)
+{
+    return std::snprintf(reinterpret_cast<char *>(str.ptr_), size, reinterpret_cast<const char *>(format->elements_), reinterpret_cast<const char *>(arg1->elements_));
+}
+
+int32_t Interop_Text::_s_SNPrintF(gc_ptr<uint8_t> str, int32_t size, gc_obj_ref<SZArray_1<uint8_t>> format, int32_t arg1)
+{
+    return std::snprintf(reinterpret_cast<char *>(str.ptr_), size, reinterpret_cast<const char *>(format->elements_), arg1);
+}

+ 90 - 0
src/Native/natsu.array.cpp

@@ -0,0 +1,90 @@
+#include "System.Private.CoreLib.h"
+
+using namespace natsu;
+using namespace System_Private_CoreLib;
+using namespace System_Private_CoreLib::System;
+using namespace System_Private_CoreLib::System::Runtime::CompilerServices;
+
+int32_t Array::GetLength(gc_obj_ref<Array> _this, int32_t dimension)
+{
+    if (dimension != 0)
+        throw_index_out_of_range_exception();
+    return (intptr_t)_this.cast<RawSzArrayData>()->Count;
+}
+
+int32_t Array::get_Rank(gc_obj_ref<Array> _this)
+{
+    return 1;
+}
+
+int32_t Array::get_Length(gc_obj_ref<Array> _this)
+{
+    return (intptr_t)_this.cast<RawSzArrayData>()->Count;
+}
+
+int64_t Array::get_LongLength(gc_obj_ref<Array> _this)
+{
+    return (intptr_t)_this.cast<RawSzArrayData>()->Count;
+}
+
+int32_t Array::GetUpperBound(gc_obj_ref<Array> _this, int32_t dimension)
+{
+    return GetLength(_this, dimension);
+}
+
+int32_t Array::GetLowerBound(gc_obj_ref<Array> _this, int32_t dimension)
+{
+    if (dimension != 0)
+        throw_exception<IndexOutOfRangeException>();
+    return 0;
+}
+
+void Array::_s_Copy(gc_obj_ref<Array> sourceArray, int32_t sourceIndex, gc_obj_ref<Array> destinationArray, int32_t destinationIndex, int32_t length, bool reliable)
+{
+    check_null_obj_ref(sourceArray);
+    check_null_obj_ref(destinationArray);
+    auto src = sourceArray.cast<RawSzArrayData>();
+    auto dest = sourceArray.cast<RawSzArrayData>();
+    auto element_size = sourceArray.header().vtable_->ElementSize;
+
+    if ((sourceIndex + length) > (intptr_t)src->Count || (destinationIndex + length) > (intptr_t)dest->Count)
+        throw_index_out_of_range_exception();
+
+    if (sourceArray.header().vtable_ != destinationArray.header().vtable_)
+        throw_exception<ArrayTypeMismatchException>();
+    std::memmove(&dest->Data + (size_t)destinationIndex * element_size, &src->Data + (size_t)sourceIndex * element_size, (size_t)length * element_size);
+}
+
+gc_ref<uint8_t> Array::_s_GetRawArrayGeometry(gc_obj_ref<Array> array, gc_ref<uint32_t> numComponents, gc_ref<uint32_t> elementSize, gc_ref<int32_t> lowerBound, ::natsu::gc_ref<bool> containsGCPointers)
+{
+    *numComponents = (uint32_t)Array::GetLength(array, 0);
+    *elementSize = array.header().vtable_->ElementSize;
+    *lowerBound = Array::GetLowerBound(array, 0);
+    *containsGCPointers = true;
+    return array.cast<RawSzArrayData>()->Data;
+}
+
+bool Array::_s_TrySZReverse(gc_obj_ref<Array> array, int32_t index, int32_t count)
+{
+    check_null_obj_ref(array);
+    auto src = array.cast<RawSzArrayData>();
+    auto element_size = array.header().vtable_->ElementSize;
+    auto data = reinterpret_cast<uint8_t *>(&src->Data);
+
+    if ((index + count) > (intptr_t)src->Count)
+        return false;
+
+    size_t i = index, j = index + count - 1;
+    void *tmp = alloca(element_size);
+    while (i < j)
+    {
+        std::memcpy(tmp, data + i * element_size, element_size);
+        std::memcpy(data + j * element_size, data + i * element_size, element_size);
+        std::memcpy(data + j * element_size, tmp, element_size);
+
+        i++;
+        j--;
+    }
+
+    return true;
+}

+ 37 - 0
src/Native/natsu.buffer.cpp

@@ -0,0 +1,37 @@
+#include "System.Private.CoreLib.h"
+#include <cstring>
+
+using namespace natsu;
+using namespace System_Private_CoreLib;
+using namespace System_Private_CoreLib::System;
+using namespace System_Private_CoreLib::System::Runtime::CompilerServices;
+
+void Buffer::_s_BlockCopy(gc_obj_ref<Array> src, int32_t srcOffset, gc_obj_ref<Array> dst, int32_t dstOffset, int32_t count)
+{
+    check_null_obj_ref(src);
+    check_null_obj_ref(dst);
+    auto src_arr = src.cast<RawSzArrayData>();
+    auto dest_arr = dst.cast<RawSzArrayData>();
+    auto element_size_src = src.header().vtable_->ElementSize;
+    auto element_size_dest = dst.header().vtable_->ElementSize;
+    auto src_begin = reinterpret_cast<uint8_t *>(&src_arr->Data);
+    auto src_bytes = src_arr->Count * element_size_src;
+    auto dest_begin = reinterpret_cast<uint8_t *>(&dest_arr->Data);
+    auto dest_bytes = dest_arr->Count * element_size_dest;
+
+    if (srcOffset < 0 || dstOffset < 0 || count < 0)
+        throw_index_out_of_range_exception();
+    if ((srcOffset + count) > src_bytes || (dstOffset + count) > dest_bytes)
+        throw_exception<ArgumentException>();
+    std::memmove(dest_begin, src_begin, count);
+}
+
+void Buffer::_s_Memcpy(gc_ptr<uint8_t> dest, gc_ptr<uint8_t> src, int32_t len)
+{
+    std::memcpy(dest.get(), src.get(), len);
+}
+
+void Buffer::_s_Memmove(gc_ptr<uint8_t> dest, gc_ptr<uint8_t> src, uint64_t len)
+{
+    std::memmove(dest.get(), src.get(), len);
+}

+ 465 - 0
src/Native/natsu.console.cpp

@@ -0,0 +1,465 @@
+#include "System.Console.h"
+#include "System.Private.CoreLib.h"
+
+using namespace natsu;
+using namespace System_Private_CoreLib;
+using namespace System_Private_CoreLib::System;
+using namespace System_Console::System;
+
+namespace
+{
+static const constexpr auto xterm_256color_name = make_string_literal(u"xterm-256color");
+
+// clang-format off
+// Generated by vscode-hexdump
+static const constexpr auto xterm_256color_data = make_szarray_literal<uint8_t, 3525>(
+{
+	0x1a, 0x01, 0x25, 0x00, 0x26, 0x00, 0x0f, 0x00, 
+	0x9d, 0x01, 0x02, 0x06, 0x78, 0x74, 0x65, 0x72, 
+	0x6d, 0x2d, 0x32, 0x35, 0x36, 0x63, 0x6f, 0x6c, 
+	0x6f, 0x72, 0x7c, 0x78, 0x74, 0x65, 0x72, 0x6d, 
+	0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x32, 0x35, 
+	0x36, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x73, 
+	0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 
+	0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 
+	0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 
+	0x50, 0x00, 0x08, 0x00, 0x18, 0x00, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0x00, 0x01, 0xff, 0x7f, 0x00, 0x00, 
+	0x04, 0x00, 0x06, 0x00, 0x08, 0x00, 0x19, 0x00, 
+	0x1e, 0x00, 0x26, 0x00, 0x2a, 0x00, 0x2e, 0x00, 
+	0xff, 0xff, 0x39, 0x00, 0x4a, 0x00, 0x4c, 0x00, 
+	0x50, 0x00, 0x57, 0x00, 0xff, 0xff, 0x59, 0x00, 
+	0x66, 0x00, 0xff, 0xff, 0x6a, 0x00, 0x6e, 0x00, 
+	0x78, 0x00, 0x7c, 0x00, 0xff, 0xff, 0xff, 0xff, 
+	0x80, 0x00, 0x84, 0x00, 0x89, 0x00, 0x8e, 0x00, 
+	0xff, 0xff, 0xa0, 0x00, 0xa5, 0x00, 0xaa, 0x00, 
+	0xff, 0xff, 0xaf, 0x00, 0xb4, 0x00, 0xb9, 0x00, 
+	0xbe, 0x00, 0xc7, 0x00, 0xcb, 0x00, 0xd2, 0x00, 
+	0xff, 0xff, 0xe4, 0x00, 0xe9, 0x00, 0xef, 0x00, 
+	0xf5, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0x07, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0x19, 0x01, 0xff, 0xff, 0x1d, 0x01, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0x1f, 0x01, 0xff, 0xff, 
+	0x24, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0x28, 0x01, 0x2c, 0x01, 0x32, 0x01, 
+	0x36, 0x01, 0x3a, 0x01, 0x3e, 0x01, 0x44, 0x01, 
+	0x4a, 0x01, 0x50, 0x01, 0x56, 0x01, 0x5c, 0x01, 
+	0x60, 0x01, 0xff, 0xff, 0x65, 0x01, 0xff, 0xff, 
+	0x69, 0x01, 0x6e, 0x01, 0x73, 0x01, 0x77, 0x01, 
+	0x7e, 0x01, 0xff, 0xff, 0x85, 0x01, 0x89, 0x01, 
+	0x91, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0x99, 0x01, 0xa2, 0x01, 0xff, 0xff, 0xff, 0xff, 
+	0xab, 0x01, 0xb4, 0x01, 0xbd, 0x01, 0xc6, 0x01, 
+	0xcf, 0x01, 0xd8, 0x01, 0xe1, 0x01, 0xea, 0x01, 
+	0xf3, 0x01, 0xfc, 0x01, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0x05, 0x02, 0x09, 0x02, 0x0e, 0x02, 
+	0x13, 0x02, 0x27, 0x02, 0x30, 0x02, 0xff, 0xff, 
+	0xff, 0xff, 0x42, 0x02, 0x45, 0x02, 0x50, 0x02, 
+	0x53, 0x02, 0x55, 0x02, 0x58, 0x02, 0xb5, 0x02, 
+	0xff, 0xff, 0xb8, 0x02, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xba, 0x02, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xbe, 0x02, 0xff, 0xff, 0xf3, 0x02, 
+	0xff, 0xff, 0xff, 0xff, 0xf7, 0x02, 0xfd, 0x02, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x03, 
+	0x07, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0x0b, 0x03, 0xff, 0xff, 
+	0xff, 0xff, 0x12, 0x03, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0x19, 0x03, 0x20, 0x03, 
+	0x27, 0x03, 0xff, 0xff, 0xff, 0xff, 0x2e, 0x03, 
+	0xff, 0xff, 0x35, 0x03, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0x3c, 0x03, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x43, 0x03, 
+	0x49, 0x03, 0x4f, 0x03, 0x56, 0x03, 0x5d, 0x03, 
+	0x64, 0x03, 0x6b, 0x03, 0x73, 0x03, 0x7b, 0x03, 
+	0x83, 0x03, 0x8b, 0x03, 0x93, 0x03, 0x9b, 0x03, 
+	0xa3, 0x03, 0xab, 0x03, 0xb2, 0x03, 0xb9, 0x03, 
+	0xc0, 0x03, 0xc7, 0x03, 0xcf, 0x03, 0xd7, 0x03, 
+	0xdf, 0x03, 0xe7, 0x03, 0xef, 0x03, 0xf7, 0x03, 
+	0xff, 0x03, 0x07, 0x04, 0x0e, 0x04, 0x15, 0x04, 
+	0x1c, 0x04, 0x23, 0x04, 0x2b, 0x04, 0x33, 0x04, 
+	0x3b, 0x04, 0x43, 0x04, 0x4b, 0x04, 0x53, 0x04, 
+	0x5b, 0x04, 0x63, 0x04, 0x6a, 0x04, 0x71, 0x04, 
+	0x78, 0x04, 0x7f, 0x04, 0x87, 0x04, 0x8f, 0x04, 
+	0x97, 0x04, 0x9f, 0x04, 0xa7, 0x04, 0xaf, 0x04, 
+	0xb7, 0x04, 0xbf, 0x04, 0xc6, 0x04, 0xcd, 0x04, 
+	0xd4, 0x04, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xd9, 0x04, 0xe4, 0x04, 0xe9, 0x04, 0xfc, 0x04, 
+	0x00, 0x05, 0x09, 0x05, 0x10, 0x05, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0x6e, 0x05, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0x73, 0x05, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0x79, 0x05, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0x7d, 0x05, 0xbc, 0x05, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xff, 0xff, 0xfc, 0x05, 0xff, 0x05, 
+	0x1b, 0x5b, 0x5a, 0x00, 0x07, 0x00, 0x0d, 0x00, 
+	0x1b, 0x5b, 0x25, 0x69, 0x25, 0x70, 0x31, 0x25, 
+	0x64, 0x3b, 0x25, 0x70, 0x32, 0x25, 0x64, 0x72, 
+	0x00, 0x1b, 0x5b, 0x33, 0x67, 0x00, 0x1b, 0x5b, 
+	0x48, 0x1b, 0x5b, 0x32, 0x4a, 0x00, 0x1b, 0x5b, 
+	0x4b, 0x00, 0x1b, 0x5b, 0x4a, 0x00, 0x1b, 0x5b, 
+	0x25, 0x69, 0x25, 0x70, 0x31, 0x25, 0x64, 0x47, 
+	0x00, 0x1b, 0x5b, 0x25, 0x69, 0x25, 0x70, 0x31, 
+	0x25, 0x64, 0x3b, 0x25, 0x70, 0x32, 0x25, 0x64, 
+	0x48, 0x00, 0x0a, 0x00, 0x1b, 0x5b, 0x48, 0x00, 
+	0x1b, 0x5b, 0x3f, 0x32, 0x35, 0x6c, 0x00, 0x08, 
+	0x00, 0x1b, 0x5b, 0x3f, 0x31, 0x32, 0x6c, 0x1b, 
+	0x5b, 0x3f, 0x32, 0x35, 0x68, 0x00, 0x1b, 0x5b, 
+	0x43, 0x00, 0x1b, 0x5b, 0x41, 0x00, 0x1b, 0x5b, 
+	0x3f, 0x31, 0x32, 0x3b, 0x32, 0x35, 0x68, 0x00, 
+	0x1b, 0x5b, 0x50, 0x00, 0x1b, 0x5b, 0x4d, 0x00, 
+	0x1b, 0x28, 0x30, 0x00, 0x1b, 0x5b, 0x35, 0x6d, 
+	0x00, 0x1b, 0x5b, 0x31, 0x6d, 0x00, 0x1b, 0x5b, 
+	0x3f, 0x31, 0x30, 0x34, 0x39, 0x68, 0x1b, 0x5b, 
+	0x32, 0x32, 0x3b, 0x30, 0x3b, 0x30, 0x74, 0x00, 
+	0x1b, 0x5b, 0x32, 0x6d, 0x00, 0x1b, 0x5b, 0x34, 
+	0x68, 0x00, 0x1b, 0x5b, 0x38, 0x6d, 0x00, 0x1b, 
+	0x5b, 0x37, 0x6d, 0x00, 0x1b, 0x5b, 0x37, 0x6d, 
+	0x00, 0x1b, 0x5b, 0x34, 0x6d, 0x00, 0x1b, 0x5b, 
+	0x25, 0x70, 0x31, 0x25, 0x64, 0x58, 0x00, 0x1b, 
+	0x28, 0x42, 0x00, 0x1b, 0x28, 0x42, 0x1b, 0x5b, 
+	0x6d, 0x00, 0x1b, 0x5b, 0x3f, 0x31, 0x30, 0x34, 
+	0x39, 0x6c, 0x1b, 0x5b, 0x32, 0x33, 0x3b, 0x30, 
+	0x3b, 0x30, 0x74, 0x00, 0x1b, 0x5b, 0x34, 0x6c, 
+	0x00, 0x1b, 0x5b, 0x32, 0x37, 0x6d, 0x00, 0x1b, 
+	0x5b, 0x32, 0x34, 0x6d, 0x00, 0x1b, 0x5b, 0x3f, 
+	0x35, 0x68, 0x24, 0x3c, 0x31, 0x30, 0x30, 0x2f, 
+	0x3e, 0x1b, 0x5b, 0x3f, 0x35, 0x6c, 0x00, 0x1b, 
+	0x5b, 0x21, 0x70, 0x1b, 0x5b, 0x3f, 0x33, 0x3b, 
+	0x34, 0x6c, 0x1b, 0x5b, 0x34, 0x6c, 0x1b, 0x3e, 
+	0x00, 0x1b, 0x5b, 0x4c, 0x00, 0x7f, 0x00, 0x1b, 
+	0x5b, 0x33, 0x7e, 0x00, 0x1b, 0x4f, 0x42, 0x00, 
+	0x1b, 0x4f, 0x50, 0x00, 0x1b, 0x5b, 0x32, 0x31, 
+	0x7e, 0x00, 0x1b, 0x4f, 0x51, 0x00, 0x1b, 0x4f, 
+	0x52, 0x00, 0x1b, 0x4f, 0x53, 0x00, 0x1b, 0x5b, 
+	0x31, 0x35, 0x7e, 0x00, 0x1b, 0x5b, 0x31, 0x37, 
+	0x7e, 0x00, 0x1b, 0x5b, 0x31, 0x38, 0x7e, 0x00, 
+	0x1b, 0x5b, 0x31, 0x39, 0x7e, 0x00, 0x1b, 0x5b, 
+	0x32, 0x30, 0x7e, 0x00, 0x1b, 0x4f, 0x48, 0x00, 
+	0x1b, 0x5b, 0x32, 0x7e, 0x00, 0x1b, 0x4f, 0x44, 
+	0x00, 0x1b, 0x5b, 0x36, 0x7e, 0x00, 0x1b, 0x5b, 
+	0x35, 0x7e, 0x00, 0x1b, 0x4f, 0x43, 0x00, 0x1b, 
+	0x5b, 0x31, 0x3b, 0x32, 0x42, 0x00, 0x1b, 0x5b, 
+	0x31, 0x3b, 0x32, 0x41, 0x00, 0x1b, 0x4f, 0x41, 
+	0x00, 0x1b, 0x5b, 0x3f, 0x31, 0x6c, 0x1b, 0x3e, 
+	0x00, 0x1b, 0x5b, 0x3f, 0x31, 0x68, 0x1b, 0x3d, 
+	0x00, 0x1b, 0x5b, 0x3f, 0x31, 0x30, 0x33, 0x34, 
+	0x6c, 0x00, 0x1b, 0x5b, 0x3f, 0x31, 0x30, 0x33, 
+	0x34, 0x68, 0x00, 0x1b, 0x5b, 0x25, 0x70, 0x31, 
+	0x25, 0x64, 0x50, 0x00, 0x1b, 0x5b, 0x25, 0x70, 
+	0x31, 0x25, 0x64, 0x4d, 0x00, 0x1b, 0x5b, 0x25, 
+	0x70, 0x31, 0x25, 0x64, 0x42, 0x00, 0x1b, 0x5b, 
+	0x25, 0x70, 0x31, 0x25, 0x64, 0x40, 0x00, 0x1b, 
+	0x5b, 0x25, 0x70, 0x31, 0x25, 0x64, 0x53, 0x00, 
+	0x1b, 0x5b, 0x25, 0x70, 0x31, 0x25, 0x64, 0x4c, 
+	0x00, 0x1b, 0x5b, 0x25, 0x70, 0x31, 0x25, 0x64, 
+	0x44, 0x00, 0x1b, 0x5b, 0x25, 0x70, 0x31, 0x25, 
+	0x64, 0x43, 0x00, 0x1b, 0x5b, 0x25, 0x70, 0x31, 
+	0x25, 0x64, 0x54, 0x00, 0x1b, 0x5b, 0x25, 0x70, 
+	0x31, 0x25, 0x64, 0x41, 0x00, 0x1b, 0x5b, 0x69, 
+	0x00, 0x1b, 0x5b, 0x34, 0x69, 0x00, 0x1b, 0x5b, 
+	0x35, 0x69, 0x00, 0x25, 0x70, 0x31, 0x25, 0x63, 
+	0x1b, 0x5b, 0x25, 0x70, 0x32, 0x25, 0x7b, 0x31, 
+	0x7d, 0x25, 0x2d, 0x25, 0x64, 0x62, 0x00, 0x1b, 
+	0x63, 0x1b, 0x5d, 0x31, 0x30, 0x34, 0x07, 0x00, 
+	0x1b, 0x5b, 0x21, 0x70, 0x1b, 0x5b, 0x3f, 0x33, 
+	0x3b, 0x34, 0x6c, 0x1b, 0x5b, 0x34, 0x6c, 0x1b, 
+	0x3e, 0x00, 0x1b, 0x38, 0x00, 0x1b, 0x5b, 0x25, 
+	0x69, 0x25, 0x70, 0x31, 0x25, 0x64, 0x64, 0x00, 
+	0x1b, 0x37, 0x00, 0x0a, 0x00, 0x1b, 0x4d, 0x00, 
+	0x25, 0x3f, 0x25, 0x70, 0x39, 0x25, 0x74, 0x1b, 
+	0x28, 0x30, 0x25, 0x65, 0x1b, 0x28, 0x42, 0x25, 
+	0x3b, 0x1b, 0x5b, 0x30, 0x25, 0x3f, 0x25, 0x70, 
+	0x36, 0x25, 0x74, 0x3b, 0x31, 0x25, 0x3b, 0x25, 
+	0x3f, 0x25, 0x70, 0x35, 0x25, 0x74, 0x3b, 0x32, 
+	0x25, 0x3b, 0x25, 0x3f, 0x25, 0x70, 0x32, 0x25, 
+	0x74, 0x3b, 0x34, 0x25, 0x3b, 0x25, 0x3f, 0x25, 
+	0x70, 0x31, 0x25, 0x70, 0x33, 0x25, 0x7c, 0x25, 
+	0x74, 0x3b, 0x37, 0x25, 0x3b, 0x25, 0x3f, 0x25, 
+	0x70, 0x34, 0x25, 0x74, 0x3b, 0x35, 0x25, 0x3b, 
+	0x25, 0x3f, 0x25, 0x70, 0x37, 0x25, 0x74, 0x3b, 
+	0x38, 0x25, 0x3b, 0x6d, 0x00, 0x1b, 0x48, 0x00, 
+	0x09, 0x00, 0x1b, 0x4f, 0x45, 0x00, 0x60, 0x60, 
+	0x61, 0x61, 0x66, 0x66, 0x67, 0x67, 0x69, 0x69, 
+	0x6a, 0x6a, 0x6b, 0x6b, 0x6c, 0x6c, 0x6d, 0x6d, 
+	0x6e, 0x6e, 0x6f, 0x6f, 0x70, 0x70, 0x71, 0x71, 
+	0x72, 0x72, 0x73, 0x73, 0x74, 0x74, 0x75, 0x75, 
+	0x76, 0x76, 0x77, 0x77, 0x78, 0x78, 0x79, 0x79, 
+	0x7a, 0x7a, 0x7b, 0x7b, 0x7c, 0x7c, 0x7d, 0x7d, 
+	0x7e, 0x7e, 0x00, 0x1b, 0x5b, 0x5a, 0x00, 0x1b, 
+	0x5b, 0x3f, 0x37, 0x68, 0x00, 0x1b, 0x5b, 0x3f, 
+	0x37, 0x6c, 0x00, 0x1b, 0x4f, 0x46, 0x00, 0x1b, 
+	0x4f, 0x4d, 0x00, 0x1b, 0x5b, 0x33, 0x3b, 0x32, 
+	0x7e, 0x00, 0x1b, 0x5b, 0x31, 0x3b, 0x32, 0x46, 
+	0x00, 0x1b, 0x5b, 0x31, 0x3b, 0x32, 0x48, 0x00, 
+	0x1b, 0x5b, 0x32, 0x3b, 0x32, 0x7e, 0x00, 0x1b, 
+	0x5b, 0x31, 0x3b, 0x32, 0x44, 0x00, 0x1b, 0x5b, 
+	0x36, 0x3b, 0x32, 0x7e, 0x00, 0x1b, 0x5b, 0x35, 
+	0x3b, 0x32, 0x7e, 0x00, 0x1b, 0x5b, 0x31, 0x3b, 
+	0x32, 0x43, 0x00, 0x1b, 0x5b, 0x32, 0x33, 0x7e, 
+	0x00, 0x1b, 0x5b, 0x32, 0x34, 0x7e, 0x00, 0x1b, 
+	0x5b, 0x31, 0x3b, 0x32, 0x50, 0x00, 0x1b, 0x5b, 
+	0x31, 0x3b, 0x32, 0x51, 0x00, 0x1b, 0x5b, 0x31, 
+	0x3b, 0x32, 0x52, 0x00, 0x1b, 0x5b, 0x31, 0x3b, 
+	0x32, 0x53, 0x00, 0x1b, 0x5b, 0x31, 0x35, 0x3b, 
+	0x32, 0x7e, 0x00, 0x1b, 0x5b, 0x31, 0x37, 0x3b, 
+	0x32, 0x7e, 0x00, 0x1b, 0x5b, 0x31, 0x38, 0x3b, 
+	0x32, 0x7e, 0x00, 0x1b, 0x5b, 0x31, 0x39, 0x3b, 
+	0x32, 0x7e, 0x00, 0x1b, 0x5b, 0x32, 0x30, 0x3b, 
+	0x32, 0x7e, 0x00, 0x1b, 0x5b, 0x32, 0x31, 0x3b, 
+	0x32, 0x7e, 0x00, 0x1b, 0x5b, 0x32, 0x33, 0x3b, 
+	0x32, 0x7e, 0x00, 0x1b, 0x5b, 0x32, 0x34, 0x3b, 
+	0x32, 0x7e, 0x00, 0x1b, 0x5b, 0x31, 0x3b, 0x35, 
+	0x50, 0x00, 0x1b, 0x5b, 0x31, 0x3b, 0x35, 0x51, 
+	0x00, 0x1b, 0x5b, 0x31, 0x3b, 0x35, 0x52, 0x00, 
+	0x1b, 0x5b, 0x31, 0x3b, 0x35, 0x53, 0x00, 0x1b, 
+	0x5b, 0x31, 0x35, 0x3b, 0x35, 0x7e, 0x00, 0x1b, 
+	0x5b, 0x31, 0x37, 0x3b, 0x35, 0x7e, 0x00, 0x1b, 
+	0x5b, 0x31, 0x38, 0x3b, 0x35, 0x7e, 0x00, 0x1b, 
+	0x5b, 0x31, 0x39, 0x3b, 0x35, 0x7e, 0x00, 0x1b, 
+	0x5b, 0x32, 0x30, 0x3b, 0x35, 0x7e, 0x00, 0x1b, 
+	0x5b, 0x32, 0x31, 0x3b, 0x35, 0x7e, 0x00, 0x1b, 
+	0x5b, 0x32, 0x33, 0x3b, 0x35, 0x7e, 0x00, 0x1b, 
+	0x5b, 0x32, 0x34, 0x3b, 0x35, 0x7e, 0x00, 0x1b, 
+	0x5b, 0x31, 0x3b, 0x36, 0x50, 0x00, 0x1b, 0x5b, 
+	0x31, 0x3b, 0x36, 0x51, 0x00, 0x1b, 0x5b, 0x31, 
+	0x3b, 0x36, 0x52, 0x00, 0x1b, 0x5b, 0x31, 0x3b, 
+	0x36, 0x53, 0x00, 0x1b, 0x5b, 0x31, 0x35, 0x3b, 
+	0x36, 0x7e, 0x00, 0x1b, 0x5b, 0x31, 0x37, 0x3b, 
+	0x36, 0x7e, 0x00, 0x1b, 0x5b, 0x31, 0x38, 0x3b, 
+	0x36, 0x7e, 0x00, 0x1b, 0x5b, 0x31, 0x39, 0x3b, 
+	0x36, 0x7e, 0x00, 0x1b, 0x5b, 0x32, 0x30, 0x3b, 
+	0x36, 0x7e, 0x00, 0x1b, 0x5b, 0x32, 0x31, 0x3b, 
+	0x36, 0x7e, 0x00, 0x1b, 0x5b, 0x32, 0x33, 0x3b, 
+	0x36, 0x7e, 0x00, 0x1b, 0x5b, 0x32, 0x34, 0x3b, 
+	0x36, 0x7e, 0x00, 0x1b, 0x5b, 0x31, 0x3b, 0x33, 
+	0x50, 0x00, 0x1b, 0x5b, 0x31, 0x3b, 0x33, 0x51, 
+	0x00, 0x1b, 0x5b, 0x31, 0x3b, 0x33, 0x52, 0x00, 
+	0x1b, 0x5b, 0x31, 0x3b, 0x33, 0x53, 0x00, 0x1b, 
+	0x5b, 0x31, 0x35, 0x3b, 0x33, 0x7e, 0x00, 0x1b, 
+	0x5b, 0x31, 0x37, 0x3b, 0x33, 0x7e, 0x00, 0x1b, 
+	0x5b, 0x31, 0x38, 0x3b, 0x33, 0x7e, 0x00, 0x1b, 
+	0x5b, 0x31, 0x39, 0x3b, 0x33, 0x7e, 0x00, 0x1b, 
+	0x5b, 0x32, 0x30, 0x3b, 0x33, 0x7e, 0x00, 0x1b, 
+	0x5b, 0x32, 0x31, 0x3b, 0x33, 0x7e, 0x00, 0x1b, 
+	0x5b, 0x32, 0x33, 0x3b, 0x33, 0x7e, 0x00, 0x1b, 
+	0x5b, 0x32, 0x34, 0x3b, 0x33, 0x7e, 0x00, 0x1b, 
+	0x5b, 0x31, 0x3b, 0x34, 0x50, 0x00, 0x1b, 0x5b, 
+	0x31, 0x3b, 0x34, 0x51, 0x00, 0x1b, 0x5b, 0x31, 
+	0x3b, 0x34, 0x52, 0x00, 0x1b, 0x5b, 0x31, 0x4b, 
+	0x00, 0x1b, 0x5b, 0x25, 0x69, 0x25, 0x64, 0x3b, 
+	0x25, 0x64, 0x52, 0x00, 0x1b, 0x5b, 0x36, 0x6e, 
+	0x00, 0x1b, 0x5b, 0x3f, 0x25, 0x5b, 0x3b, 0x30, 
+	0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 
+	0x39, 0x5d, 0x63, 0x00, 0x1b, 0x5b, 0x63, 0x00, 
+	0x1b, 0x5b, 0x33, 0x39, 0x3b, 0x34, 0x39, 0x6d, 
+	0x00, 0x1b, 0x5d, 0x31, 0x30, 0x34, 0x07, 0x00, 
+	0x1b, 0x5d, 0x34, 0x3b, 0x25, 0x70, 0x31, 0x25, 
+	0x64, 0x3b, 0x72, 0x67, 0x62, 0x3a, 0x25, 0x70, 
+	0x32, 0x25, 0x7b, 0x32, 0x35, 0x35, 0x7d, 0x25, 
+	0x2a, 0x25, 0x7b, 0x31, 0x30, 0x30, 0x30, 0x7d, 
+	0x25, 0x2f, 0x25, 0x32, 0x2e, 0x32, 0x58, 0x2f, 
+	0x25, 0x70, 0x33, 0x25, 0x7b, 0x32, 0x35, 0x35, 
+	0x7d, 0x25, 0x2a, 0x25, 0x7b, 0x31, 0x30, 0x30, 
+	0x30, 0x7d, 0x25, 0x2f, 0x25, 0x32, 0x2e, 0x32, 
+	0x58, 0x2f, 0x25, 0x70, 0x34, 0x25, 0x7b, 0x32, 
+	0x35, 0x35, 0x7d, 0x25, 0x2a, 0x25, 0x7b, 0x31, 
+	0x30, 0x30, 0x30, 0x7d, 0x25, 0x2f, 0x25, 0x32, 
+	0x2e, 0x32, 0x58, 0x1b, 0x5c, 0x00, 0x1b, 0x5b, 
+	0x33, 0x6d, 0x00, 0x1b, 0x5b, 0x32, 0x33, 0x6d, 
+	0x00, 0x1b, 0x5b, 0x4d, 0x00, 0x1b, 0x5b, 0x25, 
+	0x3f, 0x25, 0x70, 0x31, 0x25, 0x7b, 0x38, 0x7d, 
+	0x25, 0x3c, 0x25, 0x74, 0x33, 0x25, 0x70, 0x31, 
+	0x25, 0x64, 0x25, 0x65, 0x25, 0x70, 0x31, 0x25, 
+	0x7b, 0x31, 0x36, 0x7d, 0x25, 0x3c, 0x25, 0x74, 
+	0x39, 0x25, 0x70, 0x31, 0x25, 0x7b, 0x38, 0x7d, 
+	0x25, 0x2d, 0x25, 0x64, 0x25, 0x65, 0x33, 0x38, 
+	0x3b, 0x35, 0x3b, 0x25, 0x70, 0x31, 0x25, 0x64, 
+	0x25, 0x3b, 0x6d, 0x00, 0x1b, 0x5b, 0x25, 0x3f, 
+	0x25, 0x70, 0x31, 0x25, 0x7b, 0x38, 0x7d, 0x25, 
+	0x3c, 0x25, 0x74, 0x34, 0x25, 0x70, 0x31, 0x25, 
+	0x64, 0x25, 0x65, 0x25, 0x70, 0x31, 0x25, 0x7b, 
+	0x31, 0x36, 0x7d, 0x25, 0x3c, 0x25, 0x74, 0x31, 
+	0x30, 0x25, 0x70, 0x31, 0x25, 0x7b, 0x38, 0x7d, 
+	0x25, 0x2d, 0x25, 0x64, 0x25, 0x65, 0x34, 0x38, 
+	0x3b, 0x35, 0x3b, 0x25, 0x70, 0x31, 0x25, 0x64, 
+	0x25, 0x3b, 0x6d, 0x00, 0x1b, 0x6c, 0x00, 0x1b, 
+	0x6d, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, 0x00, 
+	0x82, 0x00, 0x03, 0x03, 0x01, 0x01, 0x00, 0x00, 
+	0x07, 0x00, 0x13, 0x00, 0x18, 0x00, 0x2a, 0x00, 
+	0x30, 0x00, 0x3a, 0x00, 0x41, 0x00, 0x48, 0x00, 
+	0x4f, 0x00, 0x56, 0x00, 0x5d, 0x00, 0x64, 0x00, 
+	0x6b, 0x00, 0x72, 0x00, 0x79, 0x00, 0x80, 0x00, 
+	0x87, 0x00, 0x8e, 0x00, 0x95, 0x00, 0x9c, 0x00, 
+	0xa3, 0x00, 0xaa, 0x00, 0xb1, 0x00, 0xb8, 0x00, 
+	0xbf, 0x00, 0xc6, 0x00, 0xcd, 0x00, 0xd4, 0x00, 
+	0xdb, 0x00, 0xe2, 0x00, 0xe9, 0x00, 0xf0, 0x00, 
+	0xf7, 0x00, 0xfe, 0x00, 0x05, 0x01, 0x0c, 0x01, 
+	0x13, 0x01, 0x1a, 0x01, 0x21, 0x01, 0x28, 0x01, 
+	0x2f, 0x01, 0x36, 0x01, 0x3d, 0x01, 0x44, 0x01, 
+	0x4b, 0x01, 0x52, 0x01, 0x59, 0x01, 0x60, 0x01, 
+	0x67, 0x01, 0x6e, 0x01, 0x75, 0x01, 0x7c, 0x01, 
+	0x83, 0x01, 0x8a, 0x01, 0x91, 0x01, 0x98, 0x01, 
+	0x9f, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 
+	0xff, 0xff, 0xa6, 0x01, 0xac, 0x01, 0x00, 0x00, 
+	0x03, 0x00, 0x06, 0x00, 0x09, 0x00, 0x0c, 0x00, 
+	0x0f, 0x00, 0x12, 0x00, 0x15, 0x00, 0x18, 0x00, 
+	0x1d, 0x00, 0x22, 0x00, 0x27, 0x00, 0x2c, 0x00, 
+	0x31, 0x00, 0x35, 0x00, 0x3a, 0x00, 0x3f, 0x00, 
+	0x44, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x54, 0x00, 
+	0x5a, 0x00, 0x60, 0x00, 0x66, 0x00, 0x6c, 0x00, 
+	0x72, 0x00, 0x78, 0x00, 0x7e, 0x00, 0x84, 0x00, 
+	0x8a, 0x00, 0x8f, 0x00, 0x94, 0x00, 0x99, 0x00, 
+	0x9e, 0x00, 0xa3, 0x00, 0xa9, 0x00, 0xaf, 0x00, 
+	0xb5, 0x00, 0xbb, 0x00, 0xc1, 0x00, 0xc7, 0x00, 
+	0xcd, 0x00, 0xd3, 0x00, 0xd9, 0x00, 0xdf, 0x00, 
+	0xe5, 0x00, 0xeb, 0x00, 0xf1, 0x00, 0xf7, 0x00, 
+	0xfd, 0x00, 0x03, 0x01, 0x09, 0x01, 0x0f, 0x01, 
+	0x15, 0x01, 0x1b, 0x01, 0x1f, 0x01, 0x24, 0x01, 
+	0x29, 0x01, 0x2e, 0x01, 0x33, 0x01, 0x38, 0x01, 
+	0x3c, 0x01, 0x40, 0x01, 0x44, 0x01, 0x48, 0x01, 
+	0x4d, 0x01, 0x1b, 0x5d, 0x31, 0x31, 0x32, 0x07, 
+	0x00, 0x1b, 0x5d, 0x31, 0x32, 0x3b, 0x25, 0x70, 
+	0x31, 0x25, 0x73, 0x07, 0x00, 0x1b, 0x5b, 0x33, 
+	0x4a, 0x00, 0x1b, 0x5d, 0x35, 0x32, 0x3b, 0x25, 
+	0x70, 0x31, 0x25, 0x73, 0x3b, 0x25, 0x70, 0x32, 
+	0x25, 0x73, 0x07, 0x00, 0x1b, 0x5b, 0x32, 0x20, 
+	0x71, 0x00, 0x1b, 0x5b, 0x25, 0x70, 0x31, 0x25, 
+	0x64, 0x20, 0x71, 0x00, 0x1b, 0x5b, 0x33, 0x3b, 
+	0x33, 0x7e, 0x00, 0x1b, 0x5b, 0x33, 0x3b, 0x34, 
+	0x7e, 0x00, 0x1b, 0x5b, 0x33, 0x3b, 0x35, 0x7e, 
+	0x00, 0x1b, 0x5b, 0x33, 0x3b, 0x36, 0x7e, 0x00, 
+	0x1b, 0x5b, 0x33, 0x3b, 0x37, 0x7e, 0x00, 0x1b, 
+	0x5b, 0x31, 0x3b, 0x32, 0x42, 0x00, 0x1b, 0x5b, 
+	0x31, 0x3b, 0x33, 0x42, 0x00, 0x1b, 0x5b, 0x31, 
+	0x3b, 0x34, 0x42, 0x00, 0x1b, 0x5b, 0x31, 0x3b, 
+	0x35, 0x42, 0x00, 0x1b, 0x5b, 0x31, 0x3b, 0x36, 
+	0x42, 0x00, 0x1b, 0x5b, 0x31, 0x3b, 0x37, 0x42, 
+	0x00, 0x1b, 0x5b, 0x31, 0x3b, 0x33, 0x46, 0x00, 
+	0x1b, 0x5b, 0x31, 0x3b, 0x34, 0x46, 0x00, 0x1b, 
+	0x5b, 0x31, 0x3b, 0x35, 0x46, 0x00, 0x1b, 0x5b, 
+	0x31, 0x3b, 0x36, 0x46, 0x00, 0x1b, 0x5b, 0x31, 
+	0x3b, 0x37, 0x46, 0x00, 0x1b, 0x5b, 0x31, 0x3b, 
+	0x33, 0x48, 0x00, 0x1b, 0x5b, 0x31, 0x3b, 0x34, 
+	0x48, 0x00, 0x1b, 0x5b, 0x31, 0x3b, 0x35, 0x48, 
+	0x00, 0x1b, 0x5b, 0x31, 0x3b, 0x36, 0x48, 0x00, 
+	0x1b, 0x5b, 0x31, 0x3b, 0x37, 0x48, 0x00, 0x1b, 
+	0x5b, 0x32, 0x3b, 0x33, 0x7e, 0x00, 0x1b, 0x5b, 
+	0x32, 0x3b, 0x34, 0x7e, 0x00, 0x1b, 0x5b, 0x32, 
+	0x3b, 0x35, 0x7e, 0x00, 0x1b, 0x5b, 0x32, 0x3b, 
+	0x36, 0x7e, 0x00, 0x1b, 0x5b, 0x32, 0x3b, 0x37, 
+	0x7e, 0x00, 0x1b, 0x5b, 0x31, 0x3b, 0x33, 0x44, 
+	0x00, 0x1b, 0x5b, 0x31, 0x3b, 0x34, 0x44, 0x00, 
+	0x1b, 0x5b, 0x31, 0x3b, 0x35, 0x44, 0x00, 0x1b, 
+	0x5b, 0x31, 0x3b, 0x36, 0x44, 0x00, 0x1b, 0x5b, 
+	0x31, 0x3b, 0x37, 0x44, 0x00, 0x1b, 0x5b, 0x36, 
+	0x3b, 0x33, 0x7e, 0x00, 0x1b, 0x5b, 0x36, 0x3b, 
+	0x34, 0x7e, 0x00, 0x1b, 0x5b, 0x36, 0x3b, 0x35, 
+	0x7e, 0x00, 0x1b, 0x5b, 0x36, 0x3b, 0x36, 0x7e, 
+	0x00, 0x1b, 0x5b, 0x36, 0x3b, 0x37, 0x7e, 0x00, 
+	0x1b, 0x5b, 0x35, 0x3b, 0x33, 0x7e, 0x00, 0x1b, 
+	0x5b, 0x35, 0x3b, 0x34, 0x7e, 0x00, 0x1b, 0x5b, 
+	0x35, 0x3b, 0x35, 0x7e, 0x00, 0x1b, 0x5b, 0x35, 
+	0x3b, 0x36, 0x7e, 0x00, 0x1b, 0x5b, 0x35, 0x3b, 
+	0x37, 0x7e, 0x00, 0x1b, 0x5b, 0x31, 0x3b, 0x33, 
+	0x43, 0x00, 0x1b, 0x5b, 0x31, 0x3b, 0x34, 0x43, 
+	0x00, 0x1b, 0x5b, 0x31, 0x3b, 0x35, 0x43, 0x00, 
+	0x1b, 0x5b, 0x31, 0x3b, 0x36, 0x43, 0x00, 0x1b, 
+	0x5b, 0x31, 0x3b, 0x37, 0x43, 0x00, 0x1b, 0x5b, 
+	0x31, 0x3b, 0x32, 0x41, 0x00, 0x1b, 0x5b, 0x31, 
+	0x3b, 0x33, 0x41, 0x00, 0x1b, 0x5b, 0x31, 0x3b, 
+	0x34, 0x41, 0x00, 0x1b, 0x5b, 0x31, 0x3b, 0x35, 
+	0x41, 0x00, 0x1b, 0x5b, 0x31, 0x3b, 0x36, 0x41, 
+	0x00, 0x1b, 0x5b, 0x31, 0x3b, 0x37, 0x41, 0x00, 
+	0x1b, 0x5b, 0x32, 0x39, 0x6d, 0x00, 0x1b, 0x5b, 
+	0x39, 0x6d, 0x00, 0x41, 0x58, 0x00, 0x58, 0x54, 
+	0x00, 0x43, 0x72, 0x00, 0x43, 0x73, 0x00, 0x45, 
+	0x33, 0x00, 0x4d, 0x73, 0x00, 0x53, 0x65, 0x00, 
+	0x53, 0x73, 0x00, 0x6b, 0x44, 0x43, 0x33, 0x00, 
+	0x6b, 0x44, 0x43, 0x34, 0x00, 0x6b, 0x44, 0x43, 
+	0x35, 0x00, 0x6b, 0x44, 0x43, 0x36, 0x00, 0x6b, 
+	0x44, 0x43, 0x37, 0x00, 0x6b, 0x44, 0x4e, 0x00, 
+	0x6b, 0x44, 0x4e, 0x33, 0x00, 0x6b, 0x44, 0x4e, 
+	0x34, 0x00, 0x6b, 0x44, 0x4e, 0x35, 0x00, 0x6b, 
+	0x44, 0x4e, 0x36, 0x00, 0x6b, 0x44, 0x4e, 0x37, 
+	0x00, 0x6b, 0x45, 0x4e, 0x44, 0x33, 0x00, 0x6b, 
+	0x45, 0x4e, 0x44, 0x34, 0x00, 0x6b, 0x45, 0x4e, 
+	0x44, 0x35, 0x00, 0x6b, 0x45, 0x4e, 0x44, 0x36, 
+	0x00, 0x6b, 0x45, 0x4e, 0x44, 0x37, 0x00, 0x6b, 
+	0x48, 0x4f, 0x4d, 0x33, 0x00, 0x6b, 0x48, 0x4f, 
+	0x4d, 0x34, 0x00, 0x6b, 0x48, 0x4f, 0x4d, 0x35, 
+	0x00, 0x6b, 0x48, 0x4f, 0x4d, 0x36, 0x00, 0x6b, 
+	0x48, 0x4f, 0x4d, 0x37, 0x00, 0x6b, 0x49, 0x43, 
+	0x33, 0x00, 0x6b, 0x49, 0x43, 0x34, 0x00, 0x6b, 
+	0x49, 0x43, 0x35, 0x00, 0x6b, 0x49, 0x43, 0x36, 
+	0x00, 0x6b, 0x49, 0x43, 0x37, 0x00, 0x6b, 0x4c, 
+	0x46, 0x54, 0x33, 0x00, 0x6b, 0x4c, 0x46, 0x54, 
+	0x34, 0x00, 0x6b, 0x4c, 0x46, 0x54, 0x35, 0x00, 
+	0x6b, 0x4c, 0x46, 0x54, 0x36, 0x00, 0x6b, 0x4c, 
+	0x46, 0x54, 0x37, 0x00, 0x6b, 0x4e, 0x58, 0x54, 
+	0x33, 0x00, 0x6b, 0x4e, 0x58, 0x54, 0x34, 0x00, 
+	0x6b, 0x4e, 0x58, 0x54, 0x35, 0x00, 0x6b, 0x4e, 
+	0x58, 0x54, 0x36, 0x00, 0x6b, 0x4e, 0x58, 0x54, 
+	0x37, 0x00, 0x6b, 0x50, 0x52, 0x56, 0x33, 0x00, 
+	0x6b, 0x50, 0x52, 0x56, 0x34, 0x00, 0x6b, 0x50, 
+	0x52, 0x56, 0x35, 0x00, 0x6b, 0x50, 0x52, 0x56, 
+	0x36, 0x00, 0x6b, 0x50, 0x52, 0x56, 0x37, 0x00, 
+	0x6b, 0x52, 0x49, 0x54, 0x33, 0x00, 0x6b, 0x52, 
+	0x49, 0x54, 0x34, 0x00, 0x6b, 0x52, 0x49, 0x54, 
+	0x35, 0x00, 0x6b, 0x52, 0x49, 0x54, 0x36, 0x00, 
+	0x6b, 0x52, 0x49, 0x54, 0x37, 0x00, 0x6b, 0x55, 
+	0x50, 0x00, 0x6b, 0x55, 0x50, 0x33, 0x00, 0x6b, 
+	0x55, 0x50, 0x34, 0x00, 0x6b, 0x55, 0x50, 0x35, 
+	0x00, 0x6b, 0x55, 0x50, 0x36, 0x00, 0x6b, 0x55, 
+	0x50, 0x37, 0x00, 0x6b, 0x61, 0x32, 0x00, 0x6b, 
+	0x62, 0x31, 0x00, 0x6b, 0x62, 0x33, 0x00, 0x6b, 
+	0x63, 0x32, 0x00, 0x72, 0x6d, 0x78, 0x78, 0x00, 
+	0x73, 0x6d, 0x78, 0x78, 0x00, 
+});
+// clang-format on
+}
+
+gc_obj_ref<TermInfo_Database> TermInfo_Database::_s_ReadActiveDatabase()
+{
+    return make_object<TermInfo_Database>(xterm_256color_name.get(), xterm_256color_data.get());
+}

+ 31 - 0
src/Native/natsu.debug.cpp

@@ -0,0 +1,31 @@
+#include "Chino.Kernel.h"
+#include "System.Private.CoreLib.h"
+#ifdef _MSC_VER
+#include <intrin.h>
+#endif
+
+using namespace natsu;
+using namespace System_Private_CoreLib;
+using namespace System_Private_CoreLib::System;
+using namespace System_Private_CoreLib::System::Diagnostics;
+
+void Debug::_s_WriteCore(gc_obj_ref<String> message)
+{
+    Chino_Kernel::Chino::Kernel::KernelDebug::_s_Write(message);
+}
+
+void Debug::_s_WriteLineCore(gc_obj_ref<String> message)
+{
+    Chino_Kernel::Chino::Kernel::KernelDebug::_s_Write(message);
+    Chino_Kernel::Chino::Kernel::KernelDebug::_s_Write(Environment::_s_get_NewLine());
+}
+
+void Debug::_s_FailCore(gc_obj_ref<String> message, gc_obj_ref<String> detailMessage)
+{
+    Chino_Kernel::Chino::Kernel::KernelDebug::_s_Write(message);
+#ifdef _MSC_VER
+    __debugbreak();
+#else
+    assert(false);
+#endif
+}

+ 1 - 286
src/Native/natsu.fcall.cpp

@@ -1,6 +1,6 @@
 #include "Chino.Kernel.h"
+#include "System.Console.h"
 #include <cmath>
-#include <cstring>
 #include <random>
 #ifdef WIN32
 #include <Windows.h>
@@ -16,297 +16,12 @@ using namespace System_Private_CoreLib::System::Runtime::InteropServices;
 using namespace System_Private_CoreLib::System::Threading;
 using namespace Chino_Threading;
 
-int32_t Array::GetLength(gc_obj_ref<Array> _this, int32_t dimension)
-{
-    if (dimension != 0)
-        throw_index_out_of_range_exception();
-    return (intptr_t)_this.cast<RawSzArrayData>()->Count;
-}
-
-int32_t Array::get_Rank(gc_obj_ref<Array> _this)
-{
-    return 1;
-}
-
-int32_t Array::get_Length(gc_obj_ref<Array> _this)
-{
-    return (intptr_t)_this.cast<RawSzArrayData>()->Count;
-}
-
-int64_t Array::get_LongLength(gc_obj_ref<Array> _this)
-{
-    return (intptr_t)_this.cast<RawSzArrayData>()->Count;
-}
-
-int32_t Array::GetUpperBound(gc_obj_ref<Array> _this, int32_t dimension)
-{
-    return GetLength(_this, dimension);
-}
-
-int32_t Array::GetLowerBound(gc_obj_ref<Array> _this, int32_t dimension)
-{
-    if (dimension != 0)
-        throw_exception<IndexOutOfRangeException>();
-    return 0;
-}
-
-void Array::_s_Copy(gc_obj_ref<Array> sourceArray, int32_t sourceIndex, gc_obj_ref<Array> destinationArray, int32_t destinationIndex, int32_t length, bool reliable)
-{
-    check_null_obj_ref(sourceArray);
-    check_null_obj_ref(destinationArray);
-    auto src = sourceArray.cast<RawSzArrayData>();
-    auto dest = sourceArray.cast<RawSzArrayData>();
-    auto element_size = sourceArray.header().vtable_->ElementSize;
-
-    if ((sourceIndex + length) > (intptr_t)src->Count || (destinationIndex + length) > (intptr_t)dest->Count)
-        throw_index_out_of_range_exception();
-
-    if (sourceArray.header().vtable_ != destinationArray.header().vtable_)
-        throw_exception<ArrayTypeMismatchException>();
-    std::memmove(&dest->Data + (size_t)destinationIndex * element_size, &src->Data + (size_t)sourceIndex * element_size, (size_t)length * element_size);
-}
-
-gc_ref<uint8_t> Array::_s_GetRawArrayGeometry(gc_obj_ref<Array> array, gc_ref<uint32_t> numComponents, gc_ref<uint32_t> elementSize, gc_ref<int32_t> lowerBound, ::natsu::gc_ref<bool> containsGCPointers)
-{
-    *numComponents = (uint32_t)Array::GetLength(array, 0);
-    *elementSize = array.header().vtable_->ElementSize;
-    *lowerBound = Array::GetLowerBound(array, 0);
-    *containsGCPointers = true;
-    return array.cast<RawSzArrayData>()->Data;
-}
-
-bool Array::_s_TrySZReverse(gc_obj_ref<Array> array, int32_t index, int32_t count)
-{
-    check_null_obj_ref(array);
-    auto src = array.cast<RawSzArrayData>();
-    auto element_size = array.header().vtable_->ElementSize;
-    auto data = reinterpret_cast<uint8_t *>(&src->Data);
-
-    if ((index + count) > (intptr_t)src->Count)
-        return false;
-
-    size_t i = index, j = index + count - 1;
-    void *tmp = alloca(element_size);
-    while (i < j)
-    {
-        std::memcpy(tmp, data + i * element_size, element_size);
-        std::memcpy(data + j * element_size, data + i * element_size, element_size);
-        std::memcpy(data + j * element_size, tmp, element_size);
-
-        i++;
-        j--;
-    }
-
-    return true;
-}
-
-void Buffer::_s_BlockCopy(gc_obj_ref<Array> src, int32_t srcOffset, gc_obj_ref<Array> dst, int32_t dstOffset, int32_t count)
-{
-    check_null_obj_ref(src);
-    check_null_obj_ref(dst);
-    auto src_arr = src.cast<RawSzArrayData>();
-    auto dest_arr = dst.cast<RawSzArrayData>();
-    auto element_size_src = src.header().vtable_->ElementSize;
-    auto element_size_dest = dst.header().vtable_->ElementSize;
-    auto src_begin = reinterpret_cast<uint8_t *>(&src_arr->Data);
-    auto src_bytes = src_arr->Count * element_size_src;
-    auto dest_begin = reinterpret_cast<uint8_t *>(&dest_arr->Data);
-    auto dest_bytes = dest_arr->Count * element_size_dest;
-
-    if (srcOffset < 0 || dstOffset < 0 || count < 0)
-        throw_index_out_of_range_exception();
-    if ((srcOffset + count) > src_bytes || (dstOffset + count) > dest_bytes)
-        throw_exception<ArgumentException>();
-    std::memmove(dest_begin, src_begin, count);
-}
-
-void Buffer::_s_Memcpy(gc_ptr<uint8_t> dest, gc_ptr<uint8_t> src, int32_t len)
-{
-    std::memcpy(dest.get(), src.get(), len);
-}
-
-void Debug::_s_WriteCore(gc_obj_ref<String> message)
-{
-    Chino_Kernel::Chino::Kernel::KernelDebug::_s_Write(message);
-}
-
-void Debug::_s_WriteLineCore(gc_obj_ref<String> message)
-{
-    Chino_Kernel::Chino::Kernel::KernelDebug::_s_Write(message);
-    Chino_Kernel::Chino::Kernel::KernelDebug::_s_Write(::System_Private_CoreLib::System::Environment::_s_get_NewLine());
-}
-
-void Debug::_s_FailCore(gc_obj_ref<String> message, gc_obj_ref<String> detailMessage)
-{
-    Chino_Kernel::Chino::Kernel::KernelDebug::_s_Write(message);
-#ifdef WIN32
-    DebugBreak();
-#endif
-}
-
-void Buffer::_s_Memmove(gc_ptr<uint8_t> dest, gc_ptr<uint8_t> src, uint64_t len)
-{
-    std::memmove(dest.get(), src.get(), len);
-}
-
 gc_obj_ref<Type> Object::GetType(::natsu::gc_obj_ref<Object> _this)
 {
     check_null_obj_ref(_this);
     pure_call();
 }
 
-char16_t String::get_Chars(gc_obj_ref<String> _this, int32_t index)
-{
-    if ((uint32_t)index >= (uint32_t)_this->_stringLength)
-        throw_index_out_of_range_exception();
-    return (&_this->_firstChar)[index];
-}
-
-int32_t String::get_Length(gc_obj_ref<String> _this)
-{
-    return _this->_stringLength;
-}
-
-gc_obj_ref<String> String::_s_FastAllocateString(int32_t length)
-{
-    auto size = sizeof(String) + length * sizeof(Char);
-    auto obj = natsu::gc_new<String>(size);
-    obj->_stringLength = length;
-    (&obj->_firstChar)[length] = 0;
-    return obj;
-}
-
-int32_t String::_s_wcslen(gc_ptr<char16_t> ptr)
-{
-    std::u16string_view sv(ptr.get());
-    return (int32_t)sv.length();
-}
-
-double Math::_s_Abs(double value)
-{
-    return fabs(value);
-}
-
-float Math::_s_Abs(float value)
-{
-    return fabsf(value);
-}
-
-double Math::_s_Acos(double value)
-{
-    return acos(value);
-}
-
-double Math::_s_Acosh(double value)
-{
-    return acosh(value);
-}
-
-double Math::_s_Asin(double value)
-{
-    return asin(value);
-}
-
-double Math::_s_Asinh(double value)
-{
-    return asinh(value);
-}
-
-double Math::_s_Atan(double value)
-{
-    return atan(value);
-}
-
-double Math::_s_Atan2(double y, double x)
-{
-    return atan2(y, x);
-}
-
-double Math::_s_Atanh(double value)
-{
-    return atanh(value);
-}
-
-double Math::_s_Cbrt(double value)
-{
-    return cbrt(value);
-}
-
-double Math::_s_Ceiling(double value)
-{
-    return ceil(value);
-}
-
-double Math::_s_Cos(double value)
-{
-    return cos(value);
-}
-
-double Math::_s_Cosh(double value)
-{
-    return cosh(value);
-}
-
-double Math::_s_Exp(double value)
-{
-    return exp(value);
-}
-
-double Math::_s_Floor(double value)
-{
-    return floor(value);
-}
-
-double Math::_s_Log(double value)
-{
-    return log(value);
-}
-
-double Math::_s_Log10(double value)
-{
-    return log10(value);
-}
-
-double Math::_s_Pow(double x, double y)
-{
-    return pow(x, y);
-}
-
-double Math::_s_Sin(double value)
-{
-    return sin(value);
-}
-
-double Math::_s_Sinh(double value)
-{
-    return sinh(value);
-}
-
-double Math::_s_Sqrt(double value)
-{
-    return sqrt(value);
-}
-
-double Math::_s_Tan(double value)
-{
-    return tan(value);
-}
-
-double Math::_s_Tanh(double value)
-{
-    return tanh(value);
-}
-
-double Math::_s_FMod(double x, double y)
-{
-    return fmod(x, y);
-}
-
-double Math::_s_ModF(double x, gc_ptr<double> y)
-{
-    return fmod(x, *y);
-}
-
 gc_obj_ref<MulticastDelegate> MulticastDelegate::_s_CreateDelegateLike(gc_obj_ref<MulticastDelegate> delegate, gc_obj_ref<SZArray_1<Delegate>> invocationList)
 {
     auto d_len = invocationList->length();

+ 131 - 0
src/Native/natsu.math.cpp

@@ -0,0 +1,131 @@
+#include "System.Private.CoreLib.h"
+#include <cmath>
+
+using namespace natsu;
+using namespace System_Private_CoreLib;
+using namespace System_Private_CoreLib::System;
+
+double Math::_s_Abs(double value)
+{
+    return fabs(value);
+}
+
+float Math::_s_Abs(float value)
+{
+    return fabsf(value);
+}
+
+double Math::_s_Acos(double value)
+{
+    return acos(value);
+}
+
+double Math::_s_Acosh(double value)
+{
+    return acosh(value);
+}
+
+double Math::_s_Asin(double value)
+{
+    return asin(value);
+}
+
+double Math::_s_Asinh(double value)
+{
+    return asinh(value);
+}
+
+double Math::_s_Atan(double value)
+{
+    return atan(value);
+}
+
+double Math::_s_Atan2(double y, double x)
+{
+    return atan2(y, x);
+}
+
+double Math::_s_Atanh(double value)
+{
+    return atanh(value);
+}
+
+double Math::_s_Cbrt(double value)
+{
+    return cbrt(value);
+}
+
+double Math::_s_Ceiling(double value)
+{
+    return ceil(value);
+}
+
+double Math::_s_Cos(double value)
+{
+    return cos(value);
+}
+
+double Math::_s_Cosh(double value)
+{
+    return cosh(value);
+}
+
+double Math::_s_Exp(double value)
+{
+    return exp(value);
+}
+
+double Math::_s_Floor(double value)
+{
+    return floor(value);
+}
+
+double Math::_s_Log(double value)
+{
+    return log(value);
+}
+
+double Math::_s_Log10(double value)
+{
+    return log10(value);
+}
+
+double Math::_s_Pow(double x, double y)
+{
+    return pow(x, y);
+}
+
+double Math::_s_Sin(double value)
+{
+    return sin(value);
+}
+
+double Math::_s_Sinh(double value)
+{
+    return sinh(value);
+}
+
+double Math::_s_Sqrt(double value)
+{
+    return sqrt(value);
+}
+
+double Math::_s_Tan(double value)
+{
+    return tan(value);
+}
+
+double Math::_s_Tanh(double value)
+{
+    return tanh(value);
+}
+
+double Math::_s_FMod(double x, double y)
+{
+    return fmod(x, y);
+}
+
+double Math::_s_ModF(double x, gc_ptr<double> y)
+{
+    return fmod(x, *y);
+}

+ 36 - 0
src/Native/natsu.runtime.h

@@ -112,6 +112,19 @@ namespace stack
     static constexpr O null = 0;
 }
 
+template <class T>
+auto &vtable() noexcept
+{
+    return vtable_holder<typename T::VTable>::get();
+}
+
+template <class T>
+auto &vtable(gc_obj_ref<> obj) noexcept
+{
+    check_null_obj_ref(obj);
+    return *static_cast<const typename T::VTable *>(obj.header().vtable_);
+}
+
 gc_obj_ref<::System_Private_CoreLib::System::Object> gc_alloc(const vtable_t &vtable, size_t size);
 
 template <class T>
@@ -591,6 +604,20 @@ namespace ops
         return *reinterpret_cast<const TTo *>(address.get());
     }
 
+    template <class TTo, class TFrom>
+    void stind(gc_ptr<TFrom> &address, TTo value)
+    {
+        check_null_obj_ref(address);
+        *reinterpret_cast<TTo *>(address.get()) = value;
+    }
+
+    template <class TTo, class TFrom>
+    void stind(gc_ref<TFrom> &address, TTo value)
+    {
+        check_null_obj_ref(address);
+        *reinterpret_cast<TTo *>(address.get()) = value;
+    }
+
     template <class T>
     ::System_Private_CoreLib::System::RuntimeTypeHandle ldtoken_type()
     {
@@ -701,6 +728,15 @@ namespace details
     };
 }
 
+template <class T>
+::natsu::variable_type_t<T> System::Activator::_s_CreateInstance()
+{
+    if constexpr (::natsu::has_default_ctor_v<T>)
+        return ::natsu::make_object<T>();
+    else
+        ::natsu::throw_exception<System::MissingMethodException>();
+}
+
 template <class T>
 void System::ByReference_1<T>::_ctor(::natsu::gc_ref<System::ByReference_1<T>> _this, ::natsu::gc_ref<::natsu::variable_type_t<T>> value)
 {

+ 33 - 0
src/Native/natsu.string.cpp

@@ -0,0 +1,33 @@
+#include "System.Private.CoreLib.h"
+#include <cstring>
+
+using namespace natsu;
+using namespace System_Private_CoreLib;
+using namespace System_Private_CoreLib::System;
+
+char16_t String::get_Chars(gc_obj_ref<String> _this, int32_t index)
+{
+    if ((uint32_t)index >= (uint32_t)_this->_stringLength)
+        throw_index_out_of_range_exception();
+    return (&_this->_firstChar)[index];
+}
+
+int32_t String::get_Length(gc_obj_ref<String> _this)
+{
+    return _this->_stringLength;
+}
+
+gc_obj_ref<String> String::_s_FastAllocateString(int32_t length)
+{
+    auto size = sizeof(String) + length * sizeof(Char);
+    auto obj = natsu::gc_new<String>(size);
+    obj->_stringLength = length;
+    (&obj->_firstChar)[length] = 0;
+    return obj;
+}
+
+int32_t String::_s_wcslen(gc_ptr<char16_t> ptr)
+{
+    std::u16string_view sv(ptr.get());
+    return (int32_t)sv.length();
+}

+ 53 - 9
src/Native/natsu.typedef.h

@@ -117,12 +117,6 @@ struct vtable_holder
     }
 };
 
-template <class T>
-auto &vtable() noexcept
-{
-    return vtable_holder<typename T::VTable>::get();
-}
-
 typedef struct _vtable
 {
     uint32_t ElementSize;
@@ -236,6 +230,37 @@ struct variable_type<T, false>
 template <class T>
 using variable_type_t = typename variable_type<T, is_value_type_v<T>>::type;
 
+template <class T, bool IsValueType>
+struct this_type;
+
+template <class T>
+struct this_type<T, true>
+{
+    using type = gc_ref<T>;
+};
+
+template <class T>
+struct this_type<T, false>
+{
+    using type = gc_obj_ref<T>;
+};
+
+template <class T>
+using this_type_t = typename this_type<T, is_value_type_v<T>>::type;
+
+template <class T, class = void>
+struct has_default_ctor : std::false_type
+{
+};
+
+template <class T>
+struct has_default_ctor<T, std::void_t<decltype(T::_ctor(std::declval<this_type_t<T>>()))>> : std::true_type
+{
+};
+
+template <class T>
+constexpr bool has_default_ctor_v = is_value_type_v<T> || has_default_ctor<to_clr_type_t<T>>::value;
+
 template <class T>
 class clr_volatile
 {
@@ -342,9 +367,9 @@ struct gc_ref
         return *ptr_;
     }
 
-    gc_ref &operator=(uintptr_t ptr) noexcept
+    gc_ref &operator=(T &ptr) noexcept
     {
-        ptr_ = reinterpret_cast<T *>(ptr);
+        ptr_ = &ptr;
         return *this;
     }
 };
@@ -741,7 +766,7 @@ struct string_literal
     std::array<char16_t, N> _firstChar;
 
     constexpr string_literal(const char16_t (&str)[N])
-        : _stringLength((int32_t)N), _firstChar(init_array(str, std::make_index_sequence<N>()))
+        : _stringLength((int32_t)N - 1), _firstChar(init_array(str, std::make_index_sequence<N>()))
     {
     }
 
@@ -752,6 +777,18 @@ struct string_literal
     }
 };
 
+template <class T, size_t N>
+struct szarray_literal
+{
+    intptr_t Length;
+    std::array<T, N> _elements;
+
+    constexpr szarray_literal(const std::array<T, N> &values)
+        : Length((intptr_t)N), _elements(values)
+    {
+    }
+};
+
 template <class TObject, class TValue>
 struct static_object
 {
@@ -780,6 +817,13 @@ constexpr auto make_string_literal(const char16_t (&str)[N])
     return static_object<::System_Private_CoreLib::System::String,
         string_literal<N>>(str);
 }
+
+template <class T, size_t N>
+constexpr auto make_szarray_literal(const std::array<T, N> &values)
+{
+    return static_object<::System_Private_CoreLib::System::SZArray_1<T>,
+        szarray_literal<T, N>>(values);
+}
 }
 
 #define NATSU_PRIMITIVE_IMPL_BYTE                     \

+ 96 - 11
src/Natsu.Compiler/ILImporter.cs

@@ -399,12 +399,24 @@ namespace Natsu.Compiler
                     case Code.Add:
                         emitter.Add();
                         break;
+                    case Code.Add_Ovf:
+                        emitter.Add_Ovf();
+                        break;
                     case Code.Sub:
                         emitter.Sub();
                         break;
+                    case Code.Sub_Ovf:
+                        emitter.Sub_Ovf();
+                        break;
                     case Code.Mul:
                         emitter.Mul();
                         break;
+                    case Code.Mul_Ovf:
+                        emitter.Mul_Ovf();
+                        break;
+                    case Code.Mul_Ovf_Un:
+                        emitter.Mul_Ovf_Un();
+                        break;
                     case Code.Div:
                         emitter.Div();
                         break;
@@ -847,8 +859,12 @@ namespace Natsu.Compiler
         // Binary
 
         public void Add() => Binary("+");
+        public void Add_Ovf() => Binary_Ovf("+");
         public void Sub() => Binary("-");
+        public void Sub_Ovf() => Binary_Ovf("-");
         public void Mul() => Binary("*");
+        public void Mul_Ovf() => Binary_Ovf("*");
+        public void Mul_Ovf_Un() => Binary_Ovf_Un("*");
         public void Div() => Binary("/");
         public void Div_Un() => Binary_Un("/");
         public void Rem() => Binary("%");
@@ -935,14 +951,19 @@ namespace Natsu.Compiler
         public void Ldind_U4() => Ldind(CorLibTypes.UInt32);
 
         // Stind
-        public void Stind_I1() => Stind("i1");
-        public void Stind_I2() => Stind("i2");
-        public void Stind_I4() => Stind("i4");
-        public void Stind_I8() => Stind("i8");
-        public void Stind_R4() => Stind("r4");
-        public void Stind_R8() => Stind("r8");
-        public void Stind_I() => Stind("i");
-        public void Stind_Ref() => Stind("ref");
+        public void Stind_I1() => Stind(CorLibTypes.SByte);
+        public void Stind_I2() => Stind(CorLibTypes.Int16);
+        public void Stind_I4() => Stind(CorLibTypes.Int32);
+        public void Stind_I8() => Stind(CorLibTypes.Int64);
+        public void Stind_R4() => Stind(CorLibTypes.Single);
+        public void Stind_R8() => Stind(CorLibTypes.Double);
+        public void Stind_I() => Stind(CorLibTypes.IntPtr);
+        public void Stind_Ref()
+        {
+            var value = Stack.Pop();
+            var addr = Stack.Pop();
+            Writer.Ident(Ident).WriteLine($"*{addr.Expression} = {value.Expression};");
+        }
 
         // Ldelem
         public void Ldelem_I1() => Ldelem(CorLibTypes.SByte, "i1");
@@ -1115,7 +1136,7 @@ namespace Natsu.Compiler
             {
                 return $"{src.Expression}.get()";
             }
-            else if (destType.ElementType != ElementType.ByRef &&
+            else if (!TypeUtils.IsByRef(destType) &&
                 src.Type.Code == StackTypeCode.Ref)
             {
                 return $"*{src.Expression}";
@@ -1300,6 +1321,54 @@ namespace Natsu.Compiler
             }
         }
 
+        public void Binary_Ovf(string op)
+        {
+            var v2 = Stack.Pop();
+            var v1 = Stack.Pop();
+            var type = TypeUtils.IsRefOrPtr(v1.Type) && TypeUtils.IsRefOrPtr(v2.Type)
+                ? TypeUtils.GetStackType(CorLibTypes.IntPtr)
+                : v1.Type;
+
+            if (op == "%" && v1.Type.Code == StackTypeCode.F)
+            {
+                if (v1.Type.TypeSig.ElementType == ElementType.R4)
+                    Stack.Push(type, $"fmodf({v1.Expression}, {v2.Expression})");
+                else
+                    Stack.Push(type, $"fmod({v1.Expression}, {v2.Expression})");
+            }
+            else
+            {
+                if (v1.Type.TypeSig.ElementType == ElementType.ValueType)
+                    Stack.Push(v2.Type, $"({v1.Expression} {op} {v2.Expression})");
+                else
+                    Stack.Push(type, $"({v1.Expression} {op} {v2.Expression})");
+            }
+        }
+
+        public void Binary_Ovf_Un(string op)
+        {
+            var v2 = Stack.Pop();
+            var v1 = Stack.Pop();
+            var type = TypeUtils.IsRefOrPtr(v1.Type) && TypeUtils.IsRefOrPtr(v2.Type)
+                ? TypeUtils.GetStackType(CorLibTypes.IntPtr)
+                : v1.Type;
+
+            if (op == "%" && v1.Type.Code == StackTypeCode.F)
+            {
+                if (v1.Type.TypeSig.ElementType == ElementType.R4)
+                    Stack.Push(type, $"fmodf({v1.Expression}, {v2.Expression})");
+                else
+                    Stack.Push(type, $"fmod({v1.Expression}, {v2.Expression})");
+            }
+            else
+            {
+                if (v1.Type.TypeSig.ElementType == ElementType.ValueType)
+                    Stack.Push(v2.Type, $"({v1.Expression} {op} {v2.Expression})");
+                else
+                    Stack.Push(type, $"({v1.Expression} {op} {v2.Expression})");
+            }
+        }
+
         public void Binary_Un(string op)
         {
             var v2 = Stack.Pop();
@@ -1631,11 +1700,27 @@ namespace Natsu.Compiler
             Stack.Push(stackType, $"::natsu::ops::ldind<{TypeUtils.EscapeVariableTypeName(stackType)}>({addr.Expression})");
         }
 
-        private void Stind(string type)
+        private void Stind(TypeSig stackType)
         {
             var value = Stack.Pop();
             var addr = Stack.Pop();
-            Writer.Ident(Ident).WriteLine($"*{addr.Expression} = {value.Expression};");
+
+            if (addr.Expression == "str" && value.Expression == "p")
+                ;
+
+            if (addr.Type.TypeSig.ElementType == ElementType.ByRef ||
+                addr.Type.TypeSig.ElementType == ElementType.Ptr)
+            {
+                var actualType = addr.Type.TypeSig.Next;
+                if (TypeUtils.IsSameType(actualType.ToTypeDefOrRef(), stackType.ToTypeDefOrRef())
+                    || TypeUtils.IsSameType(actualType.ToTypeDefOrRef(), value.Type.TypeSig.ToTypeDefOrRef()))
+                {
+                    Writer.Ident(Ident).WriteLine($"*{addr.Expression} = {value.Expression};");
+                    return;
+                }
+            }
+
+            Writer.Ident(Ident).WriteLine($"::natsu::ops::stind<{TypeUtils.EscapeVariableTypeName(stackType)}>({addr.Expression}, {value.Expression});");
         }
 
         private void Ldelem(TypeSig stackType, string type)

+ 3 - 1
src/Natsu.Compiler/Program.cs

@@ -21,8 +21,10 @@ namespace Natsu.Compiler
             @"..\..\..\..\..\out\bin\netcoreapp3.0\Chino.IO.dll",
             @"..\..\..\..\..\out\bin\netcoreapp3.0\Chino.Chip.K210.dll",
             @"..\..\..\..\..\out\bin\netcoreapp3.0\Chino.Chip.Emulator.dll",
+            @"..\..\..\..\..\out\bin\netcoreapp3.0\Chino.Interop.dll",
             @"..\..\..\..\..\out\bin\netcoreapp3.0\Chino.Apps.Shell.dll",
             @"..\..\..\..\..\out\bin\netcoreapp3.0\System.Private.CoreLib.dll",
+            @"..\..\..\..\..\out\bin\netcoreapp3.0\System.Console.dll",
             @"..\..\..\..\..\out\bin\netcoreapp3.0\System.Collections.dll",
             @"..\..\..\..\..\out\bin\netcoreapp3.0\System.Memory.dll",
             @"..\..\..\..\..\out\bin\netcoreapp3.0\System.Runtime.dll",
@@ -72,7 +74,7 @@ namespace Natsu.Compiler
             using (var sha256 = SHA256.Create())
             {
                 digest = Convert.ToBase64String(sha256.ComputeHash(File.ReadAllBytes(_module.Location)));
-#if false
+#if true
                 if (HasOutputUptodate(Path.Combine(outputPath, $"{_module.Assembly.Name}.h"), digest))
                     return;
 #endif

+ 13 - 2
src/Natsu.Compiler/TypeUtils.cs

@@ -470,7 +470,7 @@ namespace Natsu.Compiler
             if (method.MethodSig.HasThis)
             {
                 var sb = new StringBuilder();
-                if (hasExplicit)
+                if (hasExplicit || method.Name.Contains(".cctor"))
                     sb.Append(EscapeIdentifier(method.Name.String));
                 else
                     sb.Append(EscapeIdentifier(method.Name.String.Split('.').Last()));
@@ -655,6 +655,9 @@ namespace Natsu.Compiler
             if (string.IsNullOrEmpty(name))
                 throw new ArgumentException("Invalid identifier");
 
+            if (name == "_int32")
+                return "int32_";
+
             var sb = new StringBuilder();
             if (char.IsDigit(name[0]))
                 sb.Append('_');
@@ -896,7 +899,7 @@ namespace Natsu.Compiler
 
         public static bool IsSameType(ITypeDefOrRef type1, ITypeDefOrRef type2)
         {
-            return type1 == type2 || type1 == type2.ScopeType;
+            return type1 == type2 || type1.FullName == type2.FullName || type1 == type2.ScopeType;
         }
 
         public static string GetLocalName(Local local, MethodDef method)
@@ -946,5 +949,13 @@ namespace Natsu.Compiler
 
             return true;
         }
+
+        public static bool IsByRef(TypeSig type)
+        {
+            if (type.ElementType == ElementType.ByRef) return true;
+            if (type.ElementType == ElementType.Pinned)
+                return IsByRef(type.Next);
+            return false;
+        }
     }
 }

+ 3 - 3
src/System.Console/System/ConsolePal.Chino.cs

@@ -779,7 +779,7 @@ namespace System
             // and specific color choice.  If we have, just output that format string again.
             int fgbgIndex = foreground ? 0 : 1;
             int ccValue = (int)color;
-            string evaluatedString = s_fgbgAndColorStrings[fgbgIndex, ccValue]; // benign race
+            string evaluatedString = s_fgbgAndColorStrings[fgbgIndex * 16 + ccValue]; // benign race
             if (evaluatedString != null)
             {
                 WriteStdoutAnsiString(evaluatedString);
@@ -798,7 +798,7 @@ namespace System
 
                     WriteStdoutAnsiString(evaluatedString);
 
-                    s_fgbgAndColorStrings[fgbgIndex, ccValue] = evaluatedString; // benign race
+                    s_fgbgAndColorStrings[fgbgIndex * 16 + ccValue] = evaluatedString; // benign race
                 }
             }
         }
@@ -842,7 +842,7 @@ namespace System
         };
 
         /// <summary>Cache of the format strings for foreground/background and ConsoleColor.</summary>
-        private static readonly string[,] s_fgbgAndColorStrings = new string[2, 16]; // 2 == fg vs bg, 16 == ConsoleColor values
+        private static readonly string[] s_fgbgAndColorStrings = new string[2 * 16]; // 2 == fg vs bg, 16 == ConsoleColor values
 
         public static bool TryGetSpecialConsoleKey(char[] givenChars, int startIndex, int endIndex, out ConsoleKeyInfo key, out int keyLength)
         {

+ 9 - 6
src/System.Console/System/TermInfo.cs

@@ -766,9 +766,12 @@ namespace System
 
                 // Determine how much space is needed to store the formatted string.
                 string? stringArg = arg as string;
-                int neededLength = stringArg != null ?
-                    Interop.Text.SNPrintF(null, 0, format, stringArg) :
-                    Interop.Text.SNPrintF(null, 0, format, (int)arg);
+                var asciiFormat = Encoding.ASCII.GetBytes(format);
+                var asciiArg = stringArg != null ? Encoding.ASCII.GetBytes(stringArg) : null;
+
+                int neededLength = asciiArg != null ?
+                    Interop.Text.SNPrintF(null, 0, asciiFormat, asciiArg) :
+                    Interop.Text.SNPrintF(null, 0, asciiFormat, (int)arg);
                 if (neededLength == 0)
                 {
                     return string.Empty;
@@ -782,9 +785,9 @@ namespace System
                 byte[] bytes = new byte[neededLength + 1]; // extra byte for the null terminator
                 fixed (byte* ptr = &bytes[0])
                 {
-                    int length = stringArg != null ?
-                        Interop.Text.SNPrintF(ptr, bytes.Length, format, stringArg) :
-                        Interop.Text.SNPrintF(ptr, bytes.Length, format, (int)arg);
+                    int length = asciiArg != null ?
+                        Interop.Text.SNPrintF(ptr, bytes.Length, asciiFormat, asciiArg) :
+                        Interop.Text.SNPrintF(ptr, bytes.Length, asciiFormat, (int)arg);
                     if (length != neededLength)
                     {
                         throw new InvalidOperationException(SR.InvalidOperation_PrintF);

+ 17 - 0
src/System.Private.CoreLib/System/ReadOnlySpan.Fast.cs

@@ -207,6 +207,23 @@ namespace System
             return left._length == right._length && Unsafe.AreSame<T>(ref left._pointer.Value, ref right._pointer.Value);
         }
 
+        /// <summary>
+        /// For <see cref="ReadOnlySpan{Char}"/>, returns a new instance of string that represents the characters pointed to by the span.
+        /// Otherwise, returns a <see cref="string"/> with the name of the type and the number of elements.
+        /// </summary>
+        public override string ToString()
+        {
+            if (typeof(T) == typeof(char))
+            {
+                unsafe
+                {
+                    fixed (char* src = &Unsafe.As<T, char>(ref _pointer.Value))
+                        return new string(src, 0, _length);
+                }
+            }
+            return string.Format("System.ReadOnlySpan<>[{0}]", _length);
+        }
+
         /// <summary>
         /// Forms a slice out of the given read-only span, beginning at 'start'.
         /// </summary>

+ 1 - 1
src/apps/Chino.Apps.Shell/Program.cs

@@ -7,7 +7,7 @@ namespace Chino.Apps.Shell
     {
         static void Main(string[] args)
         {
-            Debug.WriteLine("Hello Shell!");
+            Console.WriteLine("Hello Shell!");
         }
     }
 }

+ 1 - 0
tests/ChinoTest/ChinoTest.csproj

@@ -15,6 +15,7 @@
 
   <ItemGroup>
     <ProjectReference Include="..\..\src\Chino.Core\Chino.Core.csproj" />
+    <ProjectReference Include="..\..\src\Chino.IO\Chino.IO.csproj" />
   </ItemGroup>
 
 </Project>

+ 28 - 0
tests/ChinoTest/ObjectTests.cs

@@ -1,6 +1,8 @@
 using System;
 using System.Collections.Generic;
 using System.Text;
+using Chino.IO;
+using Chino.IO.Devices;
 using Chino.Objects;
 using Xunit;
 
@@ -17,6 +19,24 @@ namespace ChinoTest
             }
         }
 
+        private class TestDevice : ConsoleDevice
+        {
+
+        }
+
+        private class TestDriver : Driver
+        {
+            protected override void InstallDevice(DeviceDescription deviceDescription)
+            {
+                IOManager.InstallDevice(new TestDevice());
+            }
+
+            protected override bool IsCompatible(DeviceDescription deviceDescription)
+            {
+                return true;
+            }
+        }
+
         [Fact]
         public void TestCreateDirectory()
         {
@@ -34,5 +54,13 @@ namespace ChinoTest
 
             Assert.Equal("obj", obj.Object.Name);
         }
+
+        [Fact]
+        public void TestCreateDevice()
+        {
+            IOManager.InstallDriver("test.test", new TestDriver());
+            IOManager.RegisterDeviceDescription(new DeviceDescription("test.console"));
+            var device = ObjectManager.OpenObject<Device>(AccessMask.GenericRead, new ObjectAttributes { Name = "/dev/console0" });
+        }
     }
 }