diff --git a/lcrash/CMakeLists.txt b/lcrash/CMakeLists.txt index 55c5ffb..dcd4f9f 100644 --- a/lcrash/CMakeLists.txt +++ b/lcrash/CMakeLists.txt @@ -8,7 +8,7 @@ lw_project(lcrash enable_language(ASM) lw_add_executable(lcrashkern - SOURCES main.c cmdline.c util.c lnxboot.c math.c debug/debug.c acpi/acpi.c efi/efi.c efi/guid.c efi/memmap.c gdb/gdb.c pci/pci.c mm/phys.c mm/kmalloc.c mm/virt.c driver/sysbus.c + SOURCES main.c cmdline.c util.c lnxboot.c math.c irq.c irq.s debug/debug.c acpi/acpi.c efi/efi.c efi/guid.c efi/memmap.c gdb/gdb.c pci/pci.c mm/phys.c mm/kmalloc.c mm/virt.c driver/sysbus.c driver/vga.c driver/cap/textdisplay.c ) add_executable(lcrashkernld IMPORTED) set_property(TARGET lcrashkernld PROPERTY IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/lcrash.ld) diff --git a/lcrash/driver/cap/textdisplay.c b/lcrash/driver/cap/textdisplay.c new file mode 100644 index 0000000..75c66e9 --- /dev/null +++ b/lcrash/driver/cap/textdisplay.c @@ -0,0 +1,17 @@ +#include + +struct SysbusDeviceCapability* TextModeDisplayCapability = 0; + +bool TextModeDisplayCapabilityInitialized = false; +bool TextModeDisplayCapabilityIsInitialized() { + return TextModeDisplayCapabilityInitialized; +} + +void TextModeDisplayCapabilityInitialize() { + TextModeDisplayCapability = SysbusCreateCapability(); + TextModeDisplayCapabilityInitialized = true; +}; + +struct SysbusDeviceCapability* TextModeDisplayCapabilityGetCapability() { + return TextModeDisplayCapability; +} diff --git a/lcrash/driver/cap/textdisplay.h b/lcrash/driver/cap/textdisplay.h new file mode 100644 index 0000000..af115f7 --- /dev/null +++ b/lcrash/driver/cap/textdisplay.h @@ -0,0 +1,62 @@ +#pragma once + +#include +#include + +/** + * Text-mode display capability. + */ +struct TextModeDisplayCapability { + /** + * Switch the display into text mode if it supports + * other display modes + * + * \return 0 on success + */ + s32 (*Enable)(struct SysbusDevice* Device); + + /** + * Clear the screen and reset it's attributes to a known + * state, what state exactly? That's for me to know and + * you to find out. + * + * \return 0 on success + */ + s32 (*Reset)(struct SysbusDevice* Device); + + /** + * Get the maximum number of usable colors + * + * \return color count or -ERROR + */ + s32 (*GetPaletteSize)(struct SysbusDevice* Device); + + /** + * Set a palette color + * + * \return 0 on success + */ + s32 (*SetPaletteColor)(struct SysbusDevice* Device, u32 ID, u8 Red, u8 Green, u8 Blue); + + /** + * Set a character on the display + * + * \return 0 on success + */ + s32 (*SetCharacter)(struct SysbusDevice* Device, u32 Row, u32 Col, c8 Char, u32 ForegroundColor, u32 BackgroundColor); +}; + +/** + * Initialize the capability driver + */ +void TextModeDisplayCapabilityInitialize(); + +/** + * Function name + */ +struct SysbusDeviceCapability* TextModeDisplayCapabilityGetCapability(); + +/** + * Yeah + */ +bool TextModeDisplayCapabilityIsInitialized(); diff --git a/lcrash/driver/sysbus.c b/lcrash/driver/sysbus.c index de68d0f..3660ec0 100644 --- a/lcrash/driver/sysbus.c +++ b/lcrash/driver/sysbus.c @@ -86,6 +86,9 @@ struct SysbusDevice* SysbusCreateDeviceInternal( // Add us as an instance Description->Instances[Description->InstanceCount++] = Device; + // Run hook + if (Description->CreateDevice != 0) Description->CreateDevice(Device, DeviceData); + return Device; } @@ -109,6 +112,22 @@ void SysbusDeleteDevice(struct SysbusDevice* Device) { Panic("todo"); } +struct SysbusDeviceCapability* SysbusCreateCapability() { + struct SysbusDeviceCapability* Capability = KernelHeapAlloc(sizeof(struct SysbusDeviceCapability), 1, 0); + + return Capability; +} + +void SysbusDeleteCapability() { + Panic("todo"); +} + +void* SysbusGetCapability(struct SysbusDevice* Device, struct SysbusDeviceCapability* Capability) { + if (Device->DeviceDescription->GetCapability != 0) { + return Device->DeviceDescription->GetCapability(Device, Capability); + } else return 0; +} + void SysbusInitialize() { // Create the sysbus root SysbusRootDeviceDescription = SysbusCreateDeviceDescriptionInternal(); @@ -124,3 +143,5 @@ void SysbusInitialize() { return; } + +struct SysbusDevice* SysbusGetRootDevice() { return SysbusRootDevice; } diff --git a/lcrash/driver/sysbus.h b/lcrash/driver/sysbus.h index 388c5ba..7812035 100644 --- a/lcrash/driver/sysbus.h +++ b/lcrash/driver/sysbus.h @@ -184,3 +184,23 @@ struct SysbusDevice* SysbusCreateDevice( * Delete a device */ void SysbusDeleteDevice(struct SysbusDevice* Device); + +/** + * Create a sysbus capability + */ +struct SysbusDeviceCapability* SysbusCreateCapability(); + +/** + * Delete a sysbus capability + */ +void SysbusDeleteCapability(); + +/** + * Get a sysbus capability + */ +void* SysbusGetCapability(struct SysbusDevice* Device, struct SysbusDeviceCapability* Capability); + +/** + * Get the system bus device + */ +struct SysbusDevice* SysbusGetRootDevice(); diff --git a/lcrash/driver/vga.c b/lcrash/driver/vga.c new file mode 100644 index 0000000..e93c9d5 --- /dev/null +++ b/lcrash/driver/vga.c @@ -0,0 +1,913 @@ +#include +#include +#include +#include + +#define _(X, Y, A, B, C, D, E, F, G, H) \ + [X][Y] = A, [X + 1][Y] = B, [X + 2][Y] = C, [X + 3][Y] = D, [X + 4][Y] = E, [X + 5][Y] = F, [X + 6][Y] = G, [X + 7][Y] = H, +// Font uh yeah its a font yeah B) +u8 VgaFont[256][32] = { + _(0x00, 0x0, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x00, 0x1, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x00, 0x2, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x00, 0x3, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x00, 0x4, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x00, 0x5, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x00, 0x6, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x00, 0x7, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x00, 0x8, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x00, 0x9, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x00, 0xa, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x00, 0xb, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x00, 0xc, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x00, 0xd, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x00, 0xe, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x00, 0xf, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + + _(0x08, 0x0, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x08, 0x1, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x08, 0x2, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x08, 0x3, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x08, 0x4, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x08, 0x5, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x08, 0x6, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x08, 0x7, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x08, 0x8, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x08, 0x9, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x08, 0xa, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x08, 0xb, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x08, 0xc, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x08, 0xd, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x08, 0xe, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x08, 0xf, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + + _(0x10, 0x0, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x10, 0x1, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x10, 0x2, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x10, 0x3, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x10, 0x4, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x10, 0x5, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x10, 0x6, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x10, 0x7, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x10, 0x8, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x10, 0x9, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x10, 0xa, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x10, 0xb, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x10, 0xc, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x10, 0xd, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x10, 0xe, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x10, 0xf, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + + _(0x18, 0x0, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x18, 0x1, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x18, 0x2, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x18, 0x3, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x18, 0x4, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x18, 0x5, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x18, 0x6, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x18, 0x7, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x18, 0x8, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x18, 0x9, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x18, 0xa, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x18, 0xb, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x18, 0xc, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x18, 0xd, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x18, 0xe, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x18, 0xf, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + + _(0x20, 0x0, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x20, 0x1, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x20, 0x2, 0b00000000, 0b01100000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x20, 0x3, 0b00000000, 0b01100000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x20, 0x4, 0b00000000, 0b01100000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x20, 0x5, 0b00000000, 0b01100000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x20, 0x6, 0b00000000, 0b01100000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x20, 0x7, 0b00000000, 0b01100000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x20, 0x8, 0b00000000, 0b01100000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x20, 0x9, 0b00000000, 0b01100000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x20, 0xa, 0b00000000, 0b01100000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x20, 0xb, 0b00000000, 0b01100000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x20, 0xc, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x20, 0xd, 0b00000000, 0b01100000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x20, 0xe, 0b00000000, 0b01100000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x20, 0xf, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + + _(0x28, 0x0, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x28, 0x1, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x28, 0x2, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00001100) + _(0x28, 0x3, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00001100) + _(0x28, 0x4, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00001100) + _(0x28, 0x5, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00001100) + _(0x28, 0x6, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00001100) + _(0x28, 0x7, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00110000) + _(0x28, 0x8, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00110000) + _(0x28, 0x9, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00110000) + _(0x28, 0xa, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00110000) + _(0x28, 0xb, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b11000000) + _(0x28, 0xc, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b01100000, 0b00000000, 0b00000000, 0b11000000) + _(0x28, 0xd, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b01100000, 0b00000000, 0b00000000, 0b11000000) + _(0x28, 0xe, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b01100000, 0b00000000, 0b01100000, 0b11000000) + _(0x28, 0xf, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b01100000, 0b00000000, 0b01100000, 0b11000000) + + _(0x30, 0x0, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x30, 0x1, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x30, 0x2, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x30, 0x3, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x30, 0x4, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x30, 0x5, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x30, 0x6, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x30, 0x7, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x30, 0x8, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x30, 0x9, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x30, 0xa, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x30, 0xb, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x30, 0xc, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x30, 0xd, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x30, 0xe, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x30, 0xf, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + + _(0x38, 0x0, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x38, 0x1, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x38, 0x2, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x38, 0x3, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x38, 0x4, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x38, 0x5, 0b00000000, 0b00000000, 0b01100000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x38, 0x6, 0b00000000, 0b00000000, 0b01100000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x38, 0x7, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x38, 0x8, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x38, 0x9, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x38, 0xa, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x38, 0xb, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x38, 0xc, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x38, 0xd, 0b00000000, 0b00000000, 0b01100000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x38, 0xe, 0b00000000, 0b00000000, 0b01100000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x38, 0xf, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + + _(0x40, 0x0, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x40, 0x1, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x40, 0x2, 0b00000000, 0b00110000, 0b11111000, 0b11111100, 0b11111000, 0b11111100, 0b11111100, 0b01111100) + _(0x40, 0x3, 0b00000000, 0b01111000, 0b11111000, 0b11111100, 0b11111100, 0b11111100, 0b11111100, 0b11111100) + _(0x40, 0x4, 0b00000000, 0b11001100, 0b11001100, 0b11000000, 0b11001100, 0b11000000, 0b11000000, 0b11000000) + _(0x40, 0x5, 0b00000000, 0b11001100, 0b11001100, 0b11000000, 0b11001100, 0b11000000, 0b11000000, 0b11000000) + _(0x40, 0x6, 0b00000000, 0b11001100, 0b11001100, 0b11000000, 0b11001100, 0b11000000, 0b11000000, 0b11000000) + _(0x40, 0x7, 0b00000000, 0b11001100, 0b11001100, 0b11000000, 0b11001100, 0b11000000, 0b11000000, 0b11000000) + _(0x40, 0x8, 0b00000000, 0b11001100, 0b11001100, 0b11000000, 0b11001100, 0b11000000, 0b11000000, 0b11000000) + _(0x40, 0x9, 0b00000000, 0b11111100, 0b11111000, 0b11000000, 0b11001100, 0b11111100, 0b11111100, 0b11011100) + _(0x40, 0xa, 0b00000000, 0b11111100, 0b11111000, 0b11000000, 0b11001100, 0b11111100, 0b11111100, 0b11011100) + _(0x40, 0xb, 0b00000000, 0b11001100, 0b11001100, 0b11000000, 0b11001100, 0b11000000, 0b11000000, 0b11001100) + _(0x40, 0xc, 0b00000000, 0b11001100, 0b11001100, 0b11000000, 0b11001100, 0b11000000, 0b11000000, 0b11001100) + _(0x40, 0xd, 0b00000000, 0b11001100, 0b11001100, 0b11000000, 0b11001100, 0b11000000, 0b11000000, 0b11001100) + _(0x40, 0xe, 0b00000000, 0b11001100, 0b11111100, 0b11111100, 0b11111100, 0b11111100, 0b11000000, 0b11111100) + _(0x40, 0xf, 0b00000000, 0b11001100, 0b11111000, 0b11111100, 0b11111000, 0b11111100, 0b11000000, 0b01111000) + + _(0x48, 0x0, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x48, 0x1, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x48, 0x2, 0b11001100, 0b11111100, 0b00001100, 0b11001100, 0b11000000, 0b11000110, 0b11000110, 0b11111100) + _(0x48, 0x3, 0b11001100, 0b11111100, 0b00001100, 0b11001100, 0b11000000, 0b11000110, 0b11000110, 0b11111100) + _(0x48, 0x4, 0b11001100, 0b00110000, 0b00001100, 0b11001100, 0b11000000, 0b11101110, 0b11000110, 0b11001100) + _(0x48, 0x5, 0b11001100, 0b00110000, 0b00001100, 0b11011000, 0b11000000, 0b11101110, 0b11000110, 0b11001100) + _(0x48, 0x6, 0b11001100, 0b00110000, 0b00001100, 0b11011000, 0b11000000, 0b11111110, 0b11000110, 0b11001100) + _(0x48, 0x7, 0b11001100, 0b00110000, 0b00001100, 0b11011000, 0b11000000, 0b11010110, 0b11110110, 0b11001100) + _(0x48, 0x8, 0b11001100, 0b00110000, 0b00001100, 0b11100000, 0b11000000, 0b11010110, 0b11110110, 0b11001100) + _(0x48, 0x9, 0b11111100, 0b00110000, 0b00001100, 0b11110000, 0b11000000, 0b11000110, 0b11110110, 0b11001100) + _(0x48, 0xa, 0b11111100, 0b00110000, 0b00001100, 0b11011000, 0b11000000, 0b11000110, 0b11011110, 0b11001100) + _(0x48, 0xb, 0b11001100, 0b00110000, 0b00001100, 0b11011000, 0b11000000, 0b11000110, 0b11011110, 0b11001100) + _(0x48, 0xc, 0b11001100, 0b00110000, 0b11001100, 0b11011000, 0b11000000, 0b11000110, 0b11011110, 0b11001100) + _(0x48, 0xd, 0b11001100, 0b00110000, 0b11001100, 0b11001100, 0b11000000, 0b11000110, 0b11001110, 0b11001100) + _(0x48, 0xe, 0b11001100, 0b11111100, 0b11111100, 0b11001100, 0b11111100, 0b11000110, 0b11001110, 0b11111100) + _(0x48, 0xf, 0b11001100, 0b11111100, 0b01111000, 0b11001100, 0b01111100, 0b11000110, 0b11001110, 0b11111100) + + _(0x50, 0x0, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x50, 0x1, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x50, 0x2, 0b11111100, 0b01111000, 0b11111000, 0b01111000, 0b11111100, 0b11001100, 0b11001100, 0b11000110) + _(0x50, 0x3, 0b11111100, 0b11111100, 0b11001100, 0b11111100, 0b11111100, 0b11001100, 0b11001100, 0b11000110) + _(0x50, 0x4, 0b11001100, 0b11001100, 0b11001100, 0b11000000, 0b00110000, 0b11001100, 0b11001100, 0b11000110) + _(0x50, 0x5, 0b11001100, 0b11001100, 0b11001100, 0b11000000, 0b00110000, 0b11001100, 0b11001100, 0b11000110) + _(0x50, 0x6, 0b11001100, 0b11001100, 0b11001100, 0b11000000, 0b00110000, 0b11001100, 0b11001100, 0b11000110) + _(0x50, 0x7, 0b11001100, 0b11001100, 0b11001100, 0b11000000, 0b00110000, 0b11001100, 0b01001000, 0b11000110) + _(0x50, 0x8, 0b11001100, 0b11001100, 0b11001100, 0b11111000, 0b00110000, 0b11001100, 0b01001000, 0b11000110) + _(0x50, 0x9, 0b11111100, 0b11001100, 0b11111100, 0b01111100, 0b00110000, 0b11001100, 0b01001000, 0b11000110) + _(0x50, 0xa, 0b11111100, 0b11001100, 0b11111000, 0b00001100, 0b00110000, 0b11001100, 0b01111000, 0b11000110) + _(0x50, 0xb, 0b11000000, 0b11101100, 0b11011000, 0b00001100, 0b00110000, 0b11001100, 0b01111000, 0b11010110) + _(0x50, 0xc, 0b11000000, 0b11111100, 0b11011000, 0b00001100, 0b00110000, 0b11001100, 0b00110000, 0b11010110) + _(0x50, 0xd, 0b11000000, 0b01111000, 0b11001100, 0b00001100, 0b00110000, 0b11001100, 0b00110000, 0b11010110) + _(0x50, 0xe, 0b11000000, 0b00011100, 0b11001100, 0b11111100, 0b00110000, 0b11111100, 0b00110000, 0b11111110) + _(0x50, 0xf, 0b11000000, 0b00001100, 0b11001100, 0b01111000, 0b00110000, 0b11111100, 0b00110000, 0b01101100) + + _(0x58, 0x0, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x58, 0x1, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x58, 0x2, 0b11001100, 0b11001100, 0b11111100, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x58, 0x3, 0b11001100, 0b11001100, 0b11111100, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x58, 0x4, 0b11001100, 0b11001100, 0b00001100, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x58, 0x5, 0b01111000, 0b11001100, 0b00001100, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x58, 0x6, 0b01111000, 0b01111000, 0b00011000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x58, 0x7, 0b01111000, 0b01111000, 0b00011000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x58, 0x8, 0b00110000, 0b01111000, 0b00011000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x58, 0x9, 0b00110000, 0b01111000, 0b00110000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x58, 0xa, 0b01111000, 0b00110000, 0b00110000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x58, 0xb, 0b01111000, 0b00110000, 0b00110000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x58, 0xc, 0b01111000, 0b00110000, 0b01100000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x58, 0xd, 0b11001100, 0b00110000, 0b01100000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x58, 0xe, 0b11001100, 0b00110000, 0b11111100, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x58, 0xf, 0b11001100, 0b00110000, 0b11111100, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + + _(0x60, 0x0, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x60, 0x1, 0b11100000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x60, 0x2, 0b11110000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x60, 0x3, 0b01111000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x60, 0x4, 0b00111000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x60, 0x5, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x60, 0x6, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x60, 0x7, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x60, 0x8, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x60, 0x9, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x60, 0xa, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x60, 0xb, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x60, 0xc, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x60, 0xd, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x60, 0xe, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x60, 0xf, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + + _(0x68, 0x0, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x68, 0x1, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x68, 0x2, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x68, 0x3, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x68, 0x4, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x68, 0x5, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x68, 0x6, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x68, 0x7, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x68, 0x8, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x68, 0x9, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x68, 0xa, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x68, 0xb, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x68, 0xc, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x68, 0xd, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x68, 0xe, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x68, 0xf, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + + _(0x70, 0x0, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x70, 0x1, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x70, 0x2, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x70, 0x3, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x70, 0x4, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x70, 0x5, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x70, 0x6, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x70, 0x7, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x70, 0x8, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x70, 0x9, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x70, 0xa, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x70, 0xb, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x70, 0xc, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x70, 0xd, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x70, 0xe, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x70, 0xf, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + + _(0x78, 0x0, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x78, 0x1, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x78, 0x2, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x78, 0x3, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x78, 0x4, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x78, 0x5, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x78, 0x6, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x78, 0x7, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x78, 0x8, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x78, 0x9, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x78, 0xa, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x78, 0xb, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x78, 0xc, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x78, 0xd, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x78, 0xe, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x78, 0xf, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + + _(0x80, 0x0, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x80, 0x1, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x80, 0x2, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x80, 0x3, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x80, 0x4, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x80, 0x5, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x80, 0x6, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x80, 0x7, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x80, 0x8, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x80, 0x9, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x80, 0xa, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x80, 0xb, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x80, 0xc, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x80, 0xd, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x80, 0xe, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x80, 0xf, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + + _(0x88, 0x0, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x88, 0x1, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x88, 0x2, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x88, 0x3, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x88, 0x4, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x88, 0x5, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x88, 0x6, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x88, 0x7, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x88, 0x8, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x88, 0x9, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x88, 0xa, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x88, 0xb, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x88, 0xc, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x88, 0xd, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x88, 0xe, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x88, 0xf, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + + _(0x90, 0x0, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x90, 0x1, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x90, 0x2, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x90, 0x3, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x90, 0x4, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x90, 0x5, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x90, 0x6, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x90, 0x7, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x90, 0x8, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x90, 0x9, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x90, 0xa, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x90, 0xb, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x90, 0xc, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x90, 0xd, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x90, 0xe, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x90, 0xf, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + + _(0x98, 0x0, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x98, 0x1, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x98, 0x2, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x98, 0x3, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x98, 0x4, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x98, 0x5, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x98, 0x6, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x98, 0x7, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x98, 0x8, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x98, 0x9, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x98, 0xa, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x98, 0xb, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x98, 0xc, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x98, 0xd, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x98, 0xe, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0x98, 0xf, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + + _(0xa0, 0x0, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xa0, 0x1, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xa0, 0x2, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xa0, 0x3, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xa0, 0x4, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xa0, 0x5, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xa0, 0x6, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xa0, 0x7, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xa0, 0x8, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xa0, 0x9, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xa0, 0xa, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xa0, 0xb, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xa0, 0xc, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xa0, 0xd, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xa0, 0xe, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xa0, 0xf, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + + _(0xa8, 0x0, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xa8, 0x1, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xa8, 0x2, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xa8, 0x3, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xa8, 0x4, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xa8, 0x5, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xa8, 0x6, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xa8, 0x7, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xa8, 0x8, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xa8, 0x9, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xa8, 0xa, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xa8, 0xb, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xa8, 0xc, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xa8, 0xd, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xa8, 0xe, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xa8, 0xf, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + + _(0xb0, 0x0, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xb0, 0x1, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xb0, 0x2, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xb0, 0x3, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xb0, 0x4, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xb0, 0x5, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xb0, 0x6, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xb0, 0x7, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xb0, 0x8, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xb0, 0x9, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xb0, 0xa, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xb0, 0xb, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xb0, 0xc, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xb0, 0xd, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xb0, 0xe, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xb0, 0xf, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + + _(0xb8, 0x0, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xb8, 0x1, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xb8, 0x2, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xb8, 0x3, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xb8, 0x4, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xb8, 0x5, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xb8, 0x6, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xb8, 0x7, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xb8, 0x8, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xb8, 0x9, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xb8, 0xa, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xb8, 0xb, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xb8, 0xc, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xb8, 0xd, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xb8, 0xe, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xb8, 0xf, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + + _(0xc0, 0x0, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xc0, 0x1, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xc0, 0x2, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xc0, 0x3, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xc0, 0x4, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xc0, 0x5, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xc0, 0x6, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xc0, 0x7, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xc0, 0x8, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xc0, 0x9, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xc0, 0xa, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xc0, 0xb, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xc0, 0xc, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xc0, 0xd, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xc0, 0xe, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xc0, 0xf, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + + _(0xc8, 0x0, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xc8, 0x1, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xc8, 0x2, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xc8, 0x3, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xc8, 0x4, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xc8, 0x5, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xc8, 0x6, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xc8, 0x7, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xc8, 0x8, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xc8, 0x9, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xc8, 0xa, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xc8, 0xb, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xc8, 0xc, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xc8, 0xd, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xc8, 0xe, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xc8, 0xf, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + + _(0xd0, 0x0, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xd0, 0x1, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xd0, 0x2, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xd0, 0x3, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xd0, 0x4, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xd0, 0x5, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xd0, 0x6, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xd0, 0x7, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xd0, 0x8, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xd0, 0x9, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xd0, 0xa, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xd0, 0xb, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xd0, 0xc, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xd0, 0xd, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xd0, 0xe, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xd0, 0xf, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + + _(0xd8, 0x0, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xd8, 0x1, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xd8, 0x2, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xd8, 0x3, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xd8, 0x4, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xd8, 0x5, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xd8, 0x6, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xd8, 0x7, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xd8, 0x8, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xd8, 0x9, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xd8, 0xa, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xd8, 0xb, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xd8, 0xc, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xd8, 0xd, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xd8, 0xe, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xd8, 0xf, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + + _(0xe0, 0x0, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xe0, 0x1, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xe0, 0x2, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xe0, 0x3, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xe0, 0x4, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xe0, 0x5, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xe0, 0x6, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xe0, 0x7, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xe0, 0x8, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xe0, 0x9, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xe0, 0xa, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xe0, 0xb, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xe0, 0xc, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xe0, 0xd, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xe0, 0xe, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xe0, 0xf, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + + _(0xe8, 0x0, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xe8, 0x1, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xe8, 0x2, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xe8, 0x3, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xe8, 0x4, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xe8, 0x5, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xe8, 0x6, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xe8, 0x7, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xe8, 0x8, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xe8, 0x9, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xe8, 0xa, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xe8, 0xb, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xe8, 0xc, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xe8, 0xd, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xe8, 0xe, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xe8, 0xf, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + + _(0xf0, 0x0, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xf0, 0x1, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xf0, 0x2, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xf0, 0x3, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xf0, 0x4, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xf0, 0x5, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xf0, 0x6, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xf0, 0x7, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xf0, 0x8, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xf0, 0x9, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xf0, 0xa, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xf0, 0xb, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xf0, 0xc, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xf0, 0xd, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xf0, 0xe, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xf0, 0xf, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + + _(0xf8, 0x0, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xf8, 0x1, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xf8, 0x2, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xf8, 0x3, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xf8, 0x4, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xf8, 0x5, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xf8, 0x6, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xf8, 0x7, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xf8, 0x8, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xf8, 0x9, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xf8, 0xa, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xf8, 0xb, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xf8, 0xc, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xf8, 0xd, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xf8, 0xe, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) + _(0xf8, 0xf, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000) +}; + +// -- Device prototype -- +struct VgaSBDevice { + // Ports + u16 MiscOutputRegisterReadPort; + u16 MiscOutputRegisterWritePort; + + u16 GraphicsRegisterIndexPort; + u16 GraphicsRegisterDataPort; + + u16 AttributeRegisterIndexPort; + u16 AttributeRegisterDataPort; + + u16 CrtRegisterIndexPort; + u16 CrtRegisterDataPort; + + u16 SequencerRegisterIndexPort; + u16 SequencerRegisterDataPort; + + u16 DacWritePort; + u16 DacReadPort; + u16 DacDataPort; + + volatile c8* Plane0; +}; + +void VgaSBDeviceTMDC_I_TweakGenericRegister(u8 Read, u8 Write, u8 Value, u8 Mask) { + u8 Reg = PortRead8(Read); + Reg &= ~Mask; + Reg |= Value & Mask; + PortWrite8(Write, Reg); +} + +void VgaSBDeviceTMDC_I_WriteGraphicsRegister(struct SysbusDevice* Device, u8 Index, u8 Value) { + struct VgaSBDevice* Data = Device->DeviceData; + + PortWrite8(Data->GraphicsRegisterIndexPort, Index); + PortWrite8(Data->GraphicsRegisterDataPort, Value); + + return; +} + +u8 VgaSBDeviceTMDC_I_ReadGraphicsRegister(struct SysbusDevice* Device, u8 Index) { + struct VgaSBDevice* Data = Device->DeviceData; + + PortWrite8(Data->GraphicsRegisterIndexPort, Index); + + return PortRead8(Data->GraphicsRegisterDataPort); +} + +void VgaSBDeviceTMDC_I_TweakGraphicsRegister(struct SysbusDevice* Device, u8 Index, u8 Value, u8 Mask) { + u8 Reg = VgaSBDeviceTMDC_I_ReadGraphicsRegister(Device, Index); + Reg &= ~Mask; + Reg |= Value & Mask; + VgaSBDeviceTMDC_I_WriteGraphicsRegister(Device, Index, Reg); +} + +void VgaSBDeviceTMDC_I_WriteInternalPalette(struct SysbusDevice* Device, u8 Index, u8 Value) { + struct VgaSBDevice* Data = Device->DeviceData; + + // bit 5 being set to 0 makes the attribute register fetch info from + // the internal palette, it's a really strange design but i suppose it + // makes sense since you don't want to use too many io ports, it also + // has the same address and data ports + PortWrite8(Data->AttributeRegisterIndexPort, (Index & 0x1f)); + PortWrite8(Data->AttributeRegisterIndexPort, Value); + + return; +} + +u8 VgaSBDeviceTMDC_I_ReadInternalPalette(struct SysbusDevice* Device, u8 Index) { + struct VgaSBDevice* Data = Device->DeviceData; + + PortWrite8(Data->AttributeRegisterIndexPort, (Index & 0x1f)); + + return PortRead8(Data->AttributeRegisterDataPort); +} + +void VgaSBDeviceTMDC_I_WriteAttributeRegister(struct SysbusDevice* Device, u8 Index, u8 Value) { + struct VgaSBDevice* Data = Device->DeviceData; + + PortWrite8(Data->AttributeRegisterIndexPort, (Index & 0x1f) | 0x20); + PortWrite8(Data->AttributeRegisterIndexPort, Value); + + return; +} + +u8 VgaSBDeviceTMDC_I_ReadAttributeRegister(struct SysbusDevice* Device, u8 Index) { + struct VgaSBDevice* Data = Device->DeviceData; + + PortWrite8(Data->AttributeRegisterIndexPort, (Index & 0x1f) | 0x20); + + return PortRead8(Data->AttributeRegisterDataPort); +} + +void VgaSBDeviceTMDC_I_TweakAttributeRegister(struct SysbusDevice* Device, u8 Index, u8 Value, u8 Mask) { + u8 Reg = VgaSBDeviceTMDC_I_ReadAttributeRegister(Device, Index); + Reg &= ~Mask; + Reg |= Value & Mask; + VgaSBDeviceTMDC_I_WriteAttributeRegister(Device, Index, Reg); +} + +void VgaSBDeviceTMDC_I_WriteCrtRegister(struct SysbusDevice* Device, u8 Index, u8 Value) { + struct VgaSBDevice* Data = Device->DeviceData; + + PortWrite8(Data->CrtRegisterIndexPort, Index); + PortWrite8(Data->CrtRegisterDataPort, Value); + + return; +} + +u8 VgaSBDeviceTMDC_I_ReadCrtRegister(struct SysbusDevice* Device, u8 Index) { + struct VgaSBDevice* Data = Device->DeviceData; + + PortWrite8(Data->CrtRegisterIndexPort, Index); + + return PortRead8(Data->CrtRegisterDataPort); +} + +void VgaSBDeviceTMDC_I_TweakCrtRegister(struct SysbusDevice* Device, u8 Index, u8 Value, u8 Mask) { + u8 Reg = VgaSBDeviceTMDC_I_ReadCrtRegister(Device, Index); + Reg &= ~Mask; + Reg |= Value & Mask; + VgaSBDeviceTMDC_I_WriteCrtRegister(Device, Index, Reg); +} + +void VgaSBDeviceTMDC_I_WriteSequencerRegister(struct SysbusDevice* Device, u8 Index, u8 Value) { + struct VgaSBDevice* Data = Device->DeviceData; + + PortWrite8(Data->SequencerRegisterIndexPort, Index); + PortWrite8(Data->SequencerRegisterDataPort, Value); + + return; +} + +u8 VgaSBDeviceTMDC_I_ReadSequencerRegister(struct SysbusDevice* Device, u8 Index) { + struct VgaSBDevice* Data = Device->DeviceData; + + PortWrite8(Data->SequencerRegisterIndexPort, Index); + + return PortRead8(Data->SequencerRegisterDataPort); +} + +void VgaSBDeviceTMDC_I_TweakSequencerRegister(struct SysbusDevice* Device, u8 Index, u8 Value, u8 Mask) { + u8 Reg = VgaSBDeviceTMDC_I_ReadSequencerRegister(Device, Index); + Reg &= ~Mask; + Reg |= Value & Mask; + VgaSBDeviceTMDC_I_WriteSequencerRegister(Device, Index, Reg); +} + +void VgaSBDeviceTMDC_I_WriteDacColor(struct SysbusDevice* Device, u8 Color, u8 Red, u8 Green, u8 Blue) { + struct VgaSBDevice* Data = Device->DeviceData; + + PortWrite8(Data->DacWritePort, Color); + PortWrite8(Data->DacDataPort, Red >> 2); + PortWrite8(Data->DacDataPort, Green >> 2); + PortWrite8(Data->DacDataPort, Blue >> 2); +} + +s32 VgaSBDeviceTMDC_Enable(struct SysbusDevice* Device) { + return 0; +} + +void VgaSBDeviceTMDC_Reset_RealStub(void*) { + return; +} + +s32 VgaSBDeviceTMDC_Reset(struct SysbusDevice* Device) { + struct VgaSBDevice* Data = Device->DeviceData; + + // Enable display buffer + VgaSBDeviceTMDC_I_TweakGenericRegister(Data->MiscOutputRegisterReadPort, Data->MiscOutputRegisterWritePort, 0x02, 0x02); + + // Disable monochrome adapter compatibility (move ports to expected locations) + VgaSBDeviceTMDC_I_TweakGenericRegister(Data->MiscOutputRegisterReadPort, Data->MiscOutputRegisterWritePort, 0x01, 0x01); + + // Switch the graphics controller into alphanumeric mode and map VRAM to 0xA0000-0xBFFFF + VgaSBDeviceTMDC_I_TweakGraphicsRegister(Device, 0x06, 0x00 | 0x00, 0x01 | 0x0c); + + // Unprotect CRT registers + VgaSBDeviceTMDC_I_TweakCrtRegister(Device, 0x11, 0x00, 0x80); + + // Set character height to uh... 16 + VgaSBDeviceTMDC_I_TweakCrtRegister(Device, 0x09, 0x0f, 0x1f); + + // Character width can be like uhm... 8 + VgaSBDeviceTMDC_I_TweakSequencerRegister(Device, 0x01, 0x01, 0x01); + + // Lets go with 80 characters per line + VgaSBDeviceTMDC_I_WriteCrtRegister(Device, 0x01, 80 - 1); + + // How about 25 columns... a classic! everything supports it. + VgaSBDeviceTMDC_I_WriteCrtRegister(Device, 0x12, (16 * 25) & 0xff); + VgaSBDeviceTMDC_I_TweakCrtRegister(Device, 0x07, ((16 * 25) & 0x100) ? 2 : 0, 0x42); + + // Each line is 80 bytes long, 80 / 2... + VgaSBDeviceTMDC_I_WriteCrtRegister(Device, 0x13, 40); + + // Clear upper bits from DAC value + VgaSBDeviceTMDC_I_TweakAttributeRegister(Device, 0x14, 0x00, 0x0f); + + // Lets enable every color plane, i can't find any documentation on what it does but i suppose it enables the RGB values + VgaSBDeviceTMDC_I_WriteAttributeRegister(Device, 0x12, 0xf); + + // Colors + //VgaSBDeviceTMDC_I_WriteDacColor(Device, 16, 0, 0, 0); + + // Set overscan color to 16 + VgaSBDeviceTMDC_I_WriteAttributeRegister(Device, 0x11, 0); + + // Unlock memory planes 0, 1 and 2 + VgaSBDeviceTMDC_I_TweakSequencerRegister(Device, 0x02, 0x07, 0x0f); + + // Select font 0 for charsets A and B + VgaSBDeviceTMDC_I_TweakSequencerRegister(Device, 0x03, 0x00, 0x3f); + + // Disable odd-even mode + VgaSBDeviceTMDC_I_TweakSequencerRegister(Device, 0x04, 0x04, 0x04); + VgaSBDeviceTMDC_I_TweakGraphicsRegister(Device, 0x05, 0x00, 0x10); + VgaSBDeviceTMDC_I_TweakGraphicsRegister(Device, 0x06, 0x00, 0x02); + + // Select write mode 0 + VgaSBDeviceTMDC_I_TweakGraphicsRegister(Device, 0x05, 0x00, 0x03); + + // Derive data from memory + VgaSBDeviceTMDC_I_TweakGraphicsRegister(Device, 0x00, 0x00, 0x0f); + + // Don't rotate data + VgaSBDeviceTMDC_I_TweakGraphicsRegister(Device, 0x03, 0x00, 0x07); + + // Don't do any transformations on the data + VgaSBDeviceTMDC_I_TweakGraphicsRegister(Device, 0x03, 0x00, 0x18); + + // Bitmask + VgaSBDeviceTMDC_I_TweakGraphicsRegister(Device, 0x08, 0xff, 0xff); + + // Only write to plane 2 + VgaSBDeviceTMDC_I_TweakSequencerRegister(Device, 0x02, 0x04, 0x0f); + + // Load font 0 + for (int i = 0; i < 256; i++) { + for (int j = 0; j < 32; j++) { + Data->Plane0[i * 32 + j] = VgaFont[i][j]; + } + } + + // Only write to plane 0 and 1 + VgaSBDeviceTMDC_I_TweakSequencerRegister(Device, 0x02, 0x03, 0x0f); + + // Map VRAM to 0xB8000-0xBFFFF + VgaSBDeviceTMDC_I_TweakGraphicsRegister(Device, 0x06, 0x0c, 0x0c); + + // Set VRAM start address to start of VRAM + VgaSBDeviceTMDC_I_WriteCrtRegister(Device, 0x0D, 0); + VgaSBDeviceTMDC_I_WriteCrtRegister(Device, 0x0C, 0); + + // Ensure chain mode is off + VgaSBDeviceTMDC_I_TweakGraphicsRegister(Device, 0x04, 0x08, 0x00); + + // Enable odd/even mode + VgaSBDeviceTMDC_I_TweakGraphicsRegister(Device, 0x05, 0x10, 0x10); + VgaSBDeviceTMDC_I_TweakGraphicsRegister(Device, 0x06, 0x02, 0x02); + VgaSBDeviceTMDC_I_TweakSequencerRegister(Device, 0x04, 0x00, 0x04); + + return 0; +} + +s32 VgaSBDeviceTMDC_GetPaletteSize(struct SysbusDevice* Device) { + return 15; +} + +s32 VgaSBDeviceTMDC_SetPaletteColor(struct SysbusDevice* Device, u32 ID, u8 Red, u8 Green, u8 Blue) { + if (ID >= 16) return -1; + + VgaSBDeviceTMDC_I_WriteDacColor(Device, ID, Red, Green, Blue); + VgaSBDeviceTMDC_I_WriteInternalPalette(Device, ID, ID); + VgaSBDeviceTMDC_I_WriteAttributeRegister(Device, 0x12, 0xf); + + return 0; +} + +s32 VgaSBDeviceTMDC_SetCharacter(struct SysbusDevice* Device, u32 Row, u32 Col, c8 Char, u32 FG, u32 BG) { + if (Row > 25 || Col > 80) return -1; + + struct VgaSBDevice* Data = Device->DeviceData; + + Data->Plane0[0x18000 + (Row * 80 + Col) * 2 ] = Char; + Data->Plane0[0x18000 + (Row * 80 + Col) * 2 + 1] = ((FG & 0xf) << 4) | (BG & 0xf); + + return 0; +} + +struct TextModeDisplayCapability VgaSBDeviceTextModeDisplayCapability = { + .Enable = VgaSBDeviceTMDC_Enable, + .Reset = VgaSBDeviceTMDC_Reset, + .GetPaletteSize = VgaSBDeviceTMDC_GetPaletteSize, + .SetPaletteColor = VgaSBDeviceTMDC_SetPaletteColor, + .SetCharacter = VgaSBDeviceTMDC_SetCharacter +}; + +struct SysbusDeviceDescription* VgaSBDevice = 0; + +s32 VgaSBDevice_Create(struct SysbusDevice* Device, void* Data) { + struct VgaSBDevice* UData = KernelHeapAlloc(sizeof(struct VgaSBDevice), 1, KHA_ZERO); + UData->MiscOutputRegisterReadPort = 0x03cc; + UData->MiscOutputRegisterWritePort= 0x03c2; + UData->GraphicsRegisterIndexPort = 0x03ce; + UData->GraphicsRegisterDataPort = 0x03cf; + UData->AttributeRegisterIndexPort = 0x03c0; + UData->AttributeRegisterDataPort = 0x03c1; + UData->CrtRegisterIndexPort = 0x03d4; + UData->CrtRegisterDataPort = 0x03d5; + UData->SequencerRegisterIndexPort = 0x03c4; + UData->SequencerRegisterDataPort = 0x03c5; + UData->DacWritePort = 0x03c8; + UData->DacReadPort = 0x03c7; + UData->DacDataPort = 0x03c9; + UData->Plane0 = (c8*)0xa0000; + Device->DeviceData = UData; + + return 0; +} + +s32 VgaSBDevice_Delete(struct SysbusDevice* Device) { + KernelHeapFree(Device->DeviceData); + + return 0; +} + +void* VgaSBDevice_GetCapability(struct SysbusDevice* Device, struct SysbusDeviceCapability* Capability) { + if (Capability == TextModeDisplayCapabilityGetCapability()) { + return &VgaSBDeviceTextModeDisplayCapability; + } else return 0; +} + +// -- Device creation/destruction -- +bool VgaInitialized = false; +bool VgaIsInitialized() { return VgaInitialized; } + +void VgaInitialize() { + if (!TextModeDisplayCapabilityIsInitialized()) { + TextModeDisplayCapabilityInitialize(); + } + + VgaSBDevice = SysbusCreateDeviceDescription(); + VgaSBDevice->DeviceName = "VGA Compatible Device"; + VgaSBDevice->CreateDevice = VgaSBDevice_Create; + VgaSBDevice->DeleteDevice = VgaSBDevice_Delete; + VgaSBDevice->GetCapability = VgaSBDevice_GetCapability; + + VgaInitialized = true; +} + +struct SysbusDevice* VgaCreateDevice(struct SysbusDevice* Parent) { + return SysbusCreateDevice(VgaSBDevice, Parent, NULL); +} + +void VgaDeleteDevice(struct SysbusDevice* Device) { + SysbusDeleteDevice(Device); +} diff --git a/lcrash/driver/vga.h b/lcrash/driver/vga.h new file mode 100644 index 0000000..dfcba20 --- /dev/null +++ b/lcrash/driver/vga.h @@ -0,0 +1,24 @@ +#pragma once + +#include +#include + +/** + * Initialize the VGA driver + */ +void VgaInitialize(); + +/** + * Vga drivers are ready + */ +bool VgaIsInitialized(); + +/** + * Create a legacy VGA device, due to how VGA works, only one may exist at a time :D + */ +struct SysbusDevice* VgaCreateDevice(struct SysbusDevice* Parent); + +/** + * Delete a legacy VGA device + */ +void VgaDeleteDevice(struct SysbusDevice* Device); diff --git a/lcrash/irq.c b/lcrash/irq.c new file mode 100644 index 0000000..14715ed --- /dev/null +++ b/lcrash/irq.c @@ -0,0 +1,180 @@ +#include + +#include +#include + +#define PICMCMD 0x0020 +#define PICMDAT 0x0021 +#define PICSCMD 0x00A0 +#define PICSDAT 0x00A1 + +struct IrqHandlerGate { + /// Gate number + u8 GateNumber; + + /// Hooks + struct IrqHandlerHook* Hooks; +}; + +struct [[gnu::packed]] IrqHandlerDescriptor { + u16 Offset0; + u16 Segment; + u16 Flags; + u16 Offset1; + u32 Offset2; + u32 Reserved; +}; + +struct [[gnu::packed]] IrqHandlerIDTR { + u16 Length; + struct IrqHandlerDescriptor* Offset; +}; + +struct IrqHandlerInterruptFrame { + u64 PrevInstructionAddress; + u64 PrevInstructionSegment; + u64 PrevFlags; + u64 PrevStackAddress; + u64 PrevStackSegment; +}; + +struct IrqHandlerGate IrqHandlerGates[256] = {}; + +[[gnu::aligned(16)]] +struct IrqHandlerDescriptor IrqHandlerDescriptors[256] = {}; + +/// Check for spurious IRQs +bool IrqHandlerCheckRealIRQ(u64 Interrupt) { + if (Interrupt == 0x27) { + PortWrite8(PICMCMD, 0x0B); // RDISR + if (PortRead8(PICMDAT) & 0x80) return false; + } + + if (Interrupt >= 0x28 && Interrupt <= 0x2f) { + PortWrite8(PICSCMD, 0x0B); // RDISR + if (PortRead8(PICSDAT) & 0x80) { + PortWrite8(PICMCMD, 0x20); + return false; + } + } + + return true; +} + +/// Send an EOI to the PIC +void IrqHandlerSendEOI(u64 Interrupt) { + if (Interrupt >= 0x20 && Interrupt < 0x30) { + if (Interrupt >= 0x28) PortWrite8(PICSCMD, 0x20); // EOI + PortWrite8(PICMCMD, 0x20); // EOI + } +} + +/// Handle an interrupt +[[gnu::target("general-regs-only")]] +void IrqHandlerHandleInterrupt(struct IrqHandlerInterruptFrame* Frame, u64 Interrupt) { + // Panic("Got interrupt"); + + IrqHandlerSendEOI(Interrupt); + + return; +} + +/// Handle an exception +[[gnu::target("general-regs-only")]] +void IrqHandlerHandleException(struct IrqHandlerInterruptFrame* Frame, u64 ErrorCode, u64 Interrupt) { + //Panic("Got exception"); + + IrqHandlerSendEOI(Interrupt); + + return; +} + +s32 IrqHandlerInitialize() { + extern int IrqHandlerISRTable; + void* ISRTable = &IrqHandlerISRTable; + + // Table stating if an interrupt is an error or not + bool Error[256] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 1, 1, 1, 1, 1, 0, + 0, 1, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + }; + + // Fill IDT + for (int i = 0; i < 256; i++) { + u64 Offset = (u64)ISRTable; + + IrqHandlerDescriptors[i].Segment = 0x10; // TODO: This shouldnt be hardcoded + IrqHandlerDescriptors[i].Flags = Error[i] ? 0x8F00 : 0x8E00; + IrqHandlerDescriptors[i].Offset0 = Offset & 0xffff; + IrqHandlerDescriptors[i].Offset1 = (Offset >> 16) & 0xffff; + IrqHandlerDescriptors[i].Offset2 = Offset >> 32 & 0xffffffff; + + ISRTable += 0x20; + } + + // Load the IDT + struct IrqHandlerIDTR IDTR; + IDTR.Offset = IrqHandlerDescriptors; + IDTR.Length = 256 * 16 - 1; + asm ("lidt %0" :: "m" (IDTR)); + + // Drop to assembly and do a long jump to get our IRQ's working + asm ("call IrqHandlerApplyStateChange"); + + // TODO: Disable APIC until APIC support is added + + // Reconfigure legacy PIC (TODO: Switch to APIC) + PortWrite8(PICMCMD, 0x11); // Initialize / cascade + PortWrite8(PICSCMD, 0x11); + PortWrite8(PICMDAT, 0x20); // Map master PIC IRQs to 0x20-0x27 + PortWrite8(PICSDAT, 0x28); // Map slave PIC IRQS to 0x28-0x2f + PortWrite8(PICMDAT, 0x04); // Slave at IRQ2 + PortWrite8(PICSDAT, 0x02); // Slave ID 2 + PortWrite8(PICMDAT, 0x01); // Switch to 8086 mode + PortWrite8(PICSDAT, 0x01); + PortWrite8(PICMDAT, 0x01); // Respect all external interrupts except the PIC timer because its fucking stupid + PortWrite8(PICSDAT, 0x00); + + return 0; +} + +void IrqHandlerEnableInterrupts() { asm ("sti"); } +void IrqHandlerDisableInterrupts() { asm ("cli"); } + +s32 IrqHandlerAttach(u8 Gate, struct IrqHandlerHook* Hook) { + return -1; +} + +s32 IrqHandlerDetach(struct IrqHandlerHook* Hook) { + return -1; +} diff --git a/lcrash/irq.h b/lcrash/irq.h new file mode 100644 index 0000000..ee4b45d --- /dev/null +++ b/lcrash/irq.h @@ -0,0 +1,62 @@ +#pragma once + +#include + +/** + * A specific IRQ gate + * \internal + */ +struct IrqHandlerGate; + +/** + * A hook called on an interrupt + */ +struct IrqHandlerHook { + /// Higher priority values called first + u32 Priority; + + /** + * The hook itself. + * + * \return 1 to cancel uncalled hooks + * 0 on success + * -1 on failure + */ + s32 (*HookCall)(); + + /** + * Next hook + * \internal + */ + struct IrqHandlerHook* Next; + + /** + * Attached gate + * \internal + */ + struct IrqHandlerGate* Gate; +}; + +/** + * Initialize the IRQ handler + * + * \return 0 on success + */ +s32 IrqHandlerInitialize(); + +/** + * Hook an interrupt + * + * \return 0 on success + */ +s32 IrqHandlerAttach(u8 Gate, struct IrqHandlerHook* Hook); + +/** + * Remove a hook + * + * \return 0 on success + */ +s32 IrqHandlerDetach(struct IrqHandlerHook* Hook); + +void IrqHandlerDisableInterrupts(); +void IrqHandlerEnableInterrupts(); diff --git a/lcrash/irq.s b/lcrash/irq.s new file mode 100644 index 0000000..4260305 --- /dev/null +++ b/lcrash/irq.s @@ -0,0 +1,111 @@ + .align 0x1000 + .global IrqHandlerApplyStateChange + .local a +IrqHandlerApplyStateChange: + push %r14 + push %r15 + + // Disable interrupts + cli + + // Get pointer to IrqHandlerApplyStateChange + lea (%rip), %r15 +a: sub $(a - IrqHandlerApplyStateChange), %r15 + + // Get pointer to IrqHandlerApplyStateChangeReprotect + mov %r15, %r14 + add $(IrqHandlerApplyStateChangeFinish - IrqHandlerApplyStateChange), %r14 + + // Jump far + sub $6, %rsp + movl %r14d, (%rsp) + movw %cs, 4(%rsp) + .code32 // HACK: This isn't correct it's valid in 64-bit mode, but GAS doesn't seem to agree + ljmp *(%esp) + .code64 + .local IrqHandlerApplyStateChangeFinish +IrqHandlerApplyStateChangeFinish: + // Fix registers + add $6, %rsp + pop %r15 + pop %r14 + + // Enable interrupts + // sti + + // Return + ret + + +// Generate IRQ handlers +.macro gen_irqh int, err + .set pta, . + + // Disable interrupts + cli + + // Call the thing + .if \err + popq %rsi + movq %rsp, %rdi + movq $\int, %rdx + call IrqHandlerHandleException + .else + movq %rsp, %rdi + movq $\int, %rsi + call IrqHandlerHandleInterrupt + .endif + + // Re-enable interrupts + sti + + // Goodbye :3 + iretq + + // Pad area + .if (0x20 - (. - pta)) < 0 + .error "IRQ Handler is too long" + .elseif (0x20 - (. - pta)) > 0 + .zero 0x20 - (. - pta) + .endif +.endm + + .global IrqHandlerISRTable +IrqHandlerISRTable: + gen_irqh 0, 0 + gen_irqh 1, 0 + gen_irqh 2, 0 + gen_irqh 3, 0 + gen_irqh 4, 0 + gen_irqh 5, 0 + gen_irqh 6, 0 + gen_irqh 7, 0 + gen_irqh 8, 1 + gen_irqh 9, 0 + gen_irqh 10, 1 + gen_irqh 11, 1 + gen_irqh 12, 1 + gen_irqh 13, 1 + gen_irqh 14, 1 + gen_irqh 15, 0 + gen_irqh 16, 0 + gen_irqh 17, 1 + gen_irqh 18, 0 + gen_irqh 19, 0 + gen_irqh 20, 0 + gen_irqh 21, 1 + gen_irqh 22, 0 + gen_irqh 23, 0 + gen_irqh 24, 0 + gen_irqh 25, 0 + gen_irqh 26, 0 + gen_irqh 27, 0 + gen_irqh 28, 0 + gen_irqh 29, 1 + gen_irqh 30, 1 + gen_irqh 31, 0 + .equ i, 32 + .rept 256 - 32 + gen_irqh i, 0 + .equ i, i + 1 + .endr diff --git a/lcrash/main.c b/lcrash/main.c index d487498..b34e98d 100644 --- a/lcrash/main.c +++ b/lcrash/main.c @@ -9,12 +9,84 @@ #include #include #include +#include +#include #include "types.h" #include "lnxboot.h" #include "efi/efi.h" +struct SysbusDevice* TryFindScreen(struct SysbusDevice* Device) { + if (SysbusGetCapability(Device, TextModeDisplayCapabilityGetCapability()) != NULL) { + return Device; + } + + for (int i = 0; i < Device->ChildCount; i++) { + struct SysbusDevice* ChildDevice = TryFindScreen(Device->Children[i]); + + if (ChildDevice != NULL) return ChildDevice; + } + + return NULL; +} + +/** + * Fill a screen range with a character. + * Positions are 1-indexed + */ +void FillScreenCharRange(struct SysbusDevice* Device, struct TextModeDisplayCapability* TMDC, u32 R0, u32 C0, u32 R1, u32 C1, c8 Char, u32 FG, u32 BG) { + R0 -= 1; + R1 -= 1; + C0 -= 1; + C1 -= 1; + + for (int r = R0; r <= R1; r++) { + for (int c = C0; c <= C1; c++) { + TMDC->SetCharacter(Device, r, c, Char, FG, BG); + } + } +} + +/** + * Draw text at a location + * Positions are 1-indexed + */ +void DrawTextBox(struct SysbusDevice* Device, struct TextModeDisplayCapability* TMDC, u32 R0, u32 C0, u32 R1, u32 C1, u32 FG, u32 BG, c8* Text) { + R0 -= 1; + R1 -= 1; + C0 -= 1; + C1 -= 1; + + bool InText = true; + int Row = R0; + int Col = 0; + for (Row = R0; Row <= R1; Row++) { + for (Col = C0; Col <= C1;) { + if (*Text == 0) InText = false; + if (InText) { + c8 Char = *Text; + if (Char >= 'a' && Char <= 'z') Char = Char - 'a' + 'A'; + if (Char == '\r') { + Col = C0; + } else if (Char == '\n') { + Row += 1; + } else { + TMDC->SetCharacter(Device, Row, Col, Char, FG, BG); + Col += 1; + } + + Text += 1; + } else { + TMDC->SetCharacter(Device, Row, Col, ' ', FG, BG); + Col += 1; + } + } + } + + return; +} + [[noreturn]] void entry64(struct boot_params* BootParams) { BootBootParams = BootParams; @@ -36,6 +108,12 @@ void entry64(struct boot_params* BootParams) { // Initialize the kernel heap if (KernelHeapInitialize()) while (1) {} + // Initialize the IRQ handler + if (IrqHandlerInitialize()) while (1) {} + + // Enable interrupts + IrqHandlerEnableInterrupts(); + // Initialize the extended debugging information block if (DebugInitialize()) while (1) {} @@ -54,6 +132,33 @@ void entry64(struct boot_params* BootParams) { // Initialize PCI code.. PciInitialize(); + // Try to find a screen and write some crap to it. + // TODO: REMOVE WHEN DONE WITH DISPLAY DRIVERS + if (!TextModeDisplayCapabilityIsInitialized()) TextModeDisplayCapabilityInitialize(); + + struct SysbusDevice* Screen = TryFindScreen(SysbusGetRootDevice()); + if (Screen == 0) Panic("No screen found"); + struct TextModeDisplayCapability* ScreenTMDC = SysbusGetCapability(Screen, TextModeDisplayCapabilityGetCapability()); + + if (ScreenTMDC->Reset(Screen)) Panic("Failed to reset screen"); + if (ScreenTMDC->Enable(Screen)) Panic("Failed to enable screen"); + + // Set color palette + ScreenTMDC->SetPaletteColor(Screen, 0, 0, 0, 0 ); + ScreenTMDC->SetPaletteColor(Screen, 1, 200, 0, 0 ); + ScreenTMDC->SetPaletteColor(Screen, 2, 200, 200, 200); + + // Clear screen + FillScreenCharRange(Screen, ScreenTMDC, 1, 1, 25, 80, ' ', 1, 1); + + // Draw header + DrawTextBox(Screen, ScreenTMDC, 4, 32, 4, 47, 2, 1, " YOU FUCKED UP! "); + + // Draw body + DrawTextBox(Screen, ScreenTMDC, 6, 5, 8, 75, 1, 2, "A fatal error has occurred and Lindows has shut down to prevent damage to your device."); + DrawTextBox(Screen, ScreenTMDC, 10, 5, 13, 75, 1, 2, "If this error occurs again after a reboot, check the logs in `C:/Windows/Logs/`. If you are unable to correct the error, try dumping the system and analyzing it in GDB or submitting a bug report with the dump and logs included."); + DrawTextBox(Screen, ScreenTMDC, 21, 5, 22, 75, 1, 2, "Press any key to reboot.\r\nPress ESC to dump the system state to `C:/Windows/SystemDump/`."); + // Hang :) while (1) {} } diff --git a/lcrash/mm/kmalloc.c b/lcrash/mm/kmalloc.c index 7961c83..c64b6ce 100644 --- a/lcrash/mm/kmalloc.c +++ b/lcrash/mm/kmalloc.c @@ -262,6 +262,12 @@ void* KernelHeapAllocInternal(u32 Size, u32 Align, u32 Flags, u32 Iteration) { Block->Free = 0; Block->Size = Size; + // Transform block data + u8* BlockData = (void*)Block + sizeof(struct KernelHeapBlock); + if (Flags & KHA_ZERO) { + for (int i = 0; i < Block->Size; i++) BlockData[i] = 0; + } + return (void*)Block + sizeof(struct KernelHeapBlock); } } diff --git a/lcrash/mm/kmalloc.h b/lcrash/mm/kmalloc.h index 9383ac3..e10b8a6 100644 --- a/lcrash/mm/kmalloc.h +++ b/lcrash/mm/kmalloc.h @@ -12,6 +12,9 @@ int KernelHeapInitialize(); */ void* KernelHeapAlloc(u32 Size, u32 Align, u32 Flags); +/// Flag for KernelHeapAlloc: Zero memory +#define KHA_ZERO 1 + /** * Free memory */ diff --git a/lcrash/mm/virt.c b/lcrash/mm/virt.c index 6b23222..9adb50e 100644 --- a/lcrash/mm/virt.c +++ b/lcrash/mm/virt.c @@ -12,11 +12,59 @@ void VmemMapMemory(void* Phys, void* Virt, u64 Size) { if ((PhysStart | VirtStart | Size) & 0xfff) Panic("VmemMapMemory: Addresses not page aligned"); + // Map and/or create pages/tables for (u64 Offset4 = VirtStart; Offset4 < VirtStart + Size; Offset4 += 0x8000000000) { + u64 Index4 = (Offset4 >> 48) & 0x1ff; + + u64 (*PDPT)[512] = ((*VmemPML4)[Index4] & 1) + ? (void*)((*VmemPML4)[Index4] & 0x0007fffffffff000) + : KernelHeapAlloc(sizeof(u64) * 512, 0x1000, KHA_ZERO); + + // Add our table + if (!((*VmemPML4)[Index4] & 1)) { + (*VmemPML4)[Index4] = (u64)PDPT | 7; + } + for (u64 Offset3 = Offset4; Offset3 < VirtStart + Size && Offset3 < Offset4 + 0x8000000000; Offset3 += 0x40000000) { + u64 Index3 = (Offset3 >> 30) & 0x1ff; + + u64 (*PD)[512] = ((*PDPT)[Index3] & 1) && !((*PDPT)[Index3] & 128) + ? (void*)((*PDPT)[Index3] & 0x0007fffffffff000) + : KernelHeapAlloc(sizeof(u64) * 512, 0x1000, KHA_ZERO); + + // Add our table + if (!((*PDPT)[Index3] & 1)) { + (*PDPT)[Index3] = (u64)PD | 7; + + if ((*PDPT)[Index3] & 128) { + // TODO: Copy stuff from the thing + } + } + + for (u64 Offset2 = Offset3; Offset2 < VirtStart + Size && Offset2 < Offset3 + 0x40000000; Offset2 += 0x200000) { + u64 Index2 = (Offset2 >> 21) & 0x1ff; + + [[maybe_unused]] + u64 (*PT)[512] = ((*PD)[Index2] & 1) && !((*PD)[Index2] & 128) + ? (void*)((*PD)[Index2] & 0x0007fffffffff000) + : KernelHeapAlloc(sizeof(u64) * 512, 0x1000, KHA_ZERO); + + // ADD OUR TABLE + if (!((*PD)[Index2] & 1)) { + (*PD)[Index2] = (u64)PT | 7; + + if ((*PD)[Index2] & 128) { + // TODO: Copy stuff from the thing + } + } + for (u64 Offset1 = Offset2; Offset2 < VirtStart + Size && Offset1 < Offset2 + 0x200000; Offset1 += 0x1000) { - + [[maybe_unused]] + u64 Index1 = (Offset1 >> 12) & 0x1ff; + + // Map the page + (*PT)[Index1] = Offset1 | 7; } } } diff --git a/lcrash/pci/pci.c b/lcrash/pci/pci.c index fd61a90..0a8dd45 100644 --- a/lcrash/pci/pci.c +++ b/lcrash/pci/pci.c @@ -4,30 +4,128 @@ #include #include #include +#include +#include +#include + +#define PSD_MISC_() PciCreateMiscDevice(Parent, Bus, Device, DeviceHeader->Class, DeviceHeader->Subclass, DeviceHeader->ProgIF) bool PciIsPresent = false; bool PciSupportsECM = false; void* PciBusses[256] = {}; -void PciScanDevice(u32 Bus, u32 Device) { - struct PciConfigurationSpaceHeader* DeviceHeader = (struct PciConfigurationSpaceHeader*)(PciBusses[Bus] + Device * 0x800); +struct SysbusDeviceDescription* PciSBHostControllerDevice = 0; +struct SysbusDeviceDescription* PciSBMiscDevice = 0; + +void PciCreateMiscDevice(struct SysbusDevice* Parent, u8 Bus, u8 Device, u8 Class, u8 Subclass, u8 ProgInterface) { + struct SysbusDevice* Dev = SysbusCreateDevice(PciSBMiscDevice, Parent, NULL); + struct PciSBMiscDevice* DeviceData = KernelHeapAlloc(sizeof(PciSBMiscDevice), 1, 0); + + DeviceData->Bus = Bus; + DeviceData->Device = Device; + DeviceData->Class = Class; + DeviceData->Subclass = Subclass; + DeviceData->ProgInterface = ProgInterface; + + Dev->DeviceName = "PCI Misc Device"; + Dev->DeviceData = DeviceData; +} + +void PciScanDevice(u32 Bus, u32 Device, struct SysbusDevice* Parent) { + struct PciConfigurationSpaceHeader* DeviceHeader = (struct PciConfigurationSpaceHeader*)(PciBusses[Bus] + Device * 0x8000); // Is a device connected here? if (DeviceHeader->VendorID != 0xFFFF) { - while (1) {} + if ((DeviceHeader->HeaderType & 3) == 0) { + if (DeviceHeader->Class == 3) { + if (DeviceHeader->Subclass == 0) { + if (DeviceHeader->ProgIF == 0) { + // It looks like theres something in the + // VGA's BARs but i can't seem to find any + // documentation on them, so we'll just use + // legacy vga ports! + + // Get VGA drivers ready + if (!VgaIsInitialized()) VgaInitialize(); + + // QEMU oh so kindly provides us with a builtin version of the VESA BIOS Extensions! + // They break our code. Disable them. + if (DeviceHeader->VendorID == 0x1234 && DeviceHeader->DeviceID == 0x1111) { + PortWrite16(0x01CE, 0x04); // VBE_DISPI_IOPORT_INDEX <= 0x04 + PortWrite16(0x01D0, 0x00); // [IDX:04] ENABLED <= FALSE + } + + struct SysbusDevice* VgaDev = VgaCreateDevice(Parent); + VgaDev->DeviceName = "VGA Device"; + } else PSD_MISC_(); + } else PSD_MISC_(); + } else if (DeviceHeader->Class == 6) { + if (DeviceHeader->Subclass == 0) { + if (DeviceHeader->HeaderType & 0x80) { + Panic("No support for multiple host controller busses"); + } else { + struct PciSBHostController_CreateArgs CreateArgs; + CreateArgs.Bus = Bus; + CreateArgs.Device = Device; + CreateArgs.OwnedBusCount = 1; + CreateArgs.OwnedBusses[0] = Bus; + + struct SysbusDevice* HostController = SysbusCreateDevice( + PciSBHostControllerDevice, + Parent, &CreateArgs + ); + HostController->DeviceName = "PCI Host Controller"; + + if (Device == 0) { + for (int i = 1; i < 32; i++) PciScanDevice(Bus, i, HostController); + } else Panic("Bus root inside bus"); + } + } else PSD_MISC_(); + } else PSD_MISC_(); + } else PSD_MISC_(); } } -void PciScanBus(u32 Bus) { - // Scan bus devices - for (int i = 0; i < 32; i++) PciScanDevice(Bus, i); +s32 PciSBHostControllerDevice_Create(struct SysbusDevice* Device, void* Data) { + struct PciSBHostController_CreateArgs* CreateArgs = Data; + struct PciSBHostController* DeviceData = KernelHeapAlloc(sizeof(struct PciSBHostController), 1, KHA_ZERO); + + // Copy parameters + DeviceData->Bus = CreateArgs->Bus; + DeviceData->Device = CreateArgs->Device; + DeviceData->OwnedBusCount = CreateArgs->OwnedBusCount; + for (int i = 0; i < DeviceData->OwnedBusCount; i++) DeviceData->OwnedBusses[i] = CreateArgs->OwnedBusses[i]; + + // Save device data + Device->DeviceData = (void*)DeviceData; + + return 0; +} + +s32 PciSBHostControllerDevice_Delete(struct SysbusDevice* Device) { + struct PciSBHostController* DeviceData = Device->DeviceData; + + // Free device data + KernelHeapFree(DeviceData); + + return 0; } void PciInitialize() { // Try to figure out if we have PCIe if (!AcpiPresent()) Panic("Failed to initialize PCI"); - + + // Define our devices + PciSBHostControllerDevice = SysbusCreateDeviceDescription(); + PciSBHostControllerDevice->DeviceName = "PCI Host Controller"; + PciSBHostControllerDevice->CreateDevice = PciSBHostControllerDevice_Create; + PciSBHostControllerDevice->DeleteDevice = PciSBHostControllerDevice_Delete; + + PciSBMiscDevice = SysbusCreateDeviceDescription(); + PciSBMiscDevice->DeviceName = "PCI Misc Device"; + + // Acpi struct AcpiMCFG* BridgeTable = AcpiGetTable("MCFG"); // Guess not @@ -39,7 +137,7 @@ void PciInitialize() { // Identity map our busses because linux doesn't do it for us VmemMapMemory( BridgeTable->Bridges[i].Address, BridgeTable->Bridges[i].Address, - (BridgeTable->Bridges[i].EndBus - BridgeTable->Bridges[i].StartBus) * 0x100000 + (BridgeTable->Bridges[i].EndBus - BridgeTable->Bridges[i].StartBus + 1) * 0x100000 ); for (int Bus = BridgeTable->Bridges[i].StartBus; Bus < BridgeTable->Bridges[i].EndBus; Bus++) { @@ -48,7 +146,7 @@ void PciInitialize() { } // Scan the root bus - PciScanBus(0); + PciScanDevice(0, 0, SysbusGetRootDevice()); return; } diff --git a/lcrash/pci/pci.h b/lcrash/pci/pci.h index efed49c..4a34947 100644 --- a/lcrash/pci/pci.h +++ b/lcrash/pci/pci.h @@ -11,19 +11,72 @@ struct [[gnu::packed]] PciConfigurationSpaceHeader { u16 Status; u16 Command; u8 RevisionID : 8; - u32 ClassCode : 24; + u8 ProgIF; + u8 Subclass; + u8 Class; u8 CacheLineSize; u8 MasterLatencyTimer; u8 HeaderType; u8 BIST; - u8 Reserved[0x20]; + union { + struct { + u32 BAR0; + u32 BAR1; + u32 BAR2; + u32 BAR3; + u32 BAR4; + u32 BAR5; + u32 CIS; + u16 SubsystemVendor; + u16 Subsystem; + u32 ExpansionROM; + u8 Reserved[3]; + }; + u8 Reserved2[0x20]; + }; u8 CapabilitiesPointer; - u8 Reserved2[7]; + u8 Reserved3[7]; u8 InterruptLine; u8 InterruptPin; - u8 Reserved3[2]; + u8 Reserved4[2]; }; +/** + * PCI Host Controller device for the system bus + */ +struct PciSBHostController { + u8 Bus; + u8 Device; + + u8 OwnedBusCount; + u8 OwnedBusses[8]; +}; + +/** + * PCI Host Controller device create arguments + */ +struct PciSBHostController_CreateArgs { + u8 Bus; + u8 Device; + + u8 OwnedBusCount; + u8 OwnedBusses[8]; +}; + +/** + * Unknown PCI device + */ +struct PciSBMiscDevice { + u8 Bus; + u8 Device; + + u8 Class; + u8 Subclass; + u8 ProgInterface; +}; + +typedef struct PciSBMiscDevice PciSBMiscDevice_CreateArgs; + /** * Initialize the PCI code. */ diff --git a/lcrash/setup/compressed/entry64.S b/lcrash/setup/compressed/entry64.S index 1dcf2f4..cad369d 100644 --- a/lcrash/setup/compressed/entry64.S +++ b/lcrash/setup/compressed/entry64.S @@ -28,5 +28,5 @@ entry64: // 64-bit entry point for kernel decompression .section ".bss" init_stack: // this should be sufficient for kernel decompression - .skip 0x8000, 0 + .skip 0x10000, 0 einit_stack: diff --git a/lcrash/setup/header.S b/lcrash/setup/header.S index d554aba..d735c81 100644 --- a/lcrash/setup/header.S +++ b/lcrash/setup/header.S @@ -46,7 +46,7 @@ payload_offset: .long _end // cckernel_start payload_length: .long _KKCLEN // cckernel_size setup_data: .quad 0 pref_address: .quad 0 -init_size: .long 0x20000 // a bit of space +init_size: .long 0x40000 // a bit of space handover_offset: .long 0 // TODO kernel_info_offset: .long 0 // TODO /* .globl entrylow diff --git a/lcrash/util.c b/lcrash/util.c index e9482cb..dc55d5b 100644 --- a/lcrash/util.c +++ b/lcrash/util.c @@ -11,3 +11,48 @@ bool CompareMemory(const void* Addr1, const void* Addr2, u32 Length) { return true; } + +void PortWrite8(u16 Port, u8 Data) { + asm ( "out %b1, %w0" + : + : "d" (Port), + "a" (Data)); +} + +void PortWrite16(u16 Port, u16 Data) { + asm ( "out %w1, %w0" + : + : "d" (Port), + "a" (Data)); +} + +void PortWrite32(u16 Port, u32 Data) { + asm ( "out %1, %w0" + : + : "d" (Port), + "a" (Data)); +} + +u8 PortRead8(u16 Port) { + u8 Data = 0; + asm ( "in %w1, %b0" + : "=a" (Data) + : "d" (Port)); + return Data; +} + +u16 PortRead16(u16 Port) { + u16 Data = 0; + asm ( "in %w1, %w0" + : "=a" (Data) + : "d" (Port)); + return Data; +} + +u32 PortRead32(u16 Port) { + u32 Data = 0; + asm ( "in %w1, %0" + : "=a" (Data) + : "d" (Port)); + return Data; +} diff --git a/lcrash/util.h b/lcrash/util.h index 80a1988..8376695 100644 --- a/lcrash/util.h +++ b/lcrash/util.h @@ -6,3 +6,11 @@ * Compare the data at two memory addresses */ bool CompareMemory(const void* Addr1, const void* Addr2, u32 Length); + +void PortWrite8(u16 Port, u8 Data); +void PortWrite16(u16 Port, u16 Data); +void PortWrite32(u16 Port, u32 Data); + +u8 PortRead8(u16 Port); +u16 PortRead16(u16 Port); +u32 PortRead32(u16 Port);