From 7b1022a86fe55f8b5d04702125f6f65bf5044dff Mon Sep 17 00:00:00 2001 From: Septicake Date: Wed, 11 Sep 2024 23:20:08 -0400 Subject: [PATCH 01/70] A solid attempt --- Makefile | 2 +- src/os/hard/disk.c | 307 +++++++++++++++++++++++++++++++++++++++++++++ src/os/hard/disk.h | 125 ++++++++++++++++++ 3 files changed, 433 insertions(+), 1 deletion(-) create mode 100644 src/os/hard/disk.c create mode 100644 src/os/hard/disk.h diff --git a/Makefile b/Makefile index e8d4009..c020e24 100644 --- a/Makefile +++ b/Makefile @@ -52,7 +52,7 @@ OBJ_NAMES := src/os/main.o src/os/test.o os_entry.o src/lib/video/VGA_text.o \ src/lib/device/serial.o src/lib/device/ps2.o src/lib/device/keyboard.o \ src/lib/container/ring_buffer.o \ src/lib/stdlib/stdio.o src/lib/stdlib/stdlib.o src/lib/stdlib/string.o \ - src/lib/pit/pit.o + src/lib/pit/pit.o src/os/hard/disk.o .PHONY: clean qemu test diff --git a/src/os/hard/disk.c b/src/os/hard/disk.c new file mode 100644 index 0000000..a5673eb --- /dev/null +++ b/src/os/hard/disk.c @@ -0,0 +1,307 @@ +#include "../stdlib/stdio.h" + +#include "../pit/pit.h" +#include "disk.h" +#include "port_io.h" + +static void insw(uint16_t reg, uint8_t *buffer, int bytes) { + for(int i = 0; i < bytes; i++) { + buffer[i] = inb(reg); + } +} + +void ide_initialize(unsigned int BAR0, unsigned int BAR1, unsigned int BAR2, + unsigned int BAR3, unsigned int BAR4) { + int i, j, k, count = 0; + + channels[ATA_PRIMARY].base = (BAR0 & 0xFFFFFFFC) + 0x1F0 * (!BAR0); + channels[ATA_PRIMARY].ctrl = (BAR1 & 0xFFFFFFFC) + 0x3F6 * (!BAR1); + channels[ATA_SECONDARY].base = (BAR2 & 0xFFFFFFFC) + 0x170 * (!BAR2); + channels[ATA_SECONDARY].ctrl = (BAR3 & 0xFFFFFFFC) + 0x376 * (!BAR3); + channels[ATA_PRIMARY].bmide = (BAR4 & 0xFFFFFFFC) + 0; + channels[ATA_SECONDARY].bmide = (BAR4 & 0xFFFFFFFC) + 8; + + ide_write(ATA_PRIMARY, ATA_REG_CONTROL, 0b10); + ide_write(ATA_SECONDARY, ATA_REG_CONTROL, 0b10); + + for(i = 0; i < 2; i++) { + for(j = 0; j < 2; j++) { + uint8_t err = 0, type = IDE_ATA, status; + ide_devices[count].Reserved = 0; + + ide_write(i, ATA_REG_HDDEVSEL, 0xA0 | (j << 4)); + sleep(1); + + ide_write(i, ATA_REG_COMMAND, ATA_CMD_IDENTIFY); + sleep(1); + + while (1) { + status = ide_read(i, ATA_REG_STATUS); + if((status & ATA_SR_ERR)) { err = 1; break; } + if(!(status & ATA_SR_BSY) && (status & ATA_SR_DRQ)) break; + } + + if(err != 0) { + uint8_t cl = ide_read(i, ATA_REG_LBA1); + uint8_t ch = ide_read(i, ATA_REG_LBA2); + + if(cl == 0x14 && ch == 0xEB) + type = IDE_ATAPI; + else if(cl == 0x69 && ch == 0x96) + type = IDE_ATAPI; + else + continue; + + ide_write(i, ATA_REG_COMMAND, ATA_CMD_IDENTIFY_PACKET); + sleep(1); + } + + ide_read_buffer(i, ATA_REG_DATA, ide_buf, 512); + + ide_devices[count].Reserved = 1; + ide_devices[count].Type = type; + ide_devices[count].Channel = i; + ide_devices[count].Drive = j; + ide_devices[count].Signature = *((uint16_t *)(ide_buf + ATA_IDENT_DEVICETYPE)); + ide_devices[count].Capabilities = *((uint16_t *)(ide_buf + ATA_IDENT_CAPABILITIES)); + ide_devices[count].CommandSets = *((uint32_t *)(ide_buf + ATA_IDENT_COMMANDSETS)); + + if(ide_devices[count].CommandSets & (1 << 26)) + ide_devices[count].Size = *((uint32_t *)(ide_buf + ATA_IDENT_MAX_LBA_EXT)); + else + ide_devices[count].Size = *((uint32_t *)(ide_buf + ATA_IDENT_MAX_LBA)); + + for(k = 0; k < 40; k += 2) { + ide_devices[count].Model[k] = ide_buf[ATA_IDENT_MODEL + k + 1]; + ide_devices[count].Model[k + 1] = ide_buf[ATA_IDENT_MODEL + k]; + } + ide_devices[count].Model[40] = 0; + + count++; + } + } + + for(i = 0; i < 4; i++) { + char buff[256]; + if(ide_devices[i].Reserved) { + snprintf(buff, 256, " Found %s Drive %dGB - %s\n", + (const char* []){"ATA", "ATAPI"}[ide_devices[i].Type], + ide_devices[i].Size / 1024 / 1024 / 2, + ide_devices[i].Model); + } + } +} + +uint8_t ide_ata_access(uint8_t direction, uint8_t drive, uint32_t lba, + uint8_t numsects, uint16_t selector, uint32_t edi) { + uint8_t lba_mode, dma, cmd; + uint8_t lba_io[6]; + uint32_t channel = ide_devices[drive].Channel; + uint32_t slavebit = ide_devices[drive].Drive; + uint32_t bus = channels[channel].base; + uint32_t words = 256; + uint16_t cyl, i; + uint8_t head, sect, err; + + if(lba >= 0x10000000) { + // LBA48 + lba_mode = 2; + lba_io[0] = (lba & 0x000000FF) >> 0; + lba_io[1] = (lba & 0x0000FF00) >> 8; + lba_io[2] = (lba & 0x00FF0000) >> 16; + lba_io[3] = (lba & 0xFF000000) >> 24; + lba_io[4] = 0; + lba_io[5] = 0; + head = 0; + } else if(ide_devices[drive].Capabilities & 0x200) { + // LBA28 + lba_mode = 1; + lba_io[0] = (lba & 0x00000FF) >> 0; + lba_io[1] = (lba & 0x000FF00) >> 8; + lba_io[2] = (lba & 0x0FF0000) >> 16; + lba_io[3] = 0; + lba_io[4] = 0; + lba_io[5] = 0; + head = (lba & 0xF000000) >> 24; + } else { + // CHS + lba_mode = 0; + sect = (lba & (63 - 1)) + 1; + cyl = (lba + 1 - sect) / (16 * 63); + lba_io[0] = sect; + lba_io[1] = (cyl >> 0) & 0xFF; + lba_io[2] = (cyl >> 8) & 0xFF; + lba_io[3] = 0; + lba_io[4] = 0; + lba_io[5] = 0; + head = (lba + 1 - sect) & ((16 * 63) - 1) / 63; + } + + dma = 0; // DMA is not supported + + while(ide_read(channel, ATA_REG_STATUS) & ATA_SR_BSY); + + if(lba_mode == 0) { + ide_write(channel, ATA_REG_HDDEVSEL, 0xA0 | (slavebit << 4) | head); + } else { + ide_write(channel, ATA_REG_HDDEVSEL, 0xE0 | (slavebit << 4) | head); + } + + if(lba_mode == 2) { + ide_write(channel, ATA_REG_SECCOUNT1, 0); + ide_write(channel, ATA_REG_LBA3, lba_io[3]); + ide_write(channel, ATA_REG_LBA4, lba_io[4]); + ide_write(channel, ATA_REG_LBA5, lba_io[5]); + } + ide_write(channel, ATA_REG_SECCOUNT0, numsects); + ide_write(channel, ATA_REG_LBA0, lba_io[0]); + ide_write(channel, ATA_REG_LBA1, lba_io[1]); + ide_write(channel, ATA_REG_LBA2, lba_io[2]); + + if (lba_mode == 0 && dma == 0 && direction == 0) cmd = ATA_CMD_READ_PIO; + if (lba_mode == 1 && dma == 0 && direction == 0) cmd = ATA_CMD_READ_PIO; + if (lba_mode == 2 && dma == 0 && direction == 0) cmd = ATA_CMD_READ_PIO_EXT; + if (lba_mode == 0 && dma == 1 && direction == 0) cmd = ATA_CMD_READ_DMA; + if (lba_mode == 1 && dma == 1 && direction == 0) cmd = ATA_CMD_READ_DMA; + if (lba_mode == 2 && dma == 1 && direction == 0) cmd = ATA_CMD_READ_DMA_EXT; + if (lba_mode == 0 && dma == 0 && direction == 1) cmd = ATA_CMD_WRITE_PIO; + if (lba_mode == 1 && dma == 0 && direction == 1) cmd = ATA_CMD_WRITE_PIO; + if (lba_mode == 2 && dma == 0 && direction == 1) cmd = ATA_CMD_WRITE_PIO_EXT; + if (lba_mode == 0 && dma == 1 && direction == 1) cmd = ATA_CMD_WRITE_DMA; + if (lba_mode == 1 && dma == 1 && direction == 1) cmd = ATA_CMD_WRITE_DMA; + if (lba_mode == 2 && dma == 1 && direction == 1) cmd = ATA_CMD_WRITE_DMA_EXT; + ide_write(channel, ATA_REG_COMMAND, cmd); + + if(dma) { + if(direction == 0) { + // DMA Read + } else { + // DMA Write + } + } else { + if(direction == 0) { + for(i = 0; i < numsects; i++) { + if((err = ide_polling(channel, 1))) { + return err; + } + __asm__ volatile("pushw %es"); + __asm__ volatile("mov %%ax, %%es"::"a"(selector)); + __asm__ volatile("rep insw"::"c"(words), "d"(bus), "D"(edi)); + __asm__ volatile("popw %es"); + edi += (words * 2); + } else { + for(i = 0; i < numsects; i++) { + ide_polling(channel, 0); + __asm__ volatile("push"); + __asm__ volatile("mov %%ax, %%ds"::"a"(selector)); + __asm__ volatile("rep outsw"::"c"(words), "d"(bus), "S"(edi)); + __asm__ volatile("popw %ds"); + edi += (words*2); + } + ide_write(channel, ATA_REG_COMMAND, (char [3]) {ATA_CMD_CACHE_FLUSH, + ATA_CMD_CACHE_FLUSH, ATA_CMD_CACHE_FLUSH_EXT}); + ide_polling(channel, 0); + } + } + } + + return 0; +} + +unsigned char ide_read(unsigned char channel, unsigned char reg) { + unsigned char result = 0; + if (reg > 0x07 && reg < 0x0C) + ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN); + if (reg < 0x08) + result = inb(channels[channel].base + reg - 0x00); + else if (reg < 0x0C) + result = inb(channels[channel].base + reg - 0x06); + else if (reg < 0x0E) + result = inb(channels[channel].ctrl + reg - 0x0A); + else if (reg < 0x16) + result = inb(channels[channel].bmide + reg - 0x0E); + if (reg > 0x07 && reg < 0x0C) + ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN); + return result; +} + +void ide_write(unsigned char channel, unsigned char reg, unsigned char data) { + if (reg > 0x07 && reg < 0x0C) + ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN); + if (reg < 0x08) + outb(channels[channel].base + reg - 0x00, data); + else if (reg < 0x0C) + outb(channels[channel].base + reg - 0x06, data); + else if (reg < 0x0E) + outb(channels[channel].ctrl + reg - 0x0A, data); + else if (reg < 0x16) + outb(channels[channel].bmide + reg - 0x0E, data); + if (reg > 0x07 && reg < 0x0C) + ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN); +} + +void ide_read_buffer(uint16_t channel, uint16_t reg, uint8_t *buffer, int bytes) { + if(reg > 0x07 && reg < 0x0C) + ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN); + asm("pushw %es; movw %ds, %ax; movw %ax, %es"); + if(reg < 0x08) + insw(channels[channel].base + reg - 0x00, buffer, bytes); + else if(reg < 0x0C) + insw(channels[channel].base + reg - 0x06, buffer, bytes); + else if(reg < 0x0E) + insw(channels[channel].ctrl + reg - 0x0A, buffer, bytes); + else if(reg < 0x16) + insw(channels[channel].bmide + reg - 0x0E, buffer, bytes); + asm("popw %es;"); + if(reg > 0x07 && reg < 0x0C) + ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN); +} + +uint8_t ide_polling(uint8_t channel, int advanced_check) { + for(int i = 0; i < 4; i++) + ide_read(channel, ATA_REG_ALTSTATUS); + + while(ide_read(channel, ATA_REG_STATUS) & ATA_SR_BSY); + + if(advanced_check) { + uint8_t state = ide_read(channel, ATA_REG_STATUS); + + if(state & ATA_SR_ERR) + return 2; + + if(state & ATA_SR_DF) + return 1; + + if((state & ATA_SR_DRQ) == 0) + return 3; + } + + return 0; +} + +uint8_t ide_print_error(uint32_t drive, uint8_t err) { + if(err == 0) + return err; + char buff[256]; + + snprintf(buff, 32, "IDE:"); + if(err == 1) { snprintf(buff, 32, "- Device Fault\n"); err = 19; } + else if(err == 2) { + uint8_t st = ide_read(ide_devices[drive].Channel, ATA_REG_ERROR); + if(st & ATA_ER_AMNF) { snprintf(buff, 32, "- No Address Mark Found\n"); err = 7; } + if(st & ATA_ER_TK0NF) { snprintf(buff, 32, "- No Media or Media Error\n"); err = 3; } + if(st & ATA_ER_ABRT) { snprintf(buff, 32, "- Command Aborted\n"); err = 20; } + if(st & ATA_ER_MCR) { snprintf(buff, 32, "- No Media or Media Error\n"); err = 3; } + if(st & ATA_ER_IDNF) { snprintf(buff, 32, "- ID Mark not Found\n"); err = 21; } + if(st & ATA_ER_MC) { snprintf(buff, 32, "- No Media or Media Error\n"); err = 3; } + if(st & ATA_ER_UNC) { snprintf(buff, 32, "- Uncorrectable Data Error\n"); err = 22; } + if(st & ATA_ER_BBK) { snprintf(buff, 32, "- Bad Sectors\n"); err = 13; } + } else if(err == 3) { snprintf(buff, 32, "- Reads Nothing\n"); err = 23; } + else if(err == 4) { snprintf(buff, 32, "- Write Protected\n"); err = 8; } + snprintf(buff, 256, "- [%s %s] %s\n", + (const char* []){"Primary", "Secondary"}[ide_devices[drive].Channel], + (const char* []){"Master", "Slave"}[ide_devices[drive].Drive], + ide_devices[drive].Model); + + return err; +} diff --git a/src/os/hard/disk.h b/src/os/hard/disk.h new file mode 100644 index 0000000..f29e003 --- /dev/null +++ b/src/os/hard/disk.h @@ -0,0 +1,125 @@ +#ifndef DISK_H +#define DISK_H + +#include + +// Status bit masks +#define ATA_SR_BSY 0x80 // Busy +#define ATA_SR_DRDY 0x40 // Drive ready +#define ATA_SR_DF 0x20 // Drive write fault +#define ATA_SR_DSC 0x10 // Drive seek complete +#define ATA_SR_DRQ 0x08 // Data request ready +#define ATA_SR_CORR 0x04 // Corrected data +#define ATA_SR_IDX 0x02 // Index +#define ATA_SR_ERR 0x01 // Error + +// Error bit masks +#define ATA_ER_BBK 0x80 // Bad block +#define ATA_ER_UNC 0x40 // Uncorrectable data +#define ATA_ER_MC 0x20 // Media changed +#define ATA_ER_IDNF 0x10 // ID mark not found +#define ATA_ER_MCR 0x08 // Media change request +#define ATA_ER_ABRT 0x04 // Command aborted +#define ATA_ER_TK0NF 0x02 // Track 0 not found +#define ATA_ER_AMNF 0x01 // No address mark + +// Commands +#define ATA_CMD_READ_PIO 0x20 +#define ATA_CMD_READ_PIO_EXT 0x24 +#define ATA_CMD_READ_DMA 0xC8 +#define ATA_CMD_READ_DMA_EXT 0x25 +#define ATA_CMD_WRITE_PIO 0x30 +#define ATA_CMD_WRITE_PIO_EXT 0x34 +#define ATA_CMD_WRITE_DMA 0xCA +#define ATA_CMD_WRITE_DMA_EXT 0x35 +#define ATA_CMD_CACHE_FLUSH 0xE7 +#define ATA_CMD_CACHE_FLUSH_EXT 0xEA +#define ATA_CMD_PACKET 0xA0 +#define ATA_CMD_IDENTIFY_PACKET 0xA1 +#define ATA_CMD_IDENTIFY 0xEC +// -> ATAPI commands +#define ATAPI_CMD_READ 0xA8 +#define ATAPI_CMD_EJECT 0x1B +// <- ATAPI commands + +// IDENTIFY identification space +#define ATA_IDENT_DEVICETYPE 0 +#define ATA_IDENT_CYLINDERS 2 +#define ATA_IDENT_HEADS 6 +#define ATA_IDENT_SECTORS 12 +#define ATA_IDENT_SERIAL 20 +#define ATA_IDENT_MODEL 54 +#define ATA_IDENT_CAPABILITIES 98 +#define ATA_IDENT_FIELDVALID 106 +#define ATA_IDENT_MAX_LBA 120 +#define ATA_IDENT_COMMANDSETS 164 +#define ATA_IDENT_MAX_LBA_EXT 200 + +#define IDE_ATA 0x00 +#define IDE_ATAPI 0x01 + +#define ATA_MASTER 0x00 +#define ATA_SLAVE 0x01 + +// Register offsets +#define ATA_REG_DATA 0x00 +#define ATA_REG_ERROR 0x01 +#define ATA_REG_FEATURES 0x01 +#define ATA_REG_SECCOUNT0 0x02 +#define ATA_REG_LBA0 0x03 +#define ATA_REG_LBA1 0x04 +#define ATA_REG_LBA2 0x05 +#define ATA_REG_HDDEVSEL 0x06 +#define ATA_REG_COMMAND 0x07 +#define ATA_REG_STATUS 0x07 +#define ATA_REG_SECCOUNT1 0x08 +#define ATA_REG_LBA3 0x09 +#define ATA_REG_LBA4 0x0A +#define ATA_REG_LBA5 0x0B +#define ATA_REG_CONTROL 0x0C +#define ATA_REG_ALTSTATUS 0x0C +#define ATA_REG_DEVADDRESS 0x0D + +// Channels: +#define ATA_PRIMARY 0x00 +#define ATA_SECONDARY 0x01 + +// Directions: +#define ATA_READ 0x00 +#define ATA_WRITE 0x01 + +struct IDEChannelRegisters { + unsigned short base; // I/O Base. + unsigned short ctrl; // Control Base + unsigned short bmide; // Bus Master IDE + unsigned char nIEN; // nIEN (No Interrupt); +} channels[2]; + +uint8_t ide_buf[2048] = {0}; +volatile static uint8_t ide_irq_invoked = 0; +static uint8_t atapi_packet[12] = {0xA8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +struct ide_device { + unsigned char Reserved; // 0 (Empty) or 1 (This Drive really exists). + unsigned char Channel; // 0 (Primary Channel) or 1 (Secondary Channel). + unsigned char Drive; // 0 (Master Drive) or 1 (Slave Drive). + unsigned short Type; // 0: ATA, 1:ATAPI. + unsigned short Signature; // Drive Signature + unsigned short Capabilities;// Features. + unsigned int CommandSets; // Command Sets Supported. + unsigned int Size; // Size in Sectors. + unsigned char Model[41]; // Model in string. +} ide_devices[4]; + +void ide_initialize(unsigned int BAR0, unsigned int BAR1, unsigned int BAR2, unsigned int BAR3, +unsigned int BAR4); +uint8_t ide_ata_access(uint8_t direction, uint8_t drive, uint32_t lba, + uint8_t numsects, uint16_t selector, uint32_t edi); + +uint8_t ide_read(unsigned char channel, unsigned char reg); +void ide_write(unsigned char channel, unsigned char reg, unsigned char data); +void ide_read_buffer(uint16_t channel, uint16_t reg, uint8_t* buffer, int bytes); +uint8_t ide_polling(uint8_t channel, int advanced_check); +uint8_t ide_print_error(uint32_t drive, uint8_t err); + +#endif \ No newline at end of file From 452d5ce560c35f7ab59a51a5b74462807e82cb9a Mon Sep 17 00:00:00 2001 From: Septicake Date: Wed, 11 Sep 2024 23:52:08 -0400 Subject: [PATCH 02/70] Fixed it --- src/os/hard/disk.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/os/hard/disk.c b/src/os/hard/disk.c index a5673eb..257c121 100644 --- a/src/os/hard/disk.c +++ b/src/os/hard/disk.c @@ -1,6 +1,6 @@ -#include "../stdlib/stdio.h" +#include "../../lib/stdlib/stdio.h" -#include "../pit/pit.h" +#include "../../lib/pit/pit.h" #include "disk.h" #include "port_io.h" @@ -189,20 +189,20 @@ uint8_t ide_ata_access(uint8_t direction, uint8_t drive, uint32_t lba, __asm__ volatile("rep insw"::"c"(words), "d"(bus), "D"(edi)); __asm__ volatile("popw %es"); edi += (words * 2); - } else { + } + } else { for(i = 0; i < numsects; i++) { ide_polling(channel, 0); - __asm__ volatile("push"); + __asm__ volatile("pushw %ds"); __asm__ volatile("mov %%ax, %%ds"::"a"(selector)); __asm__ volatile("rep outsw"::"c"(words), "d"(bus), "S"(edi)); __asm__ volatile("popw %ds"); edi += (words*2); } - ide_write(channel, ATA_REG_COMMAND, (char [3]) {ATA_CMD_CACHE_FLUSH, - ATA_CMD_CACHE_FLUSH, ATA_CMD_CACHE_FLUSH_EXT}); + ide_write(channel, ATA_REG_COMMAND, (char []){ATA_CMD_CACHE_FLUSH, + ATA_CMD_CACHE_FLUSH, ATA_CMD_CACHE_FLUSH_EXT}[lba_mode]); ide_polling(channel, 0); } - } } return 0; From ecc09832cdce2e05dcd93c31d330dc08a997141e Mon Sep 17 00:00:00 2001 From: Real-Septicake Date: Fri, 13 Sep 2024 13:15:28 -0400 Subject: [PATCH 03/70] Moved things --- src/os/hard/disk.c | 53 +++++++++++++++++++++++++++++++++------------- src/os/hard/disk.h | 23 -------------------- 2 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/os/hard/disk.c b/src/os/hard/disk.c index 257c121..400790e 100644 --- a/src/os/hard/disk.c +++ b/src/os/hard/disk.c @@ -1,9 +1,30 @@ #include "../../lib/stdlib/stdio.h" - #include "../../lib/pit/pit.h" +#include "../../lib/video/VGA_text.h" #include "disk.h" #include "port_io.h" +static struct ide_device { + unsigned char Reserved; // 0 (Empty) or 1 (This Drive really exists). + unsigned char Channel; // 0 (Primary Channel) or 1 (Secondary Channel). + unsigned char Drive; // 0 (Master Drive) or 1 (Slave Drive). + unsigned short Type; // 0: ATA, 1:ATAPI. + unsigned short Signature; // Drive Signature + unsigned short Capabilities;// Features. + unsigned int CommandSets; // Command Sets Supported. + unsigned int Size; // Size in Sectors. + unsigned char Model[41]; // Model in string. +} ide_devices[4]; + +static struct IDEChannelRegisters { + unsigned short base; // I/O Base. + unsigned short ctrl; // Control Base + unsigned short bmide; // Bus Master IDE + unsigned char nIEN; // nIEN (No Interrupt); +} channels[2]; + +static uint8_t ide_buf[2048] = {0}; + static void insw(uint16_t reg, uint8_t *buffer, int bytes) { for(int i = 0; i < bytes; i++) { buffer[i] = inb(reg); @@ -84,10 +105,11 @@ void ide_initialize(unsigned int BAR0, unsigned int BAR1, unsigned int BAR2, for(i = 0; i < 4; i++) { char buff[256]; if(ide_devices[i].Reserved) { - snprintf(buff, 256, " Found %s Drive %dGB - %s\n", + snprintf(buff, 256, "Found %s Drive %iGB - %s", (const char* []){"ATA", "ATAPI"}[ide_devices[i].Type], ide_devices[i].Size / 1024 / 1024 / 2, ide_devices[i].Model); + println(buff, yellow); } } } @@ -285,23 +307,24 @@ uint8_t ide_print_error(uint32_t drive, uint8_t err) { char buff[256]; snprintf(buff, 32, "IDE:"); - if(err == 1) { snprintf(buff, 32, "- Device Fault\n"); err = 19; } + print(buff, red); + if(err == 1) { snprintf(buff, 32, "- Device Fault"); println(buff, red); err = 19; } else if(err == 2) { uint8_t st = ide_read(ide_devices[drive].Channel, ATA_REG_ERROR); - if(st & ATA_ER_AMNF) { snprintf(buff, 32, "- No Address Mark Found\n"); err = 7; } - if(st & ATA_ER_TK0NF) { snprintf(buff, 32, "- No Media or Media Error\n"); err = 3; } - if(st & ATA_ER_ABRT) { snprintf(buff, 32, "- Command Aborted\n"); err = 20; } - if(st & ATA_ER_MCR) { snprintf(buff, 32, "- No Media or Media Error\n"); err = 3; } - if(st & ATA_ER_IDNF) { snprintf(buff, 32, "- ID Mark not Found\n"); err = 21; } - if(st & ATA_ER_MC) { snprintf(buff, 32, "- No Media or Media Error\n"); err = 3; } - if(st & ATA_ER_UNC) { snprintf(buff, 32, "- Uncorrectable Data Error\n"); err = 22; } - if(st & ATA_ER_BBK) { snprintf(buff, 32, "- Bad Sectors\n"); err = 13; } - } else if(err == 3) { snprintf(buff, 32, "- Reads Nothing\n"); err = 23; } - else if(err == 4) { snprintf(buff, 32, "- Write Protected\n"); err = 8; } - snprintf(buff, 256, "- [%s %s] %s\n", + if(st & ATA_ER_AMNF) { snprintf(buff, 32, "- No Address Mark Found"); println(buff, red); err = 7; } + if(st & ATA_ER_TK0NF) { snprintf(buff, 32, "- No Media or Media Error"); println(buff, red); err = 3; } + if(st & ATA_ER_ABRT) { snprintf(buff, 32, "- Command Aborted"); println(buff, red); err = 20; } + if(st & ATA_ER_MCR) { snprintf(buff, 32, "- No Media or Media Error"); println(buff, red); err = 3; } + if(st & ATA_ER_IDNF) { snprintf(buff, 32, "- ID Mark not Found"); println(buff, red); err = 21; } + if(st & ATA_ER_MC) { snprintf(buff, 32, "- No Media or Media Error"); println(buff, red); err = 3; } + if(st & ATA_ER_UNC) { snprintf(buff, 32, "- Uncorrectable Data Error"); println(buff, red); err = 22; } + if(st & ATA_ER_BBK) { snprintf(buff, 32, "- Bad Sectors"); println(buff, red); err = 13; } + } else if(err == 3) { snprintf(buff, 32, "- Reads Nothing"); println(buff, red); err = 23; } + else if(err == 4) { snprintf(buff, 32, "- Write Protected"); println(buff, red); err = 8; } + snprintf(buff, 256, "- [%s %s] %s", (const char* []){"Primary", "Secondary"}[ide_devices[drive].Channel], (const char* []){"Master", "Slave"}[ide_devices[drive].Drive], ide_devices[drive].Model); - + println(buff, red); return err; } diff --git a/src/os/hard/disk.h b/src/os/hard/disk.h index f29e003..1feb9c8 100644 --- a/src/os/hard/disk.h +++ b/src/os/hard/disk.h @@ -88,29 +88,6 @@ #define ATA_READ 0x00 #define ATA_WRITE 0x01 -struct IDEChannelRegisters { - unsigned short base; // I/O Base. - unsigned short ctrl; // Control Base - unsigned short bmide; // Bus Master IDE - unsigned char nIEN; // nIEN (No Interrupt); -} channels[2]; - -uint8_t ide_buf[2048] = {0}; -volatile static uint8_t ide_irq_invoked = 0; -static uint8_t atapi_packet[12] = {0xA8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - -struct ide_device { - unsigned char Reserved; // 0 (Empty) or 1 (This Drive really exists). - unsigned char Channel; // 0 (Primary Channel) or 1 (Secondary Channel). - unsigned char Drive; // 0 (Master Drive) or 1 (Slave Drive). - unsigned short Type; // 0: ATA, 1:ATAPI. - unsigned short Signature; // Drive Signature - unsigned short Capabilities;// Features. - unsigned int CommandSets; // Command Sets Supported. - unsigned int Size; // Size in Sectors. - unsigned char Model[41]; // Model in string. -} ide_devices[4]; - void ide_initialize(unsigned int BAR0, unsigned int BAR1, unsigned int BAR2, unsigned int BAR3, unsigned int BAR4); uint8_t ide_ata_access(uint8_t direction, uint8_t drive, uint32_t lba, From 44db8f49b31f88a7c02b56d96a24df802c7c1c97 Mon Sep 17 00:00:00 2001 From: Real-Septicake Date: Fri, 13 Sep 2024 13:43:34 -0400 Subject: [PATCH 04/70] Print raw disk space --- src/os/hard/disk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/os/hard/disk.c b/src/os/hard/disk.c index 400790e..9e4fe4e 100644 --- a/src/os/hard/disk.c +++ b/src/os/hard/disk.c @@ -107,7 +107,7 @@ void ide_initialize(unsigned int BAR0, unsigned int BAR1, unsigned int BAR2, if(ide_devices[i].Reserved) { snprintf(buff, 256, "Found %s Drive %iGB - %s", (const char* []){"ATA", "ATAPI"}[ide_devices[i].Type], - ide_devices[i].Size / 1024 / 1024 / 2, + ide_devices[i].Size, // / 1024 / 1024 / 2, ide_devices[i].Model); println(buff, yellow); } From c62fafd4e15b925ac93d73c7c068adc83c0e59a7 Mon Sep 17 00:00:00 2001 From: Real-Septicake Date: Wed, 18 Sep 2024 18:06:31 -0400 Subject: [PATCH 05/70] Add backspace functionality --- src/lib/device/ps2.c | 10 +++++++--- src/lib/video/VGA_text.c | 9 +++++++++ src/lib/video/VGA_text.h | 1 + 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/lib/device/ps2.c b/src/lib/device/ps2.c index 603b7e4..acbbd1e 100644 --- a/src/lib/device/ps2.c +++ b/src/lib/device/ps2.c @@ -86,9 +86,13 @@ void ps2HandlerPort1(isr_registers_t *regs) { // temporary to satisfy exactly what issue #7 says if (out.keyEvent.code != Key_none && out.keyEvent.event == KeyPressed) { - char buf[2] = " "; - buf[0] = keyPressToASCII(out.keyEvent); - print(buf, white); + if (out.keyEvent.code != Key_backspace) { + char buf[2] = " "; + buf[0] = keyPressToASCII(out.keyEvent); + print(buf, white); + } else { + delete (); + } } } } diff --git a/src/lib/video/VGA_text.c b/src/lib/video/VGA_text.c index 23563ec..cf00b4c 100644 --- a/src/lib/video/VGA_text.c +++ b/src/lib/video/VGA_text.c @@ -54,6 +54,14 @@ void adjustCursor(void) { updateCursorPos(); } +static VGA_Color clearColor; +void delete (void) { + VGA_Char clearChar = getVGAchar(' ', white, clearColor); + + *--cursor = clearChar; + adjustCursor(); +} + void print(const char *str, VGA_Color color) { while (*str != 0) { // preserve background @@ -98,6 +106,7 @@ void scroll() { void clearScreen(VGA_Color color) { VGA_Char clearChr = getVGAchar(' ', white, color); + clearColor = color; clearScreenC(clearChr); } diff --git a/src/lib/video/VGA_text.h b/src/lib/video/VGA_text.h index 5f5484a..21eb17c 100644 --- a/src/lib/video/VGA_text.h +++ b/src/lib/video/VGA_text.h @@ -50,6 +50,7 @@ void writeText(const char *str, int x, int y, VGA_Color color); // affect cursor +void delete (void); // prints with wrapping, println does the same but adds a new line. void print(const char *str, VGA_Color color); void println(const char *str, VGA_Color color); From 8be1f3340e22a48ab76b8a846d8e5af846365b86 Mon Sep 17 00:00:00 2001 From: Septicake Date: Wed, 18 Sep 2024 22:02:20 -0400 Subject: [PATCH 06/70] Removed disk files from keyboard branch --- src/os/hard/disk.c | 330 --------------------------------------------- src/os/hard/disk.h | 102 -------------- 2 files changed, 432 deletions(-) delete mode 100644 src/os/hard/disk.c delete mode 100644 src/os/hard/disk.h diff --git a/src/os/hard/disk.c b/src/os/hard/disk.c deleted file mode 100644 index 9e4fe4e..0000000 --- a/src/os/hard/disk.c +++ /dev/null @@ -1,330 +0,0 @@ -#include "../../lib/stdlib/stdio.h" -#include "../../lib/pit/pit.h" -#include "../../lib/video/VGA_text.h" -#include "disk.h" -#include "port_io.h" - -static struct ide_device { - unsigned char Reserved; // 0 (Empty) or 1 (This Drive really exists). - unsigned char Channel; // 0 (Primary Channel) or 1 (Secondary Channel). - unsigned char Drive; // 0 (Master Drive) or 1 (Slave Drive). - unsigned short Type; // 0: ATA, 1:ATAPI. - unsigned short Signature; // Drive Signature - unsigned short Capabilities;// Features. - unsigned int CommandSets; // Command Sets Supported. - unsigned int Size; // Size in Sectors. - unsigned char Model[41]; // Model in string. -} ide_devices[4]; - -static struct IDEChannelRegisters { - unsigned short base; // I/O Base. - unsigned short ctrl; // Control Base - unsigned short bmide; // Bus Master IDE - unsigned char nIEN; // nIEN (No Interrupt); -} channels[2]; - -static uint8_t ide_buf[2048] = {0}; - -static void insw(uint16_t reg, uint8_t *buffer, int bytes) { - for(int i = 0; i < bytes; i++) { - buffer[i] = inb(reg); - } -} - -void ide_initialize(unsigned int BAR0, unsigned int BAR1, unsigned int BAR2, - unsigned int BAR3, unsigned int BAR4) { - int i, j, k, count = 0; - - channels[ATA_PRIMARY].base = (BAR0 & 0xFFFFFFFC) + 0x1F0 * (!BAR0); - channels[ATA_PRIMARY].ctrl = (BAR1 & 0xFFFFFFFC) + 0x3F6 * (!BAR1); - channels[ATA_SECONDARY].base = (BAR2 & 0xFFFFFFFC) + 0x170 * (!BAR2); - channels[ATA_SECONDARY].ctrl = (BAR3 & 0xFFFFFFFC) + 0x376 * (!BAR3); - channels[ATA_PRIMARY].bmide = (BAR4 & 0xFFFFFFFC) + 0; - channels[ATA_SECONDARY].bmide = (BAR4 & 0xFFFFFFFC) + 8; - - ide_write(ATA_PRIMARY, ATA_REG_CONTROL, 0b10); - ide_write(ATA_SECONDARY, ATA_REG_CONTROL, 0b10); - - for(i = 0; i < 2; i++) { - for(j = 0; j < 2; j++) { - uint8_t err = 0, type = IDE_ATA, status; - ide_devices[count].Reserved = 0; - - ide_write(i, ATA_REG_HDDEVSEL, 0xA0 | (j << 4)); - sleep(1); - - ide_write(i, ATA_REG_COMMAND, ATA_CMD_IDENTIFY); - sleep(1); - - while (1) { - status = ide_read(i, ATA_REG_STATUS); - if((status & ATA_SR_ERR)) { err = 1; break; } - if(!(status & ATA_SR_BSY) && (status & ATA_SR_DRQ)) break; - } - - if(err != 0) { - uint8_t cl = ide_read(i, ATA_REG_LBA1); - uint8_t ch = ide_read(i, ATA_REG_LBA2); - - if(cl == 0x14 && ch == 0xEB) - type = IDE_ATAPI; - else if(cl == 0x69 && ch == 0x96) - type = IDE_ATAPI; - else - continue; - - ide_write(i, ATA_REG_COMMAND, ATA_CMD_IDENTIFY_PACKET); - sleep(1); - } - - ide_read_buffer(i, ATA_REG_DATA, ide_buf, 512); - - ide_devices[count].Reserved = 1; - ide_devices[count].Type = type; - ide_devices[count].Channel = i; - ide_devices[count].Drive = j; - ide_devices[count].Signature = *((uint16_t *)(ide_buf + ATA_IDENT_DEVICETYPE)); - ide_devices[count].Capabilities = *((uint16_t *)(ide_buf + ATA_IDENT_CAPABILITIES)); - ide_devices[count].CommandSets = *((uint32_t *)(ide_buf + ATA_IDENT_COMMANDSETS)); - - if(ide_devices[count].CommandSets & (1 << 26)) - ide_devices[count].Size = *((uint32_t *)(ide_buf + ATA_IDENT_MAX_LBA_EXT)); - else - ide_devices[count].Size = *((uint32_t *)(ide_buf + ATA_IDENT_MAX_LBA)); - - for(k = 0; k < 40; k += 2) { - ide_devices[count].Model[k] = ide_buf[ATA_IDENT_MODEL + k + 1]; - ide_devices[count].Model[k + 1] = ide_buf[ATA_IDENT_MODEL + k]; - } - ide_devices[count].Model[40] = 0; - - count++; - } - } - - for(i = 0; i < 4; i++) { - char buff[256]; - if(ide_devices[i].Reserved) { - snprintf(buff, 256, "Found %s Drive %iGB - %s", - (const char* []){"ATA", "ATAPI"}[ide_devices[i].Type], - ide_devices[i].Size, // / 1024 / 1024 / 2, - ide_devices[i].Model); - println(buff, yellow); - } - } -} - -uint8_t ide_ata_access(uint8_t direction, uint8_t drive, uint32_t lba, - uint8_t numsects, uint16_t selector, uint32_t edi) { - uint8_t lba_mode, dma, cmd; - uint8_t lba_io[6]; - uint32_t channel = ide_devices[drive].Channel; - uint32_t slavebit = ide_devices[drive].Drive; - uint32_t bus = channels[channel].base; - uint32_t words = 256; - uint16_t cyl, i; - uint8_t head, sect, err; - - if(lba >= 0x10000000) { - // LBA48 - lba_mode = 2; - lba_io[0] = (lba & 0x000000FF) >> 0; - lba_io[1] = (lba & 0x0000FF00) >> 8; - lba_io[2] = (lba & 0x00FF0000) >> 16; - lba_io[3] = (lba & 0xFF000000) >> 24; - lba_io[4] = 0; - lba_io[5] = 0; - head = 0; - } else if(ide_devices[drive].Capabilities & 0x200) { - // LBA28 - lba_mode = 1; - lba_io[0] = (lba & 0x00000FF) >> 0; - lba_io[1] = (lba & 0x000FF00) >> 8; - lba_io[2] = (lba & 0x0FF0000) >> 16; - lba_io[3] = 0; - lba_io[4] = 0; - lba_io[5] = 0; - head = (lba & 0xF000000) >> 24; - } else { - // CHS - lba_mode = 0; - sect = (lba & (63 - 1)) + 1; - cyl = (lba + 1 - sect) / (16 * 63); - lba_io[0] = sect; - lba_io[1] = (cyl >> 0) & 0xFF; - lba_io[2] = (cyl >> 8) & 0xFF; - lba_io[3] = 0; - lba_io[4] = 0; - lba_io[5] = 0; - head = (lba + 1 - sect) & ((16 * 63) - 1) / 63; - } - - dma = 0; // DMA is not supported - - while(ide_read(channel, ATA_REG_STATUS) & ATA_SR_BSY); - - if(lba_mode == 0) { - ide_write(channel, ATA_REG_HDDEVSEL, 0xA0 | (slavebit << 4) | head); - } else { - ide_write(channel, ATA_REG_HDDEVSEL, 0xE0 | (slavebit << 4) | head); - } - - if(lba_mode == 2) { - ide_write(channel, ATA_REG_SECCOUNT1, 0); - ide_write(channel, ATA_REG_LBA3, lba_io[3]); - ide_write(channel, ATA_REG_LBA4, lba_io[4]); - ide_write(channel, ATA_REG_LBA5, lba_io[5]); - } - ide_write(channel, ATA_REG_SECCOUNT0, numsects); - ide_write(channel, ATA_REG_LBA0, lba_io[0]); - ide_write(channel, ATA_REG_LBA1, lba_io[1]); - ide_write(channel, ATA_REG_LBA2, lba_io[2]); - - if (lba_mode == 0 && dma == 0 && direction == 0) cmd = ATA_CMD_READ_PIO; - if (lba_mode == 1 && dma == 0 && direction == 0) cmd = ATA_CMD_READ_PIO; - if (lba_mode == 2 && dma == 0 && direction == 0) cmd = ATA_CMD_READ_PIO_EXT; - if (lba_mode == 0 && dma == 1 && direction == 0) cmd = ATA_CMD_READ_DMA; - if (lba_mode == 1 && dma == 1 && direction == 0) cmd = ATA_CMD_READ_DMA; - if (lba_mode == 2 && dma == 1 && direction == 0) cmd = ATA_CMD_READ_DMA_EXT; - if (lba_mode == 0 && dma == 0 && direction == 1) cmd = ATA_CMD_WRITE_PIO; - if (lba_mode == 1 && dma == 0 && direction == 1) cmd = ATA_CMD_WRITE_PIO; - if (lba_mode == 2 && dma == 0 && direction == 1) cmd = ATA_CMD_WRITE_PIO_EXT; - if (lba_mode == 0 && dma == 1 && direction == 1) cmd = ATA_CMD_WRITE_DMA; - if (lba_mode == 1 && dma == 1 && direction == 1) cmd = ATA_CMD_WRITE_DMA; - if (lba_mode == 2 && dma == 1 && direction == 1) cmd = ATA_CMD_WRITE_DMA_EXT; - ide_write(channel, ATA_REG_COMMAND, cmd); - - if(dma) { - if(direction == 0) { - // DMA Read - } else { - // DMA Write - } - } else { - if(direction == 0) { - for(i = 0; i < numsects; i++) { - if((err = ide_polling(channel, 1))) { - return err; - } - __asm__ volatile("pushw %es"); - __asm__ volatile("mov %%ax, %%es"::"a"(selector)); - __asm__ volatile("rep insw"::"c"(words), "d"(bus), "D"(edi)); - __asm__ volatile("popw %es"); - edi += (words * 2); - } - } else { - for(i = 0; i < numsects; i++) { - ide_polling(channel, 0); - __asm__ volatile("pushw %ds"); - __asm__ volatile("mov %%ax, %%ds"::"a"(selector)); - __asm__ volatile("rep outsw"::"c"(words), "d"(bus), "S"(edi)); - __asm__ volatile("popw %ds"); - edi += (words*2); - } - ide_write(channel, ATA_REG_COMMAND, (char []){ATA_CMD_CACHE_FLUSH, - ATA_CMD_CACHE_FLUSH, ATA_CMD_CACHE_FLUSH_EXT}[lba_mode]); - ide_polling(channel, 0); - } - } - - return 0; -} - -unsigned char ide_read(unsigned char channel, unsigned char reg) { - unsigned char result = 0; - if (reg > 0x07 && reg < 0x0C) - ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN); - if (reg < 0x08) - result = inb(channels[channel].base + reg - 0x00); - else if (reg < 0x0C) - result = inb(channels[channel].base + reg - 0x06); - else if (reg < 0x0E) - result = inb(channels[channel].ctrl + reg - 0x0A); - else if (reg < 0x16) - result = inb(channels[channel].bmide + reg - 0x0E); - if (reg > 0x07 && reg < 0x0C) - ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN); - return result; -} - -void ide_write(unsigned char channel, unsigned char reg, unsigned char data) { - if (reg > 0x07 && reg < 0x0C) - ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN); - if (reg < 0x08) - outb(channels[channel].base + reg - 0x00, data); - else if (reg < 0x0C) - outb(channels[channel].base + reg - 0x06, data); - else if (reg < 0x0E) - outb(channels[channel].ctrl + reg - 0x0A, data); - else if (reg < 0x16) - outb(channels[channel].bmide + reg - 0x0E, data); - if (reg > 0x07 && reg < 0x0C) - ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN); -} - -void ide_read_buffer(uint16_t channel, uint16_t reg, uint8_t *buffer, int bytes) { - if(reg > 0x07 && reg < 0x0C) - ide_write(channel, ATA_REG_CONTROL, 0x80 | channels[channel].nIEN); - asm("pushw %es; movw %ds, %ax; movw %ax, %es"); - if(reg < 0x08) - insw(channels[channel].base + reg - 0x00, buffer, bytes); - else if(reg < 0x0C) - insw(channels[channel].base + reg - 0x06, buffer, bytes); - else if(reg < 0x0E) - insw(channels[channel].ctrl + reg - 0x0A, buffer, bytes); - else if(reg < 0x16) - insw(channels[channel].bmide + reg - 0x0E, buffer, bytes); - asm("popw %es;"); - if(reg > 0x07 && reg < 0x0C) - ide_write(channel, ATA_REG_CONTROL, channels[channel].nIEN); -} - -uint8_t ide_polling(uint8_t channel, int advanced_check) { - for(int i = 0; i < 4; i++) - ide_read(channel, ATA_REG_ALTSTATUS); - - while(ide_read(channel, ATA_REG_STATUS) & ATA_SR_BSY); - - if(advanced_check) { - uint8_t state = ide_read(channel, ATA_REG_STATUS); - - if(state & ATA_SR_ERR) - return 2; - - if(state & ATA_SR_DF) - return 1; - - if((state & ATA_SR_DRQ) == 0) - return 3; - } - - return 0; -} - -uint8_t ide_print_error(uint32_t drive, uint8_t err) { - if(err == 0) - return err; - char buff[256]; - - snprintf(buff, 32, "IDE:"); - print(buff, red); - if(err == 1) { snprintf(buff, 32, "- Device Fault"); println(buff, red); err = 19; } - else if(err == 2) { - uint8_t st = ide_read(ide_devices[drive].Channel, ATA_REG_ERROR); - if(st & ATA_ER_AMNF) { snprintf(buff, 32, "- No Address Mark Found"); println(buff, red); err = 7; } - if(st & ATA_ER_TK0NF) { snprintf(buff, 32, "- No Media or Media Error"); println(buff, red); err = 3; } - if(st & ATA_ER_ABRT) { snprintf(buff, 32, "- Command Aborted"); println(buff, red); err = 20; } - if(st & ATA_ER_MCR) { snprintf(buff, 32, "- No Media or Media Error"); println(buff, red); err = 3; } - if(st & ATA_ER_IDNF) { snprintf(buff, 32, "- ID Mark not Found"); println(buff, red); err = 21; } - if(st & ATA_ER_MC) { snprintf(buff, 32, "- No Media or Media Error"); println(buff, red); err = 3; } - if(st & ATA_ER_UNC) { snprintf(buff, 32, "- Uncorrectable Data Error"); println(buff, red); err = 22; } - if(st & ATA_ER_BBK) { snprintf(buff, 32, "- Bad Sectors"); println(buff, red); err = 13; } - } else if(err == 3) { snprintf(buff, 32, "- Reads Nothing"); println(buff, red); err = 23; } - else if(err == 4) { snprintf(buff, 32, "- Write Protected"); println(buff, red); err = 8; } - snprintf(buff, 256, "- [%s %s] %s", - (const char* []){"Primary", "Secondary"}[ide_devices[drive].Channel], - (const char* []){"Master", "Slave"}[ide_devices[drive].Drive], - ide_devices[drive].Model); - println(buff, red); - return err; -} diff --git a/src/os/hard/disk.h b/src/os/hard/disk.h deleted file mode 100644 index 1feb9c8..0000000 --- a/src/os/hard/disk.h +++ /dev/null @@ -1,102 +0,0 @@ -#ifndef DISK_H -#define DISK_H - -#include - -// Status bit masks -#define ATA_SR_BSY 0x80 // Busy -#define ATA_SR_DRDY 0x40 // Drive ready -#define ATA_SR_DF 0x20 // Drive write fault -#define ATA_SR_DSC 0x10 // Drive seek complete -#define ATA_SR_DRQ 0x08 // Data request ready -#define ATA_SR_CORR 0x04 // Corrected data -#define ATA_SR_IDX 0x02 // Index -#define ATA_SR_ERR 0x01 // Error - -// Error bit masks -#define ATA_ER_BBK 0x80 // Bad block -#define ATA_ER_UNC 0x40 // Uncorrectable data -#define ATA_ER_MC 0x20 // Media changed -#define ATA_ER_IDNF 0x10 // ID mark not found -#define ATA_ER_MCR 0x08 // Media change request -#define ATA_ER_ABRT 0x04 // Command aborted -#define ATA_ER_TK0NF 0x02 // Track 0 not found -#define ATA_ER_AMNF 0x01 // No address mark - -// Commands -#define ATA_CMD_READ_PIO 0x20 -#define ATA_CMD_READ_PIO_EXT 0x24 -#define ATA_CMD_READ_DMA 0xC8 -#define ATA_CMD_READ_DMA_EXT 0x25 -#define ATA_CMD_WRITE_PIO 0x30 -#define ATA_CMD_WRITE_PIO_EXT 0x34 -#define ATA_CMD_WRITE_DMA 0xCA -#define ATA_CMD_WRITE_DMA_EXT 0x35 -#define ATA_CMD_CACHE_FLUSH 0xE7 -#define ATA_CMD_CACHE_FLUSH_EXT 0xEA -#define ATA_CMD_PACKET 0xA0 -#define ATA_CMD_IDENTIFY_PACKET 0xA1 -#define ATA_CMD_IDENTIFY 0xEC -// -> ATAPI commands -#define ATAPI_CMD_READ 0xA8 -#define ATAPI_CMD_EJECT 0x1B -// <- ATAPI commands - -// IDENTIFY identification space -#define ATA_IDENT_DEVICETYPE 0 -#define ATA_IDENT_CYLINDERS 2 -#define ATA_IDENT_HEADS 6 -#define ATA_IDENT_SECTORS 12 -#define ATA_IDENT_SERIAL 20 -#define ATA_IDENT_MODEL 54 -#define ATA_IDENT_CAPABILITIES 98 -#define ATA_IDENT_FIELDVALID 106 -#define ATA_IDENT_MAX_LBA 120 -#define ATA_IDENT_COMMANDSETS 164 -#define ATA_IDENT_MAX_LBA_EXT 200 - -#define IDE_ATA 0x00 -#define IDE_ATAPI 0x01 - -#define ATA_MASTER 0x00 -#define ATA_SLAVE 0x01 - -// Register offsets -#define ATA_REG_DATA 0x00 -#define ATA_REG_ERROR 0x01 -#define ATA_REG_FEATURES 0x01 -#define ATA_REG_SECCOUNT0 0x02 -#define ATA_REG_LBA0 0x03 -#define ATA_REG_LBA1 0x04 -#define ATA_REG_LBA2 0x05 -#define ATA_REG_HDDEVSEL 0x06 -#define ATA_REG_COMMAND 0x07 -#define ATA_REG_STATUS 0x07 -#define ATA_REG_SECCOUNT1 0x08 -#define ATA_REG_LBA3 0x09 -#define ATA_REG_LBA4 0x0A -#define ATA_REG_LBA5 0x0B -#define ATA_REG_CONTROL 0x0C -#define ATA_REG_ALTSTATUS 0x0C -#define ATA_REG_DEVADDRESS 0x0D - -// Channels: -#define ATA_PRIMARY 0x00 -#define ATA_SECONDARY 0x01 - -// Directions: -#define ATA_READ 0x00 -#define ATA_WRITE 0x01 - -void ide_initialize(unsigned int BAR0, unsigned int BAR1, unsigned int BAR2, unsigned int BAR3, -unsigned int BAR4); -uint8_t ide_ata_access(uint8_t direction, uint8_t drive, uint32_t lba, - uint8_t numsects, uint16_t selector, uint32_t edi); - -uint8_t ide_read(unsigned char channel, unsigned char reg); -void ide_write(unsigned char channel, unsigned char reg, unsigned char data); -void ide_read_buffer(uint16_t channel, uint16_t reg, uint8_t* buffer, int bytes); -uint8_t ide_polling(uint8_t channel, int advanced_check); -uint8_t ide_print_error(uint32_t drive, uint8_t err); - -#endif \ No newline at end of file From 6d46a1cb3f4016ca8ac3463b76ac452d27aec462 Mon Sep 17 00:00:00 2001 From: Septicake Date: Wed, 18 Sep 2024 23:35:49 -0400 Subject: [PATCH 07/70] Arrow key functionality --- src/lib/device/ps2.c | 26 ++++++++++++++++++++------ src/lib/video/VGA_text.c | 24 ++++++++++++++++++++++++ src/lib/video/VGA_text.h | 6 +++++- 3 files changed, 49 insertions(+), 7 deletions(-) diff --git a/src/lib/device/ps2.c b/src/lib/device/ps2.c index acbbd1e..b9d4b18 100644 --- a/src/lib/device/ps2.c +++ b/src/lib/device/ps2.c @@ -86,12 +86,26 @@ void ps2HandlerPort1(isr_registers_t *regs) { // temporary to satisfy exactly what issue #7 says if (out.keyEvent.code != Key_none && out.keyEvent.event == KeyPressed) { - if (out.keyEvent.code != Key_backspace) { - char buf[2] = " "; - buf[0] = keyPressToASCII(out.keyEvent); - print(buf, white); - } else { - delete (); + switch(out.keyEvent.code) { + case Key_backspace: + delete(); + break; + case Key_left: + cursorLeft(); + break; + case Key_down: + cursorDown(); + break; + case Key_up: + cursorUp(); + break; + case Key_right: + cursorRight(); + break; + default: + char buf[2] = " "; + buf[0] = keyPressToASCII(out.keyEvent); + print(buf, white); } } } diff --git a/src/lib/video/VGA_text.c b/src/lib/video/VGA_text.c index cf00b4c..b911612 100644 --- a/src/lib/video/VGA_text.c +++ b/src/lib/video/VGA_text.c @@ -62,6 +62,30 @@ void delete (void) { adjustCursor(); } +void cursorDown(void) { + if(cursor < VGA_END - VGA_WIDTH) + cursor += VGA_WIDTH; + else + cursor = VGA_END - 1; + adjustCursor(); +} + +void cursorUp(void) { + cursor -= VGA_WIDTH; + adjustCursor(); +} + +void cursorLeft(void) { + cursor--; + adjustCursor(); +} + +void cursorRight(void) { + if(cursor < VGA_END - 1) + cursor++; + adjustCursor(); +} + void print(const char *str, VGA_Color color) { while (*str != 0) { // preserve background diff --git a/src/lib/video/VGA_text.h b/src/lib/video/VGA_text.h index 21eb17c..b7fad70 100644 --- a/src/lib/video/VGA_text.h +++ b/src/lib/video/VGA_text.h @@ -50,7 +50,11 @@ void writeText(const char *str, int x, int y, VGA_Color color); // affect cursor -void delete (void); +void delete(void); +void cursorDown(void); +void cursorUp(void); +void cursorLeft(void); +void cursorRight(void); // prints with wrapping, println does the same but adds a new line. void print(const char *str, VGA_Color color); void println(const char *str, VGA_Color color); From 1efa0295163a31b26dc36e37618e06b5e71a1535 Mon Sep 17 00:00:00 2001 From: Septicake Date: Wed, 18 Sep 2024 23:38:51 -0400 Subject: [PATCH 08/70] Format and rename `delete` to `deletePrevChar` --- src/lib/device/ps2.c | 40 ++++++++++++++++++++-------------------- src/lib/video/VGA_text.c | 8 ++++---- src/lib/video/VGA_text.h | 2 +- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/lib/device/ps2.c b/src/lib/device/ps2.c index b9d4b18..2fdb9c9 100644 --- a/src/lib/device/ps2.c +++ b/src/lib/device/ps2.c @@ -86,26 +86,26 @@ void ps2HandlerPort1(isr_registers_t *regs) { // temporary to satisfy exactly what issue #7 says if (out.keyEvent.code != Key_none && out.keyEvent.event == KeyPressed) { - switch(out.keyEvent.code) { - case Key_backspace: - delete(); - break; - case Key_left: - cursorLeft(); - break; - case Key_down: - cursorDown(); - break; - case Key_up: - cursorUp(); - break; - case Key_right: - cursorRight(); - break; - default: - char buf[2] = " "; - buf[0] = keyPressToASCII(out.keyEvent); - print(buf, white); + switch (out.keyEvent.code) { + case Key_backspace: + deletePrevChar(); + break; + case Key_left: + cursorLeft(); + break; + case Key_down: + cursorDown(); + break; + case Key_up: + cursorUp(); + break; + case Key_right: + cursorRight(); + break; + default: + char buf[2] = " "; + buf[0] = keyPressToASCII(out.keyEvent); + print(buf, white); } } } diff --git a/src/lib/video/VGA_text.c b/src/lib/video/VGA_text.c index b911612..25a8e74 100644 --- a/src/lib/video/VGA_text.c +++ b/src/lib/video/VGA_text.c @@ -55,7 +55,7 @@ void adjustCursor(void) { } static VGA_Color clearColor; -void delete (void) { +void deletePrevChar(void) { VGA_Char clearChar = getVGAchar(' ', white, clearColor); *--cursor = clearChar; @@ -63,7 +63,7 @@ void delete (void) { } void cursorDown(void) { - if(cursor < VGA_END - VGA_WIDTH) + if (cursor < VGA_END - VGA_WIDTH) cursor += VGA_WIDTH; else cursor = VGA_END - 1; @@ -81,8 +81,8 @@ void cursorLeft(void) { } void cursorRight(void) { - if(cursor < VGA_END - 1) - cursor++; + if (cursor < VGA_END - 1) + cursor++; adjustCursor(); } diff --git a/src/lib/video/VGA_text.h b/src/lib/video/VGA_text.h index b7fad70..403d348 100644 --- a/src/lib/video/VGA_text.h +++ b/src/lib/video/VGA_text.h @@ -50,7 +50,7 @@ void writeText(const char *str, int x, int y, VGA_Color color); // affect cursor -void delete(void); +void deletePrevChar(void); void cursorDown(void); void cursorUp(void); void cursorLeft(void); From 271eb5d57c1aeec1635a638eb611a25ca94c41e7 Mon Sep 17 00:00:00 2001 From: Septicake Date: Wed, 18 Sep 2024 23:45:11 -0400 Subject: [PATCH 09/70] remove disk.o from makefile --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index c020e24..fae44ca 100644 --- a/Makefile +++ b/Makefile @@ -52,7 +52,7 @@ OBJ_NAMES := src/os/main.o src/os/test.o os_entry.o src/lib/video/VGA_text.o \ src/lib/device/serial.o src/lib/device/ps2.o src/lib/device/keyboard.o \ src/lib/container/ring_buffer.o \ src/lib/stdlib/stdio.o src/lib/stdlib/stdlib.o src/lib/stdlib/string.o \ - src/lib/pit/pit.o src/os/hard/disk.o + src/lib/pit/pit.o .PHONY: clean qemu test From b083109c01f506bb854f350dc7be8f7e5f6ebda2 Mon Sep 17 00:00:00 2001 From: Septicake Date: Wed, 18 Sep 2024 23:47:47 -0400 Subject: [PATCH 10/70] Added safeguards to cursor movement functions --- src/lib/video/VGA_text.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/lib/video/VGA_text.c b/src/lib/video/VGA_text.c index 25a8e74..a2839ca 100644 --- a/src/lib/video/VGA_text.c +++ b/src/lib/video/VGA_text.c @@ -58,7 +58,8 @@ static VGA_Color clearColor; void deletePrevChar(void) { VGA_Char clearChar = getVGAchar(' ', white, clearColor); - *--cursor = clearChar; + if (cursor > VGA_MEMORY) + *--cursor = clearChar; adjustCursor(); } @@ -71,12 +72,16 @@ void cursorDown(void) { } void cursorUp(void) { - cursor -= VGA_WIDTH; + if (cursor > VGA_MEMORY + VGA_WIDTH) + cursor -= VGA_WIDTH; + else + cursor = VGA_MEMORY; adjustCursor(); } void cursorLeft(void) { - cursor--; + if (cursor > VGA_MEMORY) + cursor--; adjustCursor(); } From 076ba3e2f072154a7da297e8e07b7c680b752494 Mon Sep 17 00:00:00 2001 From: Septicake Date: Thu, 19 Sep 2024 00:19:08 -0400 Subject: [PATCH 11/70] Add `delete` key functionality --- src/lib/device/ps2.c | 3 +++ src/lib/video/VGA_text.c | 8 ++++++++ src/lib/video/VGA_text.h | 1 + 3 files changed, 12 insertions(+) diff --git a/src/lib/device/ps2.c b/src/lib/device/ps2.c index 2fdb9c9..b71abb9 100644 --- a/src/lib/device/ps2.c +++ b/src/lib/device/ps2.c @@ -90,6 +90,9 @@ void ps2HandlerPort1(isr_registers_t *regs) { case Key_backspace: deletePrevChar(); break; + case Key_delete: + deleteCurrentChar(); + break; case Key_left: cursorLeft(); break; diff --git a/src/lib/video/VGA_text.c b/src/lib/video/VGA_text.c index a2839ca..01713ab 100644 --- a/src/lib/video/VGA_text.c +++ b/src/lib/video/VGA_text.c @@ -63,6 +63,14 @@ void deletePrevChar(void) { adjustCursor(); } +void deleteCurrentChar(void) { + VGA_Char clearChar = getVGAchar(' ', white, clearColor); + + if (cursor < VGA_END - 1) + *cursor++ = clearChar; + adjustCursor(); +} + void cursorDown(void) { if (cursor < VGA_END - VGA_WIDTH) cursor += VGA_WIDTH; diff --git a/src/lib/video/VGA_text.h b/src/lib/video/VGA_text.h index 403d348..4169455 100644 --- a/src/lib/video/VGA_text.h +++ b/src/lib/video/VGA_text.h @@ -51,6 +51,7 @@ void writeText(const char *str, int x, int y, VGA_Color color); // affect cursor void deletePrevChar(void); +void deleteCurrentChar(void); void cursorDown(void); void cursorUp(void); void cursorLeft(void); From 582c5f85753b22d1b4bba9bd67a66769c43192b6 Mon Sep 17 00:00:00 2001 From: Real-Septicake Date: Thu, 19 Sep 2024 13:19:21 -0400 Subject: [PATCH 12/70] Background now gotten directly from deleted character --- src/lib/video/VGA_text.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/lib/video/VGA_text.c b/src/lib/video/VGA_text.c index 01713ab..1fb8516 100644 --- a/src/lib/video/VGA_text.c +++ b/src/lib/video/VGA_text.c @@ -54,20 +54,19 @@ void adjustCursor(void) { updateCursorPos(); } -static VGA_Color clearColor; void deletePrevChar(void) { - VGA_Char clearChar = getVGAchar(' ', white, clearColor); - - if (cursor > VGA_MEMORY) + if (cursor > VGA_MEMORY) { + VGA_Char clearChar = getVGAchar(' ', white, (cursor - 1)->color >> 4); *--cursor = clearChar; + } adjustCursor(); } void deleteCurrentChar(void) { - VGA_Char clearChar = getVGAchar(' ', white, clearColor); - - if (cursor < VGA_END - 1) + if (cursor < VGA_END - 1) { + VGA_Char clearChar = getVGAchar(' ', white, cursor->color >> 4); *cursor++ = clearChar; + } adjustCursor(); } @@ -143,7 +142,6 @@ void scroll() { void clearScreen(VGA_Color color) { VGA_Char clearChr = getVGAchar(' ', white, color); - clearColor = color; clearScreenC(clearChr); } From 4717d32792d3a7e8d02a23abd117713ed21bccc0 Mon Sep 17 00:00:00 2001 From: Real-Septicake Date: Fri, 20 Sep 2024 13:58:18 -0400 Subject: [PATCH 13/70] Start work on highlighting with cursor --- src/lib/device/ps2.c | 73 +++++++++++++++++++++++++++------------- src/lib/video/VGA_text.c | 27 +++++++++++++-- src/lib/video/VGA_text.h | 2 ++ 3 files changed, 77 insertions(+), 25 deletions(-) diff --git a/src/lib/device/ps2.c b/src/lib/device/ps2.c index b71abb9..29e0506 100644 --- a/src/lib/device/ps2.c +++ b/src/lib/device/ps2.c @@ -72,6 +72,10 @@ const struct PS2Device *getPortType(int portnum) { // temporary include for #7 #include "video/VGA_text.h" +#define SIGNUM(x) ((x > 0) - (x < 0)) + +static unsigned short highlight_offset = 0; + void ps2HandlerPort1(isr_registers_t *regs) { uint8_t b = inb(PS2_DATA); @@ -86,29 +90,52 @@ void ps2HandlerPort1(isr_registers_t *regs) { // temporary to satisfy exactly what issue #7 says if (out.keyEvent.code != Key_none && out.keyEvent.event == KeyPressed) { - switch (out.keyEvent.code) { - case Key_backspace: - deletePrevChar(); - break; - case Key_delete: - deleteCurrentChar(); - break; - case Key_left: - cursorLeft(); - break; - case Key_down: - cursorDown(); - break; - case Key_up: - cursorUp(); - break; - case Key_right: - cursorRight(); - break; - default: - char buf[2] = " "; - buf[0] = keyPressToASCII(out.keyEvent); - print(buf, white); + if(!(out.keyEvent.modifiers & KEY_MOD_SHIFT)) { + switch (out.keyEvent.code) { + case Key_backspace: + deletePrevChar(); + break; + case Key_delete: + deleteCurrentChar(); + break; + case Key_left: + cursorLeft(); + break; + case Key_down: + cursorDown(); + break; + case Key_up: + cursorUp(); + break; + case Key_right: + cursorRight(); + break; + default: + char buf[2] = " "; + buf[0] = keyPressToASCII(out.keyEvent); + print(buf, white); + } + } else { + switch (out.keyEvent.code) { + case Key_left: + if(!highlight_offset) + highlightCurrentChar(); + cursorLeft(); + highlightCurrentChar(); + highlight_offset--; + break; + case Key_right: + if(!highlight_offset) + highlightCurrentChar(); + cursorRight(); + highlightCurrentChar(); + highlight_offset++; + break; + default: + char buf[2] = " "; + buf[0] = keyPressToASCII(out.keyEvent); + print(buf, white); + } } } } diff --git a/src/lib/video/VGA_text.c b/src/lib/video/VGA_text.c index 1fb8516..47f6ea1 100644 --- a/src/lib/video/VGA_text.c +++ b/src/lib/video/VGA_text.c @@ -27,6 +27,18 @@ void writeText(const char *str, int x, int y, VGA_Color color) { } } +static inline VGA_Color invert(VGA_Color color) { + return 15 - (unsigned)color; +} + +void highlightChar(unsigned short charPos) { + if (VGA_END - VGA_MEMORY < charPos) + return; + + VGA_Char highlighted = (VGA_MEMORY[charPos]); + VGA_MEMORY[charPos] = getVGAchar(highlighted.chr, invert(highlighted.color & 0xf), invert((highlighted.color >> 4) & 0xf)); +} + void updateCursorPos(void) { // evil (but useful) pointer arithmetic @@ -54,9 +66,17 @@ void adjustCursor(void) { updateCursorPos(); } +void highlightCurrentChar(void) { + uint16_t pos = (cursor - VGA_MEMORY); + highlightChar(pos); +} + +#define CLEAR_CHAR(ptr) (getVGAchar(' ', white, (ptr)->color >> 4)) + void deletePrevChar(void) { if (cursor > VGA_MEMORY) { - VGA_Char clearChar = getVGAchar(' ', white, (cursor - 1)->color >> 4); + // preserve background + VGA_Char clearChar = CLEAR_CHAR(cursor - 1); *--cursor = clearChar; } adjustCursor(); @@ -64,12 +84,15 @@ void deletePrevChar(void) { void deleteCurrentChar(void) { if (cursor < VGA_END - 1) { - VGA_Char clearChar = getVGAchar(' ', white, cursor->color >> 4); + // preserve background + VGA_Char clearChar = CLEAR_CHAR(cursor); *cursor++ = clearChar; } adjustCursor(); } +#undef CLEAR_CHAR + void cursorDown(void) { if (cursor < VGA_END - VGA_WIDTH) cursor += VGA_WIDTH; diff --git a/src/lib/video/VGA_text.h b/src/lib/video/VGA_text.h index 4169455..0339312 100644 --- a/src/lib/video/VGA_text.h +++ b/src/lib/video/VGA_text.h @@ -48,6 +48,8 @@ VGA_Char getVGAchar(unsigned char chr, VGA_Color foreground, // prints text at location, will NOT wrap void writeText(const char *str, int x, int y, VGA_Color color); +void highlightCurrentChar(void); + // affect cursor void deletePrevChar(void); From 005f8058928956430e7ce802727d475b83b5dde0 Mon Sep 17 00:00:00 2001 From: Septicake Date: Fri, 20 Sep 2024 17:32:27 -0400 Subject: [PATCH 14/70] Continue working on highlighting --- src/lib/device/ps2.c | 111 ++++++++++++++++++++++----------------- src/lib/video/VGA_text.c | 20 +++++-- src/lib/video/VGA_text.h | 3 ++ 3 files changed, 82 insertions(+), 52 deletions(-) diff --git a/src/lib/device/ps2.c b/src/lib/device/ps2.c index 29e0506..cdede3e 100644 --- a/src/lib/device/ps2.c +++ b/src/lib/device/ps2.c @@ -74,7 +74,57 @@ const struct PS2Device *getPortType(int portnum) { #define SIGNUM(x) ((x > 0) - (x < 0)) -static unsigned short highlight_offset = 0; +static int highlight_offset = 0; + +void specialHandler(struct PS2Buf_t out) { + if (!(out.keyEvent.modifiers & KEY_MOD_SHIFT)) { + switch (out.keyEvent.code) { + case Key_backspace: + deletePrevChar(); + break; + case Key_delete: + deleteCurrentChar(); + break; + case Key_left: + cursorLeft(); + break; + case Key_down: + cursorDown(); + break; + case Key_up: + cursorUp(); + break; + case Key_right: + cursorRight(); + break; + default: + break; + } + } else { + switch (out.keyEvent.code) { + case Key_left: + if (!cursorIsAtStart()) { + if (!highlight_offset || highlight_offset == 1) + highlightCurrentChar(); + cursorLeft(); + highlightCurrentChar(); + highlight_offset--; + } + break; + case Key_right: + if (!cursorIsAtEnd()) { + if (!highlight_offset || highlight_offset == -1) + highlightCurrentChar(); + cursorRight(); + highlightCurrentChar(); + highlight_offset++; + } + break; + default: + break; + } + } +} void ps2HandlerPort1(isr_registers_t *regs) { uint8_t b = inb(PS2_DATA); @@ -90,52 +140,19 @@ void ps2HandlerPort1(isr_registers_t *regs) { // temporary to satisfy exactly what issue #7 says if (out.keyEvent.code != Key_none && out.keyEvent.event == KeyPressed) { - if(!(out.keyEvent.modifiers & KEY_MOD_SHIFT)) { - switch (out.keyEvent.code) { - case Key_backspace: - deletePrevChar(); - break; - case Key_delete: - deleteCurrentChar(); - break; - case Key_left: - cursorLeft(); - break; - case Key_down: - cursorDown(); - break; - case Key_up: - cursorUp(); - break; - case Key_right: - cursorRight(); - break; - default: - char buf[2] = " "; - buf[0] = keyPressToASCII(out.keyEvent); - print(buf, white); - } - } else { - switch (out.keyEvent.code) { - case Key_left: - if(!highlight_offset) - highlightCurrentChar(); - cursorLeft(); - highlightCurrentChar(); - highlight_offset--; - break; - case Key_right: - if(!highlight_offset) - highlightCurrentChar(); - cursorRight(); - highlightCurrentChar(); - highlight_offset++; - break; - default: - char buf[2] = " "; - buf[0] = keyPressToASCII(out.keyEvent); - print(buf, white); - } + switch (out.keyEvent.code) { + case Key_backspace: + case Key_delete: + case Key_left: + case Key_down: + case Key_up: + case Key_right: + specialHandler(out); + break; + default: + char buf[2] = " "; + buf[0] = keyPressToASCII(out.keyEvent); + print(buf, white); } } } diff --git a/src/lib/video/VGA_text.c b/src/lib/video/VGA_text.c index 47f6ea1..a41c4fc 100644 --- a/src/lib/video/VGA_text.c +++ b/src/lib/video/VGA_text.c @@ -27,6 +27,14 @@ void writeText(const char *str, int x, int y, VGA_Color color) { } } +inline int cursorIsAtStart() { + return cursor == VGA_MEMORY; +} + +inline int cursorIsAtEnd() { + return cursor == VGA_END - 1; +} + static inline VGA_Color invert(VGA_Color color) { return 15 - (unsigned)color; } @@ -36,7 +44,9 @@ void highlightChar(unsigned short charPos) { return; VGA_Char highlighted = (VGA_MEMORY[charPos]); - VGA_MEMORY[charPos] = getVGAchar(highlighted.chr, invert(highlighted.color & 0xf), invert((highlighted.color >> 4) & 0xf)); + VGA_MEMORY[charPos] = + getVGAchar(highlighted.chr, invert(highlighted.color & 0xf), + invert((highlighted.color >> 4) & 0xf)); } void updateCursorPos(void) { @@ -74,7 +84,7 @@ void highlightCurrentChar(void) { #define CLEAR_CHAR(ptr) (getVGAchar(' ', white, (ptr)->color >> 4)) void deletePrevChar(void) { - if (cursor > VGA_MEMORY) { + if (!cursorIsAtStart()) { // preserve background VGA_Char clearChar = CLEAR_CHAR(cursor - 1); *--cursor = clearChar; @@ -83,7 +93,7 @@ void deletePrevChar(void) { } void deleteCurrentChar(void) { - if (cursor < VGA_END - 1) { + if (!cursorIsAtEnd()) { // preserve background VGA_Char clearChar = CLEAR_CHAR(cursor); *cursor++ = clearChar; @@ -110,13 +120,13 @@ void cursorUp(void) { } void cursorLeft(void) { - if (cursor > VGA_MEMORY) + if (!cursorIsAtStart()) cursor--; adjustCursor(); } void cursorRight(void) { - if (cursor < VGA_END - 1) + if (!cursorIsAtEnd()) cursor++; adjustCursor(); } diff --git a/src/lib/video/VGA_text.h b/src/lib/video/VGA_text.h index 0339312..f332cf0 100644 --- a/src/lib/video/VGA_text.h +++ b/src/lib/video/VGA_text.h @@ -48,6 +48,9 @@ VGA_Char getVGAchar(unsigned char chr, VGA_Color foreground, // prints text at location, will NOT wrap void writeText(const char *str, int x, int y, VGA_Color color); +int cursorIsAtStart(void); +int cursorIsAtEnd(void); + void highlightCurrentChar(void); // affect cursor From 861ebd041b9e6e68d5fdbcfa4b8536de6ea4219e Mon Sep 17 00:00:00 2001 From: Septicake Date: Fri, 20 Sep 2024 19:43:24 -0400 Subject: [PATCH 15/70] Cursor movement after highlighting done, still need to work on deletion --- src/lib/device/ps2.c | 26 +++++++++++---- src/lib/video/VGA_text.c | 72 +++++++++++++++++++++++++++++++++------- src/lib/video/VGA_text.h | 4 +++ 3 files changed, 84 insertions(+), 18 deletions(-) diff --git a/src/lib/device/ps2.c b/src/lib/device/ps2.c index cdede3e..abf3a65 100644 --- a/src/lib/device/ps2.c +++ b/src/lib/device/ps2.c @@ -72,8 +72,6 @@ const struct PS2Device *getPortType(int portnum) { // temporary include for #7 #include "video/VGA_text.h" -#define SIGNUM(x) ((x > 0) - (x < 0)) - static int highlight_offset = 0; void specialHandler(struct PS2Buf_t out) { @@ -86,16 +84,32 @@ void specialHandler(struct PS2Buf_t out) { deleteCurrentChar(); break; case Key_left: - cursorLeft(); + if (highlight_offset) { + cursorHighlightLeft(highlight_offset); + highlight_offset = 0; + } else + cursorLeft(); break; case Key_down: - cursorDown(); + if(highlight_offset) { + cursorHighlightDown(highlight_offset); + highlight_offset = 0; + } else + cursorDown(); break; case Key_up: - cursorUp(); + if(highlight_offset) { + cursorHighlightUp(highlight_offset); + highlight_offset = 0; + } else + cursorUp(); break; case Key_right: - cursorRight(); + if (highlight_offset) { + cursorHighlightRight(highlight_offset); + highlight_offset = 0; + } else + cursorRight(); break; default: break; diff --git a/src/lib/video/VGA_text.c b/src/lib/video/VGA_text.c index a41c4fc..bb04cde 100644 --- a/src/lib/video/VGA_text.c +++ b/src/lib/video/VGA_text.c @@ -39,16 +39,6 @@ static inline VGA_Color invert(VGA_Color color) { return 15 - (unsigned)color; } -void highlightChar(unsigned short charPos) { - if (VGA_END - VGA_MEMORY < charPos) - return; - - VGA_Char highlighted = (VGA_MEMORY[charPos]); - VGA_MEMORY[charPos] = - getVGAchar(highlighted.chr, invert(highlighted.color & 0xf), - invert((highlighted.color >> 4) & 0xf)); -} - void updateCursorPos(void) { // evil (but useful) pointer arithmetic @@ -77,8 +67,8 @@ void adjustCursor(void) { } void highlightCurrentChar(void) { - uint16_t pos = (cursor - VGA_MEMORY); - highlightChar(pos); + *cursor = getVGAchar(cursor->chr, invert(cursor->color & 0xf), + invert((cursor->color >> 4) & 0xf)); } #define CLEAR_CHAR(ptr) (getVGAchar(' ', white, (ptr)->color >> 4)) @@ -103,6 +93,22 @@ void deleteCurrentChar(void) { #undef CLEAR_CHAR +#define SIGNUM(x) ((x > 0) - (x < 0)) + +void cursorHighlightDown(int offset) { + cursor -= offset; + int sign = SIGNUM(offset); + int abs_offset = SIGNUM(offset) * offset; + for(int i = abs_offset; i >= 0; i--) { + *cursor = getVGAchar(cursor->chr, invert(cursor->color & 0xf), + invert((cursor->color >> 4) & 0xf)); + cursor += sign; + } + cursor -= sign; + cursorDown(); + adjustCursor(); +} + void cursorDown(void) { if (cursor < VGA_END - VGA_WIDTH) cursor += VGA_WIDTH; @@ -111,6 +117,20 @@ void cursorDown(void) { adjustCursor(); } +void cursorHighlightUp(int offset) { + cursor -= offset; + int sign = SIGNUM(offset); + int abs_offset = SIGNUM(offset) * offset; + for(int i = abs_offset; i >= 0; i--) { + *cursor = getVGAchar(cursor->chr, invert(cursor->color & 0xf), + invert((cursor->color >> 4) & 0xf)); + cursor += sign; + } + cursor -= sign; + cursorUp(); + adjustCursor(); +} + void cursorUp(void) { if (cursor > VGA_MEMORY + VGA_WIDTH) cursor -= VGA_WIDTH; @@ -119,18 +139,46 @@ void cursorUp(void) { adjustCursor(); } +void cursorHighlightLeft(int offset) { + if (offset < 0) + cursor -= offset; + int abs_offset = SIGNUM(offset) * offset; + for (int i = abs_offset; i >= 0; i--) { + *cursor = getVGAchar(cursor->chr, invert(cursor->color & 0xf), + invert((cursor->color >> 4) & 0xf)); + cursor--; + } + cursor++; + adjustCursor(); +} + void cursorLeft(void) { if (!cursorIsAtStart()) cursor--; adjustCursor(); } +void cursorHighlightRight(int offset) { + if (offset > 0) + cursor -= offset; + int abs_offset = SIGNUM(offset) * offset; + for (int i = abs_offset; i >= 0; i--) { + *cursor = getVGAchar(cursor->chr, invert(cursor->color & 0xf), + invert((cursor->color >> 4) & 0xf)); + cursor++; + } + cursor--; + adjustCursor(); +} + void cursorRight(void) { if (!cursorIsAtEnd()) cursor++; adjustCursor(); } +#undef SIGNUM + void print(const char *str, VGA_Color color) { while (*str != 0) { // preserve background diff --git a/src/lib/video/VGA_text.h b/src/lib/video/VGA_text.h index f332cf0..81b9556 100644 --- a/src/lib/video/VGA_text.h +++ b/src/lib/video/VGA_text.h @@ -57,9 +57,13 @@ void highlightCurrentChar(void); void deletePrevChar(void); void deleteCurrentChar(void); +void cursorHighlightDown(int offset); void cursorDown(void); +void cursorHighlightUp(int offset); void cursorUp(void); +void cursorHighlightLeft(int offset); void cursorLeft(void); +void cursorHighlightRight(int offset); void cursorRight(void); // prints with wrapping, println does the same but adds a new line. void print(const char *str, VGA_Color color); From 43a9b3f14a9b52b752a9a103c0ec8d0404bc6c23 Mon Sep 17 00:00:00 2001 From: Septicake Date: Fri, 20 Sep 2024 20:44:13 -0400 Subject: [PATCH 16/70] Format --- src/lib/device/ps2.c | 4 ++-- src/lib/video/VGA_text.c | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/lib/device/ps2.c b/src/lib/device/ps2.c index abf3a65..2690bdf 100644 --- a/src/lib/device/ps2.c +++ b/src/lib/device/ps2.c @@ -91,14 +91,14 @@ void specialHandler(struct PS2Buf_t out) { cursorLeft(); break; case Key_down: - if(highlight_offset) { + if (highlight_offset) { cursorHighlightDown(highlight_offset); highlight_offset = 0; } else cursorDown(); break; case Key_up: - if(highlight_offset) { + if (highlight_offset) { cursorHighlightUp(highlight_offset); highlight_offset = 0; } else diff --git a/src/lib/video/VGA_text.c b/src/lib/video/VGA_text.c index bb04cde..d850356 100644 --- a/src/lib/video/VGA_text.c +++ b/src/lib/video/VGA_text.c @@ -68,7 +68,7 @@ void adjustCursor(void) { void highlightCurrentChar(void) { *cursor = getVGAchar(cursor->chr, invert(cursor->color & 0xf), - invert((cursor->color >> 4) & 0xf)); + invert((cursor->color >> 4) & 0xf)); } #define CLEAR_CHAR(ptr) (getVGAchar(' ', white, (ptr)->color >> 4)) @@ -99,9 +99,9 @@ void cursorHighlightDown(int offset) { cursor -= offset; int sign = SIGNUM(offset); int abs_offset = SIGNUM(offset) * offset; - for(int i = abs_offset; i >= 0; i--) { + for (int i = abs_offset; i >= 0; i--) { *cursor = getVGAchar(cursor->chr, invert(cursor->color & 0xf), - invert((cursor->color >> 4) & 0xf)); + invert((cursor->color >> 4) & 0xf)); cursor += sign; } cursor -= sign; @@ -121,9 +121,9 @@ void cursorHighlightUp(int offset) { cursor -= offset; int sign = SIGNUM(offset); int abs_offset = SIGNUM(offset) * offset; - for(int i = abs_offset; i >= 0; i--) { + for (int i = abs_offset; i >= 0; i--) { *cursor = getVGAchar(cursor->chr, invert(cursor->color & 0xf), - invert((cursor->color >> 4) & 0xf)); + invert((cursor->color >> 4) & 0xf)); cursor += sign; } cursor -= sign; @@ -145,7 +145,7 @@ void cursorHighlightLeft(int offset) { int abs_offset = SIGNUM(offset) * offset; for (int i = abs_offset; i >= 0; i--) { *cursor = getVGAchar(cursor->chr, invert(cursor->color & 0xf), - invert((cursor->color >> 4) & 0xf)); + invert((cursor->color >> 4) & 0xf)); cursor--; } cursor++; @@ -164,7 +164,7 @@ void cursorHighlightRight(int offset) { int abs_offset = SIGNUM(offset) * offset; for (int i = abs_offset; i >= 0; i--) { *cursor = getVGAchar(cursor->chr, invert(cursor->color & 0xf), - invert((cursor->color >> 4) & 0xf)); + invert((cursor->color >> 4) & 0xf)); cursor++; } cursor--; From cbfa9e5ab981d0852af5e440d28bcc723fb0ef4a Mon Sep 17 00:00:00 2001 From: Real-Septicake Date: Wed, 25 Sep 2024 17:16:36 -0400 Subject: [PATCH 17/70] Fixed moving cursor backwards while continuing to highlight --- src/lib/device/ps2.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/lib/device/ps2.c b/src/lib/device/ps2.c index 2690bdf..a5fcefe 100644 --- a/src/lib/device/ps2.c +++ b/src/lib/device/ps2.c @@ -118,20 +118,34 @@ void specialHandler(struct PS2Buf_t out) { switch (out.keyEvent.code) { case Key_left: if (!cursorIsAtStart()) { - if (!highlight_offset || highlight_offset == 1) + if (!highlight_offset) highlightCurrentChar(); - cursorLeft(); - highlightCurrentChar(); + if (highlight_offset > 0) { + highlightCurrentChar(); + cursorLeft(); + } else { + cursorLeft(); + highlightCurrentChar(); + } highlight_offset--; + if (!highlight_offset) + highlightCurrentChar(); } break; case Key_right: if (!cursorIsAtEnd()) { - if (!highlight_offset || highlight_offset == -1) + if (!highlight_offset) highlightCurrentChar(); - cursorRight(); - highlightCurrentChar(); + if (highlight_offset < 0) { + highlightCurrentChar(); + cursorRight(); + } else { + cursorRight(); + highlightCurrentChar(); + } highlight_offset++; + if (!highlight_offset) + highlightCurrentChar(); } break; default: From d1b08acc53e6cb0a16d1626ba14d840d91b1db96 Mon Sep 17 00:00:00 2001 From: Real-Septicake Date: Wed, 9 Oct 2024 17:25:58 -0400 Subject: [PATCH 18/70] Add Key_up and Key_down functionality for highlighting --- src/lib/device/ps2.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/lib/device/ps2.c b/src/lib/device/ps2.c index a5fcefe..bacf656 100644 --- a/src/lib/device/ps2.c +++ b/src/lib/device/ps2.c @@ -116,6 +116,42 @@ void specialHandler(struct PS2Buf_t out) { } } else { switch (out.keyEvent.code) { + case Key_up: + if (!cursorIsAtStart()) { + if (!highlight_offset) + highlightCurrentChar(); + for (int i = 0; i < VGA_WIDTH && !cursorIsAtStart(); i++) { + if (highlight_offset > 0) { + highlightCurrentChar(); + cursorLeft(); + } else { + cursorLeft(); + highlightCurrentChar(); + } + highlight_offset--; + } + if (!highlight_offset) + highlightCurrentChar(); + } + break; + case Key_down: + if(!cursorIsAtEnd()) { + if (!highlight_offset) + highlightCurrentChar(); + for (int i = 0; i < VGA_WIDTH && !cursorIsAtEnd(); i++) { + if (highlight_offset < 0) { + highlightCurrentChar(); + cursorRight(); + } else { + cursorRight(); + highlightCurrentChar(); + } + highlight_offset++; + } + if (!highlight_offset) + highlightCurrentChar(); + } + break; case Key_left: if (!cursorIsAtStart()) { if (!highlight_offset) From 01234241cb8791ce8b557b7fdc7fb15d3c507abc Mon Sep 17 00:00:00 2001 From: Real-Septicake Date: Wed, 9 Oct 2024 17:26:20 -0400 Subject: [PATCH 19/70] Format --- src/lib/device/ps2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/device/ps2.c b/src/lib/device/ps2.c index bacf656..82ca60e 100644 --- a/src/lib/device/ps2.c +++ b/src/lib/device/ps2.c @@ -135,7 +135,7 @@ void specialHandler(struct PS2Buf_t out) { } break; case Key_down: - if(!cursorIsAtEnd()) { + if (!cursorIsAtEnd()) { if (!highlight_offset) highlightCurrentChar(); for (int i = 0; i < VGA_WIDTH && !cursorIsAtEnd(); i++) { From 519681a79733fb7dc0c1191a5529a7783f5343f2 Mon Sep 17 00:00:00 2001 From: Real-Septicake Date: Wed, 9 Oct 2024 17:58:44 -0400 Subject: [PATCH 20/70] Add support for deletion while highlighting --- src/lib/device/ps2.c | 12 ++++++++++-- src/lib/video/VGA_text.c | 34 ++++++++++++++++++++++++++++++---- src/lib/video/VGA_text.h | 7 +++++++ 3 files changed, 47 insertions(+), 6 deletions(-) diff --git a/src/lib/device/ps2.c b/src/lib/device/ps2.c index 82ca60e..80a803e 100644 --- a/src/lib/device/ps2.c +++ b/src/lib/device/ps2.c @@ -78,10 +78,18 @@ void specialHandler(struct PS2Buf_t out) { if (!(out.keyEvent.modifiers & KEY_MOD_SHIFT)) { switch (out.keyEvent.code) { case Key_backspace: - deletePrevChar(); + if (highlight_offset) { + highlightDeletePrev(highlight_offset); + highlight_offset = 0; + } else + deletePrevChar(); break; case Key_delete: - deleteCurrentChar(); + if (highlight_offset) { + highlightDeleteCurrent(highlight_offset); + highlight_offset = 0; + } else + deleteCurrentChar(); break; case Key_left: if (highlight_offset) { diff --git a/src/lib/video/VGA_text.c b/src/lib/video/VGA_text.c index d850356..487bfa1 100644 --- a/src/lib/video/VGA_text.c +++ b/src/lib/video/VGA_text.c @@ -73,6 +73,21 @@ void highlightCurrentChar(void) { #define CLEAR_CHAR(ptr) (getVGAchar(' ', white, (ptr)->color >> 4)) +#define SIGNUM(x) (((x) > 0) - ((x) < 0)) + +void highlightDeletePrev(int offset) { + if (offset < 0) + cursor -= offset; + int abs_offset = SIGNUM(offset) * offset; + for (int i = abs_offset; i >= 0; i--) { + highlightCurrentChar(); + *cursor = CLEAR_CHAR(cursor); + cursor--; + } + cursor++; + adjustCursor(); +} + void deletePrevChar(void) { if (!cursorIsAtStart()) { // preserve background @@ -82,6 +97,19 @@ void deletePrevChar(void) { adjustCursor(); } +void highlightDeleteCurrent(int offset) { + if (offset > 0) + cursor -= offset; + int abs_offset = SIGNUM(offset) * offset; + for (int i = abs_offset; i >= 0; i--) { + highlightCurrentChar(); + *cursor = CLEAR_CHAR(cursor); + cursor++; + } + cursor--; + adjustCursor(); +} + void deleteCurrentChar(void) { if (!cursorIsAtEnd()) { // preserve background @@ -93,12 +121,10 @@ void deleteCurrentChar(void) { #undef CLEAR_CHAR -#define SIGNUM(x) ((x > 0) - (x < 0)) - void cursorHighlightDown(int offset) { cursor -= offset; int sign = SIGNUM(offset); - int abs_offset = SIGNUM(offset) * offset; + int abs_offset = sign * offset; for (int i = abs_offset; i >= 0; i--) { *cursor = getVGAchar(cursor->chr, invert(cursor->color & 0xf), invert((cursor->color >> 4) & 0xf)); @@ -120,7 +146,7 @@ void cursorDown(void) { void cursorHighlightUp(int offset) { cursor -= offset; int sign = SIGNUM(offset); - int abs_offset = SIGNUM(offset) * offset; + int abs_offset = sign * offset; for (int i = abs_offset; i >= 0; i--) { *cursor = getVGAchar(cursor->chr, invert(cursor->color & 0xf), invert((cursor->color >> 4) & 0xf)); diff --git a/src/lib/video/VGA_text.h b/src/lib/video/VGA_text.h index 81b9556..c6ff36b 100644 --- a/src/lib/video/VGA_text.h +++ b/src/lib/video/VGA_text.h @@ -55,14 +55,21 @@ void highlightCurrentChar(void); // affect cursor +void highlightDeletePrev(int offset); void deletePrevChar(void); + +void highlightDeleteCurrent(int offset); void deleteCurrentChar(void); + void cursorHighlightDown(int offset); void cursorDown(void); + void cursorHighlightUp(int offset); void cursorUp(void); + void cursorHighlightLeft(int offset); void cursorLeft(void); + void cursorHighlightRight(int offset); void cursorRight(void); // prints with wrapping, println does the same but adds a new line. From 8d0f74bc56eb5c566da6f888b596e4fc2a047e2b Mon Sep 17 00:00:00 2001 From: Real-Septicake Date: Wed, 9 Oct 2024 18:21:40 -0400 Subject: [PATCH 21/70] Delete highlighted characters when beginning to type with highlighted text --- src/lib/device/ps2.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/lib/device/ps2.c b/src/lib/device/ps2.c index 80a803e..3618db8 100644 --- a/src/lib/device/ps2.c +++ b/src/lib/device/ps2.c @@ -222,6 +222,10 @@ void ps2HandlerPort1(isr_registers_t *regs) { specialHandler(out); break; default: + if(highlight_offset) { + highlightDeletePrev(highlight_offset); + highlight_offset = 0; + } char buf[2] = " "; buf[0] = keyPressToASCII(out.keyEvent); print(buf, white); From a1c34bf953b8f24903a516ba9f79deeccfb686e8 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 23 Oct 2024 17:24:02 -0400 Subject: [PATCH 22/70] Initial code/changes for testing the keyboard/editing functionality. --- src/lib/device/ps2.c | 40 ++++++++++--------- src/lib/device/ps2.h | 4 +- .../expected/lib/stdlib/test_keyboard.expect | 1 + tests/src/lib/stdlib/test_keyboard.c | 27 +++++++++++++ 4 files changed, 53 insertions(+), 19 deletions(-) create mode 100644 tests/expected/lib/stdlib/test_keyboard.expect create mode 100644 tests/src/lib/stdlib/test_keyboard.c diff --git a/src/lib/device/ps2.c b/src/lib/device/ps2.c index 3618db8..8c11876 100644 --- a/src/lib/device/ps2.c +++ b/src/lib/device/ps2.c @@ -198,6 +198,27 @@ void specialHandler(struct PS2Buf_t out) { } } +void vgaEditor(struct PS2Buf_t out) { + switch (out.keyEvent.code) { + case Key_backspace: + case Key_delete: + case Key_left: + case Key_down: + case Key_up: + case Key_right: + specialHandler(out); + break; + default: + if(highlight_offset) { + highlightDeletePrev(highlight_offset); + highlight_offset = 0; + } + char buf[2] = " "; + buf[0] = keyPressToASCII(out.keyEvent); + print(buf, white); + } +} + void ps2HandlerPort1(isr_registers_t *regs) { uint8_t b = inb(PS2_DATA); @@ -212,24 +233,7 @@ void ps2HandlerPort1(isr_registers_t *regs) { // temporary to satisfy exactly what issue #7 says if (out.keyEvent.code != Key_none && out.keyEvent.event == KeyPressed) { - switch (out.keyEvent.code) { - case Key_backspace: - case Key_delete: - case Key_left: - case Key_down: - case Key_up: - case Key_right: - specialHandler(out); - break; - default: - if(highlight_offset) { - highlightDeletePrev(highlight_offset); - highlight_offset = 0; - } - char buf[2] = " "; - buf[0] = keyPressToASCII(out.keyEvent); - print(buf, white); - } + vgaEditor(out); } } } diff --git a/src/lib/device/ps2.h b/src/lib/device/ps2.h index fd3ea1a..333088a 100644 --- a/src/lib/device/ps2.h +++ b/src/lib/device/ps2.h @@ -69,6 +69,8 @@ struct PS2Buf_t { int ps2Init(); const struct PS2Device *getPortType(int portnum); +void vgaEditor(struct PS2Buf_t out); + bool ps2Present(void); bool ps2Port1Present(void); bool ps2Port2Present(void); @@ -84,4 +86,4 @@ struct PS2Buf_t popDev1(void); struct PS2Buf_t peekDev2(void); struct PS2Buf_t popDev2(void); -#endif \ No newline at end of file +#endif diff --git a/tests/expected/lib/stdlib/test_keyboard.expect b/tests/expected/lib/stdlib/test_keyboard.expect new file mode 100644 index 0000000..f68e0f9 --- /dev/null +++ b/tests/expected/lib/stdlib/test_keyboard.expect @@ -0,0 +1 @@ +test_keyboard done diff --git a/tests/src/lib/stdlib/test_keyboard.c b/tests/src/lib/stdlib/test_keyboard.c new file mode 100644 index 0000000..75a3b59 --- /dev/null +++ b/tests/src/lib/stdlib/test_keyboard.c @@ -0,0 +1,27 @@ +#include "../../test_helper.h" +#include "../../../../src/lib/device/keyboard.h" +#include "../../../../src/lib/device/ps2.h" +#include "stdio.h" +#include "string.h" + +#include + +struct PS2Buf_t kb (enum KeyCode code, enum KeyState event, uint8_t modifiers) { + KeyPress kp = (KeyPress){0, code, event, modifiers}; + struct PS2Buf_t b = (struct PS2Buf_t){PS2_KEY_EVENT, {.keyEvent = kp}}; + return b; +} + +void test_main() { + #define NUMKEYS 2 + struct PS2Buf_t b[NUMKEYS] = { + kb(Key_a, KeyPressed, 0), + kb(Key_b, KeyPressed, 0), + }; + for (int i = 0; i < NUMKEYS; i++) { + vgaEditor(b[i]); + } + ASSERT(1); + char done[] = "test_keyboard done\n"; + serialWrite(COM1, (uint8_t *)(done), sizeof(done) - 1); +} From 7efa7393908913c67a9deb1a6c408a6efd3cc880 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 23 Oct 2024 18:15:19 -0400 Subject: [PATCH 23/70] Added basic test framework for keyboard. --- src/lib/device/ps2.c | 2 +- tests/src/lib/stdlib/test_keyboard.c | 57 +++++++++++++++++++++++----- 2 files changed, 49 insertions(+), 10 deletions(-) diff --git a/src/lib/device/ps2.c b/src/lib/device/ps2.c index 8c11876..9068bff 100644 --- a/src/lib/device/ps2.c +++ b/src/lib/device/ps2.c @@ -72,7 +72,7 @@ const struct PS2Device *getPortType(int portnum) { // temporary include for #7 #include "video/VGA_text.h" -static int highlight_offset = 0; +int highlight_offset = 0; void specialHandler(struct PS2Buf_t out) { if (!(out.keyEvent.modifiers & KEY_MOD_SHIFT)) { diff --git a/tests/src/lib/stdlib/test_keyboard.c b/tests/src/lib/stdlib/test_keyboard.c index 75a3b59..905a07f 100644 --- a/tests/src/lib/stdlib/test_keyboard.c +++ b/tests/src/lib/stdlib/test_keyboard.c @@ -1,27 +1,66 @@ #include "../../test_helper.h" #include "../../../../src/lib/device/keyboard.h" #include "../../../../src/lib/device/ps2.h" +#include "../../../../src/lib/video/VGA_text.h" #include "stdio.h" #include "string.h" #include -struct PS2Buf_t kb (enum KeyCode code, enum KeyState event, uint8_t modifiers) { +extern int highlight_offset; + +enum CMD {keyPress, checkOffset, end}; + +struct TestCMD { + enum CMD cmd; + union { + struct PS2Buf_t kb; + int offset; + } data; +}; + +struct TestCMD kbCMD(enum KeyCode code, enum KeyState event, uint8_t modifiers) { KeyPress kp = (KeyPress){0, code, event, modifiers}; struct PS2Buf_t b = (struct PS2Buf_t){PS2_KEY_EVENT, {.keyEvent = kp}}; - return b; + return (struct TestCMD){keyPress, {.kb = b}}; +} + +struct TestCMD chkOffCMD(int expected) { + return (struct TestCMD){checkOffset, {.offset = expected}}; +} + +struct TestCMD endCMD() { + return (struct TestCMD){end, {}}; +} + +void execCMD(struct TestCMD cmd) { + switch (cmd.cmd) { + case checkOffset: + ASSERT_M(highlight_offset == cmd.data.offset, "Highlight difference | "); + break; + case keyPress: + vgaEditor(cmd.data.kb); + break; + case end: + break; + } } void test_main() { - #define NUMKEYS 2 - struct PS2Buf_t b[NUMKEYS] = { - kb(Key_a, KeyPressed, 0), - kb(Key_b, KeyPressed, 0), + //VGA_Char* vm = VGA_MEMORY; + struct TestCMD b[] = { + kbCMD(Key_a, KeyPressed, 0), + chkOffCMD(0), + kbCMD(Key_left, KeyPressed, KEY_MOD_SHIFT), + chkOffCMD(-1), + kbCMD(Key_b, KeyPressed, 0), + chkOffCMD(0), + // Remember to end command sequence! + endCMD(), }; - for (int i = 0; i < NUMKEYS; i++) { - vgaEditor(b[i]); + for (int i = 0; b[i].cmd != end; i++) { + execCMD(b[i]); } - ASSERT(1); char done[] = "test_keyboard done\n"; serialWrite(COM1, (uint8_t *)(done), sizeof(done) - 1); } From 7962b2cadfbaa947e46200a6f7913d2e93d8cd80 Mon Sep 17 00:00:00 2001 From: Septicake Date: Wed, 23 Oct 2024 19:15:35 -0400 Subject: [PATCH 24/70] Organize functions a bit more --- src/lib/video/VGA_text.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/lib/video/VGA_text.h b/src/lib/video/VGA_text.h index 81b9556..8b63af2 100644 --- a/src/lib/video/VGA_text.h +++ b/src/lib/video/VGA_text.h @@ -55,16 +55,25 @@ void highlightCurrentChar(void); // affect cursor +// deletion + void deletePrevChar(void); void deleteCurrentChar(void); + +// movement + void cursorHighlightDown(int offset); void cursorDown(void); + void cursorHighlightUp(int offset); void cursorUp(void); + void cursorHighlightLeft(int offset); void cursorLeft(void); + void cursorHighlightRight(int offset); void cursorRight(void); + // prints with wrapping, println does the same but adds a new line. void print(const char *str, VGA_Color color); void println(const char *str, VGA_Color color); From ef7fb26fd2fb598766acaa54847be7de5b32ffc2 Mon Sep 17 00:00:00 2001 From: Septicake Date: Wed, 23 Oct 2024 20:53:58 -0400 Subject: [PATCH 25/70] Add highlight deletion functions to header file --- src/lib/video/VGA_text.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/lib/video/VGA_text.h b/src/lib/video/VGA_text.h index 8b63af2..cb0770c 100644 --- a/src/lib/video/VGA_text.h +++ b/src/lib/video/VGA_text.h @@ -57,7 +57,10 @@ void highlightCurrentChar(void); // deletion +void highlightDeletePrev(int offset); void deletePrevChar(void); + +void highlightDeleteCurrent(int offset); void deleteCurrentChar(void); // movement From 65353b791519075e28c2c141fba12eae9e3f1755 Mon Sep 17 00:00:00 2001 From: Septicake Date: Wed, 23 Oct 2024 23:06:22 -0400 Subject: [PATCH 26/70] Add further testing --- tests/src/lib/stdlib/test_keyboard.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/tests/src/lib/stdlib/test_keyboard.c b/tests/src/lib/stdlib/test_keyboard.c index 905a07f..b54eb66 100644 --- a/tests/src/lib/stdlib/test_keyboard.c +++ b/tests/src/lib/stdlib/test_keyboard.c @@ -8,6 +8,9 @@ #include extern int highlight_offset; +extern VGA_Char *cursor; + +int init_pos; enum CMD {keyPress, checkOffset, end}; @@ -47,14 +50,22 @@ void execCMD(struct TestCMD cmd) { } void test_main() { - //VGA_Char* vm = VGA_MEMORY; + init_pos = cursor - VGA_MEMORY; struct TestCMD b[] = { kbCMD(Key_a, KeyPressed, 0), chkOffCMD(0), kbCMD(Key_left, KeyPressed, KEY_MOD_SHIFT), chkOffCMD(-1), + kbCMD(Key_up, KeyPressed, KEY_MOD_SHIFT), + chkOffCMD(-81), + kbCMD(Key_up, KeyPressed, KEY_MOD_SHIFT), + chkOffCMD(-161), kbCMD(Key_b, KeyPressed, 0), chkOffCMD(0), + kbCMD(Key_down, KeyPressed, KEY_MOD_SHIFT), + chkOffCMD(80), + kbCMD(Key_up, KeyPressed, 0), + chkOffCMD(0), // Remember to end command sequence! endCMD(), }; From 71705df5525fb460c608bcfa60e19df1a3715bde Mon Sep 17 00:00:00 2001 From: Septicake Date: Thu, 24 Oct 2024 03:03:16 -0400 Subject: [PATCH 27/70] Add information on what tests timed out, and added a space after the time taken --- tests/test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test.py b/tests/test.py index c7d6769..7514e3f 100644 --- a/tests/test.py +++ b/tests/test.py @@ -269,7 +269,7 @@ def test(instance: TestInstance): return test_end_stub(instance, passed) except socket.timeout: - print("test timed out") + print(instance.bin_path.name + " | test timed out") except socket.error as e: @@ -348,7 +348,7 @@ def do_tests(): for instance in instances: instance.end() - print("All tests completed in " + str(time.time() - start) + "seconds") + print("All tests completed in " + str(time.time() - start) + " seconds") total_fail = 0 total_pass = 0 From 8b1c041ec27daba6e1390bee5f640b1db38a7f2a Mon Sep 17 00:00:00 2001 From: Septicake Date: Thu, 24 Oct 2024 03:22:01 -0400 Subject: [PATCH 28/70] Add check command for cursor position relative to beginning of vga memory --- tests/src/lib/stdlib/test_keyboard.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/tests/src/lib/stdlib/test_keyboard.c b/tests/src/lib/stdlib/test_keyboard.c index b54eb66..2c1706e 100644 --- a/tests/src/lib/stdlib/test_keyboard.c +++ b/tests/src/lib/stdlib/test_keyboard.c @@ -12,7 +12,7 @@ extern VGA_Char *cursor; int init_pos; -enum CMD {keyPress, checkOffset, end}; +enum CMD {keyPress, checkOffset, checkPosition, end}; struct TestCMD { enum CMD cmd; @@ -32,6 +32,11 @@ struct TestCMD chkOffCMD(int expected) { return (struct TestCMD){checkOffset, {.offset = expected}}; } +// expected position is relative to the beginning of vga memory +struct TestCMD chkPosCMD(unsigned expected) { + return (struct TestCMD){checkPosition, {.offset = expected}}; +} + struct TestCMD endCMD() { return (struct TestCMD){end, {}}; } @@ -41,6 +46,9 @@ void execCMD(struct TestCMD cmd) { case checkOffset: ASSERT_M(highlight_offset == cmd.data.offset, "Highlight difference | "); break; + case checkPosition: + ASSERT_M(cursor - VGA_MEMORY == cmd.data.offset, "Position difference | "); + break; case keyPress: vgaEditor(cmd.data.kb); break; @@ -52,14 +60,19 @@ void execCMD(struct TestCMD cmd) { void test_main() { init_pos = cursor - VGA_MEMORY; struct TestCMD b[] = { + chkPosCMD(init_pos), kbCMD(Key_a, KeyPressed, 0), chkOffCMD(0), + chkPosCMD(init_pos + 1), kbCMD(Key_left, KeyPressed, KEY_MOD_SHIFT), chkOffCMD(-1), + chkPosCMD(init_pos), kbCMD(Key_up, KeyPressed, KEY_MOD_SHIFT), chkOffCMD(-81), + chkPosCMD(init_pos - 80), kbCMD(Key_up, KeyPressed, KEY_MOD_SHIFT), chkOffCMD(-161), + chkPosCMD(0), kbCMD(Key_b, KeyPressed, 0), chkOffCMD(0), kbCMD(Key_down, KeyPressed, KEY_MOD_SHIFT), From 220e308fda2cda4a5ca87f388f76cc8c4a13d548 Mon Sep 17 00:00:00 2001 From: Septicake Date: Thu, 24 Oct 2024 03:33:27 -0400 Subject: [PATCH 29/70] Add more position checks to current test command sequence --- tests/src/lib/stdlib/test_keyboard.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/src/lib/stdlib/test_keyboard.c b/tests/src/lib/stdlib/test_keyboard.c index 2c1706e..7ff84d9 100644 --- a/tests/src/lib/stdlib/test_keyboard.c +++ b/tests/src/lib/stdlib/test_keyboard.c @@ -75,10 +75,13 @@ void test_main() { chkPosCMD(0), kbCMD(Key_b, KeyPressed, 0), chkOffCMD(0), + chkPosCMD(1), kbCMD(Key_down, KeyPressed, KEY_MOD_SHIFT), chkOffCMD(80), + chkPosCMD(81), kbCMD(Key_up, KeyPressed, 0), chkOffCMD(0), + chkPosCMD(1), // Remember to end command sequence! endCMD(), }; From f145797a8fc2a75b15a65a4bf9b724876d8860b8 Mon Sep 17 00:00:00 2001 From: Septicake Date: Thu, 24 Oct 2024 04:17:08 -0400 Subject: [PATCH 30/70] Documentation and formatting --- src/lib/device/ps2.c | 2 +- tests/src/lib/stdlib/test_keyboard.c | 29 +++++++++++++++++++--------- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/lib/device/ps2.c b/src/lib/device/ps2.c index 9068bff..0a32bf5 100644 --- a/src/lib/device/ps2.c +++ b/src/lib/device/ps2.c @@ -209,7 +209,7 @@ void vgaEditor(struct PS2Buf_t out) { specialHandler(out); break; default: - if(highlight_offset) { + if (highlight_offset) { highlightDeletePrev(highlight_offset); highlight_offset = 0; } diff --git a/tests/src/lib/stdlib/test_keyboard.c b/tests/src/lib/stdlib/test_keyboard.c index 7ff84d9..74e3451 100644 --- a/tests/src/lib/stdlib/test_keyboard.c +++ b/tests/src/lib/stdlib/test_keyboard.c @@ -1,7 +1,7 @@ -#include "../../test_helper.h" #include "../../../../src/lib/device/keyboard.h" #include "../../../../src/lib/device/ps2.h" #include "../../../../src/lib/video/VGA_text.h" +#include "../../test_helper.h" #include "stdio.h" #include "string.h" @@ -12,7 +12,8 @@ extern VGA_Char *cursor; int init_pos; -enum CMD {keyPress, checkOffset, checkPosition, end}; +// enum representing the kinds of commands available +enum CMD { keyPress, checkOffset, checkPosition, end }; struct TestCMD { enum CMD cmd; @@ -22,37 +23,47 @@ struct TestCMD { } data; }; -struct TestCMD kbCMD(enum KeyCode code, enum KeyState event, uint8_t modifiers) { +// creates a simulated key press command +struct TestCMD kbCMD(enum KeyCode code, enum KeyState event, + uint8_t modifiers) { KeyPress kp = (KeyPress){0, code, event, modifiers}; struct PS2Buf_t b = (struct PS2Buf_t){PS2_KEY_EVENT, {.keyEvent = kp}}; return (struct TestCMD){keyPress, {.kb = b}}; } +// creates an offset check command struct TestCMD chkOffCMD(int expected) { return (struct TestCMD){checkOffset, {.offset = expected}}; } +// creates a position check command // expected position is relative to the beginning of vga memory struct TestCMD chkPosCMD(unsigned expected) { return (struct TestCMD){checkPosition, {.offset = expected}}; } +// creates an end command struct TestCMD endCMD() { return (struct TestCMD){end, {}}; } void execCMD(struct TestCMD cmd) { switch (cmd.cmd) { - case checkOffset: - ASSERT_M(highlight_offset == cmd.data.offset, "Highlight difference | "); + case checkOffset: // asserts that the current highlight offset matches the + // supplied offset + ASSERT_M(highlight_offset == cmd.data.offset, + "Highlight difference | "); break; - case checkPosition: - ASSERT_M(cursor - VGA_MEMORY == cmd.data.offset, "Position difference | "); + case checkPosition: // asserts that the relative position from the start of + // vga memory matches the supplied position + ASSERT_M(cursor - VGA_MEMORY == cmd.data.offset, + "Position difference | "); break; - case keyPress: + case keyPress: // simulates a keypress vgaEditor(cmd.data.kb); break; - case end: + case end: // end command has no effect on state, it is only used as a + // terminator break; } } From 57f951176851bf28c4c3f07a670529942e72a10b Mon Sep 17 00:00:00 2001 From: Real-Septicake Date: Thu, 24 Oct 2024 16:05:41 -0400 Subject: [PATCH 31/70] Add logging for the starting and ending of tests --- tests/test.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/test.py b/tests/test.py index 7514e3f..0df63f6 100644 --- a/tests/test.py +++ b/tests/test.py @@ -112,6 +112,7 @@ def beginQemu(self): self._qemu = subprocess.Popen(command, stdin=subprocess.PIPE, stderr=subprocess.PIPE, stdout=subprocess.PIPE) time.sleep(1) #give qemu some time to open self._ready = True + print(self.bin_path.name + " has started.") def beginTest(self): self.test = Thread(target=test, args=[self]) @@ -137,9 +138,11 @@ def endQemu(self): except: # force qemu to quit since it refuses to exit normally self._qemu.kill() + print(self.bin_path.name + " was forcefully closed.") self._qemu = None self._ready = False + print(self.bin_path.name + " has exited.") os.remove(self._qemu_file) def end(self): From c4cfbd30b67debdf927b74690e0f386a53f57c3d Mon Sep 17 00:00:00 2001 From: Real-Septicake Date: Thu, 24 Oct 2024 16:07:08 -0400 Subject: [PATCH 32/70] remove `init_pos` from the keyboard test --- tests/src/lib/stdlib/test_keyboard.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/tests/src/lib/stdlib/test_keyboard.c b/tests/src/lib/stdlib/test_keyboard.c index 74e3451..1a1029b 100644 --- a/tests/src/lib/stdlib/test_keyboard.c +++ b/tests/src/lib/stdlib/test_keyboard.c @@ -10,8 +10,6 @@ extern int highlight_offset; extern VGA_Char *cursor; -int init_pos; - // enum representing the kinds of commands available enum CMD { keyPress, checkOffset, checkPosition, end }; @@ -69,18 +67,19 @@ void execCMD(struct TestCMD cmd) { } void test_main() { - init_pos = cursor - VGA_MEMORY; struct TestCMD b[] = { - chkPosCMD(init_pos), + // The position checks assume that only 2 lines of text have been + // written during boot + chkPosCMD(160), kbCMD(Key_a, KeyPressed, 0), chkOffCMD(0), - chkPosCMD(init_pos + 1), + chkPosCMD(161), kbCMD(Key_left, KeyPressed, KEY_MOD_SHIFT), chkOffCMD(-1), - chkPosCMD(init_pos), + chkPosCMD(160), kbCMD(Key_up, KeyPressed, KEY_MOD_SHIFT), chkOffCMD(-81), - chkPosCMD(init_pos - 80), + chkPosCMD(80), kbCMD(Key_up, KeyPressed, KEY_MOD_SHIFT), chkOffCMD(-161), chkPosCMD(0), From 4ac7b90ae32d98f06efabd7bb47b2207afa1c7fa Mon Sep 17 00:00:00 2001 From: Septicake Date: Thu, 24 Oct 2024 21:53:57 -0400 Subject: [PATCH 33/70] Correct lack of mutex usage for getting number of active instances --- tests/test.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/test.py b/tests/test.py index 0df63f6..1ec4cea 100644 --- a/tests/test.py +++ b/tests/test.py @@ -291,8 +291,12 @@ def test(instance: TestInstance): def create_instance(bin_path, expected_path): - while (active_instances > MAX_INSTANCES): - time.sleep(0.5) + while (True): + with instance_mutex: + if(active_instances >= MAX_INSTANCES): + time.sleep(0.5) + else: + break instance = TestInstance(get_port(), bin_path, expected_path) instance.start() From 8e3b16e59878c5178de771d0d2f1b9e3c4973c19 Mon Sep 17 00:00:00 2001 From: Real-Septicake Date: Wed, 30 Oct 2024 19:12:57 -0400 Subject: [PATCH 34/70] Fix lack of increment in %i and %s in stdio.c --- src/lib/stdlib/stdio.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib/stdlib/stdio.c b/src/lib/stdlib/stdio.c index 16e634b..5fb0744 100644 --- a/src/lib/stdlib/stdio.c +++ b/src/lib/stdlib/stdio.c @@ -54,6 +54,7 @@ int vsnprintf(char *restrict buffer, size_t bufsz, char *format, va_list ap) { if (len + n + 1 < bufsz) { memcpy(buffer, s, len); buffer += len; + n += len - 1; } else { return n; } @@ -88,6 +89,7 @@ int vsnprintf(char *restrict buffer, size_t bufsz, char *format, va_list ap) { if (bufSize + n + 1 < bufsz) { itoa_s(i, buffer, MAX_SNPRINTF_STRING - n); buffer += bufSize; + n += bufSize - 1; } else { return n; } From 3e2a07c69247c102edf816005a48b3bfba0ad8fa Mon Sep 17 00:00:00 2001 From: Real-Septicake Date: Wed, 30 Oct 2024 19:13:19 -0400 Subject: [PATCH 35/70] Add way to print values for debugging in ASSERT_M --- tests/src/test_helper.h | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/tests/src/test_helper.h b/tests/src/test_helper.h index 24fe1bd..e6f33fb 100644 --- a/tests/src/test_helper.h +++ b/tests/src/test_helper.h @@ -2,6 +2,28 @@ #define TEST_HELPER_H #include "device/serial.h" +#include "stdio.h" + +#include + +void _assert_fail_m(char *fmt, const char *assertion, const char *file, + unsigned line, const char *function, ...) { + va_list args; + va_start(args, function); + char buff[1024]; + char errfmt[] = "%s:%i Assertion '%s' failed.\n"; + int len = snprintf(buff, 1024, errfmt, file, line, assertion); + while (!serialWriteReady(COM1)) + ; + serialWrite(COM1, (uint8_t *)buff, len); + + len = vsnprintf(buff, 1024, fmt, args); + while (!serialWriteReady(COM1)) + ; + serialWrite(COM1, (uint8_t *)buff, len); + + va_end(args); +} #define AS_STR(x) #x @@ -9,13 +31,10 @@ #define _STR_LINE(line) AS_STR(line) #define STR_LINE _STR_LINE(__LINE__) -#define ASSERT_M(condition, msg) \ +#define ASSERT_M(condition, fmt, ...) \ if (!(condition)) { \ - while (!serialWriteReady(COM1)) \ - ; \ - char errmsg[] = \ - msg AS_STR(condition) " failed in " __FILE__ ":" STR_LINE "\n"; \ - serialWrite(COM1, (uint8_t *)(errmsg), sizeof(errmsg) - 1); \ + _assert_fail_m(fmt "\n", #condition, __FILE__, __LINE__, \ + __func__ __VA_OPT__(, ) __VA_ARGS__); \ } #define ASSERT(condition) ASSERT_M(condition, "") From 26048c5dea1e8f791f9292bd1a2328904c4cf707 Mon Sep 17 00:00:00 2001 From: Real-Septicake Date: Wed, 30 Oct 2024 19:33:35 -0400 Subject: [PATCH 36/70] Fix edge case of input of %i being 0 --- src/lib/stdlib/stdio.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib/stdlib/stdio.c b/src/lib/stdlib/stdio.c index 5fb0744..6ba5dd9 100644 --- a/src/lib/stdlib/stdio.c +++ b/src/lib/stdlib/stdio.c @@ -83,6 +83,8 @@ int vsnprintf(char *restrict buffer, size_t bufsz, char *format, va_list ap) { } for (; temp >= 1; temp = temp / 10, bufSize++) ; + if(i == 0) + bufSize++; // checks if there is space for the entire string // plus the null-terminating byte From b6618ee13b57aeaad686ebfdce31ae4f2b1e52a4 Mon Sep 17 00:00:00 2001 From: Real-Septicake Date: Wed, 30 Oct 2024 19:34:40 -0400 Subject: [PATCH 37/70] test_keyboard now uses new assert macro, chkPosCMD now takes line and column positions --- tests/src/lib/stdlib/test_keyboard.c | 40 +++++++++++++++++++--------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/tests/src/lib/stdlib/test_keyboard.c b/tests/src/lib/stdlib/test_keyboard.c index 1a1029b..6ae16a2 100644 --- a/tests/src/lib/stdlib/test_keyboard.c +++ b/tests/src/lib/stdlib/test_keyboard.c @@ -11,7 +11,7 @@ extern int highlight_offset; extern VGA_Char *cursor; // enum representing the kinds of commands available -enum CMD { keyPress, checkOffset, checkPosition, end }; +enum CMD { keyPress, checkOffset, checkPosition, setPosition, end }; struct TestCMD { enum CMD cmd; @@ -36,8 +36,13 @@ struct TestCMD chkOffCMD(int expected) { // creates a position check command // expected position is relative to the beginning of vga memory -struct TestCMD chkPosCMD(unsigned expected) { - return (struct TestCMD){checkPosition, {.offset = expected}}; +struct TestCMD chkPosCMD(unsigned line, unsigned col) { + return (struct TestCMD){checkPosition, + {.offset = (line * VGA_WIDTH) + col}}; +} + +struct TestCMD setPosCMD(unsigned line, unsigned col) { + return (struct TestCMD){setPosition, {.offset = (line * VGA_WIDTH) + col}}; } // creates an end command @@ -50,12 +55,17 @@ void execCMD(struct TestCMD cmd) { case checkOffset: // asserts that the current highlight offset matches the // supplied offset ASSERT_M(highlight_offset == cmd.data.offset, - "Highlight difference | "); + "Highlight difference | Expected: %i, Actual: %i", + cmd.data.offset, highlight_offset); break; case checkPosition: // asserts that the relative position from the start of // vga memory matches the supplied position ASSERT_M(cursor - VGA_MEMORY == cmd.data.offset, - "Position difference | "); + "Position difference | Expected: %i, Actual: %i", + cmd.data.offset, cursor - VGA_MEMORY); + break; + case setPosition: + cursor = VGA_MEMORY + cmd.data.offset; break; case keyPress: // simulates a keypress vgaEditor(cmd.data.kb); @@ -67,31 +77,35 @@ void execCMD(struct TestCMD cmd) { } void test_main() { + cursor = VGA_MEMORY + 160; struct TestCMD b[] = { // The position checks assume that only 2 lines of text have been // written during boot - chkPosCMD(160), + chkPosCMD(2, 0), kbCMD(Key_a, KeyPressed, 0), chkOffCMD(0), - chkPosCMD(161), + chkPosCMD(2, 1), kbCMD(Key_left, KeyPressed, KEY_MOD_SHIFT), chkOffCMD(-1), - chkPosCMD(160), + chkPosCMD(2, 0), kbCMD(Key_up, KeyPressed, KEY_MOD_SHIFT), chkOffCMD(-81), - chkPosCMD(80), + chkPosCMD(1, 0), kbCMD(Key_up, KeyPressed, KEY_MOD_SHIFT), chkOffCMD(-161), - chkPosCMD(0), + chkPosCMD(0, 0), kbCMD(Key_b, KeyPressed, 0), chkOffCMD(0), - chkPosCMD(1), + chkPosCMD(0, 1), kbCMD(Key_down, KeyPressed, KEY_MOD_SHIFT), chkOffCMD(80), - chkPosCMD(81), + chkPosCMD(1, 1), kbCMD(Key_up, KeyPressed, 0), chkOffCMD(0), - chkPosCMD(1), + chkPosCMD(0, 1), + setPosCMD(0, 79), + kbCMD(Key_right, KeyPressed, 0), + chkPosCMD(1, 0), // Remember to end command sequence! endCMD(), }; From 65ffe5c4d6774402286c946f21fe2aa8428a3079 Mon Sep 17 00:00:00 2001 From: Real-Septicake Date: Thu, 31 Oct 2024 12:41:07 -0400 Subject: [PATCH 38/70] Use the already present `len` variable instead of creating `bufSize` --- src/lib/stdlib/stdio.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/lib/stdlib/stdio.c b/src/lib/stdlib/stdio.c index 6ba5dd9..43e7552 100644 --- a/src/lib/stdlib/stdio.c +++ b/src/lib/stdlib/stdio.c @@ -76,22 +76,22 @@ int vsnprintf(char *restrict buffer, size_t bufsz, char *format, va_list ap) { case 'i': i = va_arg(ap, int); int temp = i; - int bufSize = 0; + len = 0; if (i < 0) { - bufSize++; + len++; temp *= -1; } - for (; temp >= 1; temp = temp / 10, bufSize++) + for (; temp >= 1; temp = temp / 10, len++) ; if(i == 0) - bufSize++; + len++; // checks if there is space for the entire string // plus the null-terminating byte - if (bufSize + n + 1 < bufsz) { + if (len + n + 1 < bufsz) { itoa_s(i, buffer, MAX_SNPRINTF_STRING - n); - buffer += bufSize; - n += bufSize - 1; + buffer += len; + n += len - 1; } else { return n; } From eeee2afe04e1fc34352e6187c8b6756e90dff8f3 Mon Sep 17 00:00:00 2001 From: Real-Septicake Date: Thu, 31 Oct 2024 12:54:12 -0400 Subject: [PATCH 39/70] Add utilities to prevent a change in the size of the VGA from completely breaking the keyboard test, as well as formatting --- src/lib/stdlib/stdio.c | 2 +- tests/src/lib/stdlib/test_keyboard.c | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/lib/stdlib/stdio.c b/src/lib/stdlib/stdio.c index 43e7552..968c8be 100644 --- a/src/lib/stdlib/stdio.c +++ b/src/lib/stdlib/stdio.c @@ -83,7 +83,7 @@ int vsnprintf(char *restrict buffer, size_t bufsz, char *format, va_list ap) { } for (; temp >= 1; temp = temp / 10, len++) ; - if(i == 0) + if (i == 0) len++; // checks if there is space for the entire string diff --git a/tests/src/lib/stdlib/test_keyboard.c b/tests/src/lib/stdlib/test_keyboard.c index 6ae16a2..475541c 100644 --- a/tests/src/lib/stdlib/test_keyboard.c +++ b/tests/src/lib/stdlib/test_keyboard.c @@ -7,6 +7,9 @@ #include +// in case changes are made to the width of the screen text +#define END_COL (VGA_WIDTH - 1) + extern int highlight_offset; extern VGA_Char *cursor; @@ -89,23 +92,25 @@ void test_main() { chkOffCMD(-1), chkPosCMD(2, 0), kbCMD(Key_up, KeyPressed, KEY_MOD_SHIFT), - chkOffCMD(-81), + chkOffCMD(-VGA_WIDTH - 1), chkPosCMD(1, 0), kbCMD(Key_up, KeyPressed, KEY_MOD_SHIFT), - chkOffCMD(-161), + chkOffCMD(-(2 * VGA_WIDTH) - 1), chkPosCMD(0, 0), kbCMD(Key_b, KeyPressed, 0), chkOffCMD(0), chkPosCMD(0, 1), kbCMD(Key_down, KeyPressed, KEY_MOD_SHIFT), - chkOffCMD(80), + chkOffCMD(VGA_WIDTH), chkPosCMD(1, 1), kbCMD(Key_up, KeyPressed, 0), chkOffCMD(0), chkPosCMD(0, 1), - setPosCMD(0, 79), + setPosCMD(0, END_COL), kbCMD(Key_right, KeyPressed, 0), chkPosCMD(1, 0), + kbCMD(Key_left, KeyPressed, 0), + chkPosCMD(0, END_COL), // Remember to end command sequence! endCMD(), }; From 4b2857718ce180e132bd0518ca6de56ef6653ea4 Mon Sep 17 00:00:00 2001 From: Real-Septicake Date: Thu, 31 Oct 2024 13:13:03 -0400 Subject: [PATCH 40/70] Documentation --- tests/src/lib/stdlib/test_keyboard.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/src/lib/stdlib/test_keyboard.c b/tests/src/lib/stdlib/test_keyboard.c index 475541c..38b5b08 100644 --- a/tests/src/lib/stdlib/test_keyboard.c +++ b/tests/src/lib/stdlib/test_keyboard.c @@ -8,6 +8,7 @@ #include // in case changes are made to the width of the screen text +// we still have a portable way of selecting the final column #define END_COL (VGA_WIDTH - 1) extern int highlight_offset; @@ -44,6 +45,8 @@ struct TestCMD chkPosCMD(unsigned line, unsigned col) { {.offset = (line * VGA_WIDTH) + col}}; } +// creates a set position command +// position is relative to the beginning of VGA memory struct TestCMD setPosCMD(unsigned line, unsigned col) { return (struct TestCMD){setPosition, {.offset = (line * VGA_WIDTH) + col}}; } @@ -53,6 +56,7 @@ struct TestCMD endCMD() { return (struct TestCMD){end, {}}; } +// execute the supplied command based on its `cmd` field void execCMD(struct TestCMD cmd) { switch (cmd.cmd) { case checkOffset: // asserts that the current highlight offset matches the @@ -67,7 +71,8 @@ void execCMD(struct TestCMD cmd) { "Position difference | Expected: %i, Actual: %i", cmd.data.offset, cursor - VGA_MEMORY); break; - case setPosition: + case setPosition: // sets the cursor position, checks that the position is in bounds + cursor = VGA_MEMORY + cmd.data.offset; break; case keyPress: // simulates a keypress From 7673409f30e63b4e2575f1df49d9ced8b2eb102d Mon Sep 17 00:00:00 2001 From: Real-Septicake Date: Thu, 31 Oct 2024 14:06:04 -0400 Subject: [PATCH 41/70] Added macro that fails when reached, added logic to both assert and fail to prevent empty lines --- tests/src/test_helper.h | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/tests/src/test_helper.h b/tests/src/test_helper.h index e6f33fb..1762809 100644 --- a/tests/src/test_helper.h +++ b/tests/src/test_helper.h @@ -12,16 +12,37 @@ void _assert_fail_m(char *fmt, const char *assertion, const char *file, va_start(args, function); char buff[1024]; char errfmt[] = "%s:%i Assertion '%s' failed.\n"; - int len = snprintf(buff, 1024, errfmt, file, line, assertion); + int len = snprintf(buff, 1024, errfmt, function, line, assertion); while (!serialWriteReady(COM1)) ; serialWrite(COM1, (uint8_t *)buff, len); - len = vsnprintf(buff, 1024, fmt, args); + if (fmt[0] != 0) { + len = vsnprintf(buff, 1024, fmt, args); + while (!serialWriteReady(COM1)) + ; + serialWrite(COM1, (uint8_t *)buff, len); + } + + va_end(args); +} + +void _fail_m(char *fmt, unsigned line, const char *function, ...) { + va_list args; + va_start(args, function); + char buff[1024]; + char errfmt[] = "%s:%i Fail assertion reached.\n"; + int len = snprintf(buff, 1024, errfmt, function, line); while (!serialWriteReady(COM1)) ; serialWrite(COM1, (uint8_t *)buff, len); + if (fmt[0] != 0) { + len = vsnprintf(buff, 1024, fmt, args); + while (!serialWriteReady(COM1)) + ; + serialWrite(COM1, (uint8_t *)buff, len); + } va_end(args); } @@ -37,6 +58,9 @@ void _assert_fail_m(char *fmt, const char *assertion, const char *file, __func__ __VA_OPT__(, ) __VA_ARGS__); \ } +#define FAIL_M(fmt, ...) \ + _fail_m(fmt "\n", __LINE__, __func__ __VA_OPT__(, ) __VA_ARGS__) + #define ASSERT(condition) ASSERT_M(condition, "") #endif \ No newline at end of file From edabc13f161d919a06360508f5be0139ef654ed3 Mon Sep 17 00:00:00 2001 From: Real-Septicake Date: Thu, 31 Oct 2024 14:08:44 -0400 Subject: [PATCH 42/70] Allow for execCMD to return a non-zero value to represent a fatal error and add more tests --- tests/src/lib/stdlib/test_keyboard.c | 32 +++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/tests/src/lib/stdlib/test_keyboard.c b/tests/src/lib/stdlib/test_keyboard.c index 38b5b08..e363b62 100644 --- a/tests/src/lib/stdlib/test_keyboard.c +++ b/tests/src/lib/stdlib/test_keyboard.c @@ -8,8 +8,9 @@ #include // in case changes are made to the width of the screen text -// we still have a portable way of selecting the final column +// we still have a portable way of selecting the specific positions #define END_COL (VGA_WIDTH - 1) +#define END_LINE (VGA_HEIGHT - 1) extern int highlight_offset; extern VGA_Char *cursor; @@ -57,7 +58,7 @@ struct TestCMD endCMD() { } // execute the supplied command based on its `cmd` field -void execCMD(struct TestCMD cmd) { +int execCMD(struct TestCMD cmd) { switch (cmd.cmd) { case checkOffset: // asserts that the current highlight offset matches the // supplied offset @@ -71,8 +72,12 @@ void execCMD(struct TestCMD cmd) { "Position difference | Expected: %i, Actual: %i", cmd.data.offset, cursor - VGA_MEMORY); break; - case setPosition: // sets the cursor position, checks that the position is in bounds - + case setPosition: // sets the cursor position, checks that the position is + // in bounds + if(cmd.data.offset < 0 || cmd.data.offset >= VGA_SIZE) { + FAIL_M("Offset of %i is out of bounds for VGA of length %i.", cmd.data.offset, VGA_SIZE); + return 1; + } cursor = VGA_MEMORY + cmd.data.offset; break; case keyPress: // simulates a keypress @@ -81,7 +86,11 @@ void execCMD(struct TestCMD cmd) { case end: // end command has no effect on state, it is only used as a // terminator break; + default: + FAIL_M("Unexpected command type: %i", cmd.cmd); + return 1; } + return 0; } void test_main() { @@ -116,11 +125,24 @@ void test_main() { chkPosCMD(1, 0), kbCMD(Key_left, KeyPressed, 0), chkPosCMD(0, END_COL), + setPosCMD(END_LINE, 0), + kbCMD(Key_down, KeyPressed, 0), + chkPosCMD(END_LINE, END_COL), + kbCMD(Key_up, KeyPressed, KEY_MOD_SHIFT), + kbCMD(Key_down, KeyPressed, 0), + chkPosCMD(END_LINE, END_COL), // Remember to end command sequence! endCMD(), }; for (int i = 0; b[i].cmd != end; i++) { - execCMD(b[i]); + if (execCMD(b[i])) { + char err[] = "test_keyboard errored at command "; + serialWrite(COM1, (uint8_t *)err, sizeof(err) - 1); + char buf[4]; + int len = snprintf(buf, 4, "%i", i); + serialWrite(COM1, (uint8_t *)buf, len); + return; + } } char done[] = "test_keyboard done\n"; serialWrite(COM1, (uint8_t *)(done), sizeof(done) - 1); From b27fc07c6f32b34c98e182a2f17f0256b8923e3b Mon Sep 17 00:00:00 2001 From: Real-Septicake Date: Thu, 31 Oct 2024 14:10:45 -0400 Subject: [PATCH 43/70] Formatting --- tests/src/lib/stdlib/test_keyboard.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/src/lib/stdlib/test_keyboard.c b/tests/src/lib/stdlib/test_keyboard.c index e363b62..4f30551 100644 --- a/tests/src/lib/stdlib/test_keyboard.c +++ b/tests/src/lib/stdlib/test_keyboard.c @@ -74,8 +74,9 @@ int execCMD(struct TestCMD cmd) { break; case setPosition: // sets the cursor position, checks that the position is // in bounds - if(cmd.data.offset < 0 || cmd.data.offset >= VGA_SIZE) { - FAIL_M("Offset of %i is out of bounds for VGA of length %i.", cmd.data.offset, VGA_SIZE); + if (cmd.data.offset < 0 || cmd.data.offset >= VGA_SIZE) { + FAIL_M("Offset of %i is out of bounds for VGA of length %i.", + cmd.data.offset, VGA_SIZE); return 1; } cursor = VGA_MEMORY + cmd.data.offset; From e7755fe092529ad6e1dfe31a1cd3737efa6a8e9c Mon Sep 17 00:00:00 2001 From: Septicake Date: Thu, 31 Oct 2024 19:13:35 -0400 Subject: [PATCH 44/70] Add new lines to improve readability, removed unused file name parameter from assertion fail function --- tests/src/test_helper.h | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/tests/src/test_helper.h b/tests/src/test_helper.h index 1762809..6b4b5ec 100644 --- a/tests/src/test_helper.h +++ b/tests/src/test_helper.h @@ -6,19 +6,27 @@ #include -void _assert_fail_m(char *fmt, const char *assertion, const char *file, - unsigned line, const char *function, ...) { +void _assert_fail_m(char *fmt, const char *assertion, unsigned line, + const char *function, ...) { va_list args; va_start(args, function); - char buff[1024]; + + // buffer to write the messages to + char buff[256]; + // "{function name}:{line number} Assertion '{assertion as a string}' + // failed." char errfmt[] = "%s:%i Assertion '%s' failed.\n"; + int len = snprintf(buff, 1024, errfmt, function, line, assertion); while (!serialWriteReady(COM1)) + ; serialWrite(COM1, (uint8_t *)buff, len); + // avoid an empty line if (fmt[0] != 0) { len = vsnprintf(buff, 1024, fmt, args); + while (!serialWriteReady(COM1)) ; serialWrite(COM1, (uint8_t *)buff, len); @@ -30,19 +38,27 @@ void _assert_fail_m(char *fmt, const char *assertion, const char *file, void _fail_m(char *fmt, unsigned line, const char *function, ...) { va_list args; va_start(args, function); - char buff[1024]; + + // buffer to write the messages to + char buff[256]; + // "{function name}:{line number} Fail assertion reached." char errfmt[] = "%s:%i Fail assertion reached.\n"; + int len = snprintf(buff, 1024, errfmt, function, line); + while (!serialWriteReady(COM1)) ; serialWrite(COM1, (uint8_t *)buff, len); + // avoid an empty line if (fmt[0] != 0) { len = vsnprintf(buff, 1024, fmt, args); + while (!serialWriteReady(COM1)) ; serialWrite(COM1, (uint8_t *)buff, len); } + va_end(args); } @@ -54,7 +70,7 @@ void _fail_m(char *fmt, unsigned line, const char *function, ...) { #define ASSERT_M(condition, fmt, ...) \ if (!(condition)) { \ - _assert_fail_m(fmt "\n", #condition, __FILE__, __LINE__, \ + _assert_fail_m(fmt "\n", #condition, __LINE__, \ __func__ __VA_OPT__(, ) __VA_ARGS__); \ } From 86473f4e68516417403bc2ae17f87c4a2ab103fc Mon Sep 17 00:00:00 2001 From: Septicake Date: Fri, 1 Nov 2024 15:26:48 -0400 Subject: [PATCH 45/70] Prevent key presses that do not produce characters from clearing the highlighted area --- src/lib/device/ps2.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/lib/device/ps2.c b/src/lib/device/ps2.c index 0a32bf5..5310c05 100644 --- a/src/lib/device/ps2.c +++ b/src/lib/device/ps2.c @@ -208,14 +208,16 @@ void vgaEditor(struct PS2Buf_t out) { case Key_right: specialHandler(out); break; - default: - if (highlight_offset) { - highlightDeletePrev(highlight_offset); - highlight_offset = 0; - } + default: char buf[2] = " "; buf[0] = keyPressToASCII(out.keyEvent); - print(buf, white); + if (buf[0] != 0) { + if (highlight_offset) { + highlightDeletePrev(highlight_offset); + highlight_offset = 0; + } + print(buf, white); + } } } From 5d11ede4e868d4fdd6c05085871ed6bf93a4d606 Mon Sep 17 00:00:00 2001 From: Septicake Date: Fri, 1 Nov 2024 15:27:10 -0400 Subject: [PATCH 46/70] Update how closing Qemu instances is handled --- tests/test.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/test.py b/tests/test.py index 1ec4cea..0788949 100644 --- a/tests/test.py +++ b/tests/test.py @@ -132,13 +132,14 @@ def endQemu(self): if (self._qemu != None and self._qemu.poll() == None): try: # send the exit command to QEMU - self._qemu.communicate(b"\x01x", 5) + self._qemu.terminate() self._qemu.wait(10) except: # force qemu to quit since it refuses to exit normally - self._qemu.kill() print(self.bin_path.name + " was forcefully closed.") + self._qemu.kill() + self._qemu.wait(5) self._qemu = None self._ready = False From fd31503f34a97226cf67dd3bd74584f19baf14bf Mon Sep 17 00:00:00 2001 From: Septicake Date: Fri, 1 Nov 2024 15:28:23 -0400 Subject: [PATCH 47/70] Formatting --- src/lib/device/ps2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/device/ps2.c b/src/lib/device/ps2.c index 5310c05..4256b75 100644 --- a/src/lib/device/ps2.c +++ b/src/lib/device/ps2.c @@ -208,7 +208,7 @@ void vgaEditor(struct PS2Buf_t out) { case Key_right: specialHandler(out); break; - default: + default: char buf[2] = " "; buf[0] = keyPressToASCII(out.keyEvent); if (buf[0] != 0) { From 1c1296cef2766ede8250805ff1594dfd614bcc17 Mon Sep 17 00:00:00 2001 From: Septicake Date: Fri, 1 Nov 2024 15:28:36 -0400 Subject: [PATCH 48/70] Remove unnecessary `undef`s --- src/lib/video/VGA_text.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/lib/video/VGA_text.c b/src/lib/video/VGA_text.c index 487bfa1..0214b36 100644 --- a/src/lib/video/VGA_text.c +++ b/src/lib/video/VGA_text.c @@ -119,8 +119,6 @@ void deleteCurrentChar(void) { adjustCursor(); } -#undef CLEAR_CHAR - void cursorHighlightDown(int offset) { cursor -= offset; int sign = SIGNUM(offset); @@ -203,8 +201,6 @@ void cursorRight(void) { adjustCursor(); } -#undef SIGNUM - void print(const char *str, VGA_Color color) { while (*str != 0) { // preserve background From 873067df534c87a9d5d219c42b9d17d76b5da57d Mon Sep 17 00:00:00 2001 From: Septicake Date: Fri, 1 Nov 2024 15:29:29 -0400 Subject: [PATCH 49/70] add `test_helper.h` to include path --- tests/Makefile | 2 +- tests/src/lib/container/ring_buffer.c | 2 +- tests/src/lib/stdlib/test_keyboard.c | 8 ++++---- tests/src/lib/stdlib/test_sort.c | 2 +- tests/src/lib/stdlib/test_stdio.c | 2 +- tests/src/lib/stdlib/test_stdlib.c | 2 +- tests/src/lib/stdlib/test_string.c | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index b881c4d..6cb0a96 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -14,7 +14,7 @@ all: $(MOS_ELF) $(BIN_NAMES) rm $@.elf %.o: %.c - $(CC) -c $^ -o $@ $(CFLAGS) -I./../src/lib/ -I./../src/lib/stdlib/ + $(CC) -c $^ -o $@ $(CFLAGS) -I./src -I./../src/lib/ -I./../src/lib/stdlib/ test_entry.o: test_entry.asm nasm $^ -f elf32 -o $@ diff --git a/tests/src/lib/container/ring_buffer.c b/tests/src/lib/container/ring_buffer.c index 2f1d156..c67dff8 100644 --- a/tests/src/lib/container/ring_buffer.c +++ b/tests/src/lib/container/ring_buffer.c @@ -1,7 +1,7 @@ #include "container/ring_buffer.h" -#include "../../test_helper.h" #include "device/serial.h" +#include "test_helper.h" #define RB_SIZE 32 typedef ring_buffer(RB_SIZE) ring_buffer_byte_t; diff --git a/tests/src/lib/stdlib/test_keyboard.c b/tests/src/lib/stdlib/test_keyboard.c index 4f30551..6e8faba 100644 --- a/tests/src/lib/stdlib/test_keyboard.c +++ b/tests/src/lib/stdlib/test_keyboard.c @@ -1,9 +1,9 @@ -#include "../../../../src/lib/device/keyboard.h" -#include "../../../../src/lib/device/ps2.h" -#include "../../../../src/lib/video/VGA_text.h" -#include "../../test_helper.h" +#include "device/keyboard.h" +#include "device/ps2.h" #include "stdio.h" #include "string.h" +#include "test_helper.h" +#include "video/VGA_text.h" #include diff --git a/tests/src/lib/stdlib/test_sort.c b/tests/src/lib/stdlib/test_sort.c index 9e5c3d0..dbc2b46 100644 --- a/tests/src/lib/stdlib/test_sort.c +++ b/tests/src/lib/stdlib/test_sort.c @@ -1,6 +1,6 @@ -#include "../../test_helper.h" #include "stdlib.h" #include "string.h" +#include "test_helper.h" #include #include diff --git a/tests/src/lib/stdlib/test_stdio.c b/tests/src/lib/stdlib/test_stdio.c index dada4b3..1769797 100644 --- a/tests/src/lib/stdlib/test_stdio.c +++ b/tests/src/lib/stdlib/test_stdio.c @@ -1,6 +1,6 @@ -#include "../../test_helper.h" #include "stdio.h" #include "string.h" +#include "test_helper.h" #include diff --git a/tests/src/lib/stdlib/test_stdlib.c b/tests/src/lib/stdlib/test_stdlib.c index ef8ff7c..abe3a71 100644 --- a/tests/src/lib/stdlib/test_stdlib.c +++ b/tests/src/lib/stdlib/test_stdlib.c @@ -1,6 +1,6 @@ -#include "../../test_helper.h" #include "stdlib.h" #include "string.h" +#include "test_helper.h" #define BUFSZ 100 diff --git a/tests/src/lib/stdlib/test_string.c b/tests/src/lib/stdlib/test_string.c index 013859d..e856e3c 100644 --- a/tests/src/lib/stdlib/test_string.c +++ b/tests/src/lib/stdlib/test_string.c @@ -1,5 +1,5 @@ -#include "../../test_helper.h" #include "string.h" +#include "test_helper.h" #define BUFSZ \ 100 // the size of string compare buffers (to detect buffer overflow) From 4e2ea0a5e21fc48d2742aaf68d70397c899f768a Mon Sep 17 00:00:00 2001 From: Septicake Date: Fri, 1 Nov 2024 15:34:29 -0400 Subject: [PATCH 50/70] Add tests to make sure that keypresses that do not produce characters to not affect the highlight offset --- tests/src/lib/stdlib/test_keyboard.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/src/lib/stdlib/test_keyboard.c b/tests/src/lib/stdlib/test_keyboard.c index 6e8faba..fb4b597 100644 --- a/tests/src/lib/stdlib/test_keyboard.c +++ b/tests/src/lib/stdlib/test_keyboard.c @@ -106,6 +106,22 @@ void test_main() { kbCMD(Key_left, KeyPressed, KEY_MOD_SHIFT), chkOffCMD(-1), chkPosCMD(2, 0), + kbCMD(Key_Lctrl, KeyPressed, 0), + chkOffCMD(-1), + kbCMD(Key_Rctrl, KeyPressed, 0), + chkOffCMD(-1), + kbCMD(Key_LShift, KeyPressed, 0), + chkOffCMD(-1), + kbCMD(Key_RShift, KeyPressed, 0), + chkOffCMD(-1), + kbCMD(Key_home, KeyPressed, 0), + chkOffCMD(-1), + kbCMD(Key_end, KeyPressed, 0), + chkOffCMD(-1), + kbCMD(Key_pgUp, KeyPressed, 0), + chkOffCMD(-1), + kbCMD(Key_pgDown, KeyPressed, 0), + chkOffCMD(-1), kbCMD(Key_up, KeyPressed, KEY_MOD_SHIFT), chkOffCMD(-VGA_WIDTH - 1), chkPosCMD(1, 0), From 8a04762c112dea3668391f05be3b26ae9f5de5e8 Mon Sep 17 00:00:00 2001 From: Septicake Date: Sat, 2 Nov 2024 03:03:28 -0400 Subject: [PATCH 51/70] Now using `sizeof(buff)` to get the size of the error text buffer --- tests/src/test_helper.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/src/test_helper.h b/tests/src/test_helper.h index 6b4b5ec..a8a81b8 100644 --- a/tests/src/test_helper.h +++ b/tests/src/test_helper.h @@ -6,6 +6,8 @@ #include +#define ERR_BUFF_SIZE 256 + void _assert_fail_m(char *fmt, const char *assertion, unsigned line, const char *function, ...) { va_list args; @@ -17,7 +19,7 @@ void _assert_fail_m(char *fmt, const char *assertion, unsigned line, // failed." char errfmt[] = "%s:%i Assertion '%s' failed.\n"; - int len = snprintf(buff, 1024, errfmt, function, line, assertion); + int len = snprintf(buff, sizeof(buff), errfmt, function, line, assertion); while (!serialWriteReady(COM1)) ; @@ -25,7 +27,7 @@ void _assert_fail_m(char *fmt, const char *assertion, unsigned line, // avoid an empty line if (fmt[0] != 0) { - len = vsnprintf(buff, 1024, fmt, args); + len = vsnprintf(buff, sizeof(buff), fmt, args); while (!serialWriteReady(COM1)) ; @@ -44,7 +46,7 @@ void _fail_m(char *fmt, unsigned line, const char *function, ...) { // "{function name}:{line number} Fail assertion reached." char errfmt[] = "%s:%i Fail assertion reached.\n"; - int len = snprintf(buff, 1024, errfmt, function, line); + int len = snprintf(buff, sizeof(buff), errfmt, function, line); while (!serialWriteReady(COM1)) ; @@ -52,7 +54,7 @@ void _fail_m(char *fmt, unsigned line, const char *function, ...) { // avoid an empty line if (fmt[0] != 0) { - len = vsnprintf(buff, 1024, fmt, args); + len = vsnprintf(buff, sizeof(buff), fmt, args); while (!serialWriteReady(COM1)) ; From da3fe97137c81b8a0ca3cb142bd9ec0cc8056a98 Mon Sep 17 00:00:00 2001 From: Real-Septicake Date: Mon, 4 Nov 2024 15:05:28 -0500 Subject: [PATCH 52/70] Add termcolor for test output readability, color scheme is not finalized --- tests/Makefile | 13 ++++++++++--- tests/test.py | 13 +++++++------ 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index 6cb0a96..149144e 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -4,9 +4,16 @@ OBJ_NAMES := $(C_FILES:%.c=%.o) MOS_ELF := ./../mOS.elf +VENV = .venv +VENV_PY = $(VENV)/bin/python + .PHONY: clean test -all: $(MOS_ELF) $(BIN_NAMES) +all: $(MOS_ELF) $(BIN_NAMES) venv_setup + +venv_setup: + python3 -m venv $(VENV) + $(VENV_PY) -m pip install termcolor %.bin: %.o test_entry.o $(LD) -o $@.elf $(LFLAGS) -T link.ld $^ --just-symbols=$(MOS_ELF) @@ -24,9 +31,9 @@ $(MOS_ELF): test: all ifdef TESTS - python3 test.py $(TESTS) + $(VENV_PY) test.py $(TESTS) else - python3 test.py + $(VENV_PY) test.py endif clean: diff --git a/tests/test.py b/tests/test.py index 0788949..ef9a113 100644 --- a/tests/test.py +++ b/tests/test.py @@ -7,6 +7,7 @@ import shutil import sys +from termcolor import cprint BASE_PORT = 1111 MAX_PORT = 1234 @@ -112,7 +113,7 @@ def beginQemu(self): self._qemu = subprocess.Popen(command, stdin=subprocess.PIPE, stderr=subprocess.PIPE, stdout=subprocess.PIPE) time.sleep(1) #give qemu some time to open self._ready = True - print(self.bin_path.name + " has started.") + cprint(self.bin_path.name + " has started.", "green") def beginTest(self): self.test = Thread(target=test, args=[self]) @@ -137,13 +138,13 @@ def endQemu(self): except: # force qemu to quit since it refuses to exit normally - print(self.bin_path.name + " was forcefully closed.") + cprint(self.bin_path.name + " was forcefully closed.", "red", attrs=["bold"]) self._qemu.kill() self._qemu.wait(5) self._qemu = None self._ready = False - print(self.bin_path.name + " has exited.") + cprint(self.bin_path.name + " has exited.", "cyan") os.remove(self._qemu_file) def end(self): @@ -273,7 +274,7 @@ def test(instance: TestInstance): return test_end_stub(instance, passed) except socket.timeout: - print(instance.bin_path.name + " | test timed out") + cprint(instance.bin_path.name + " | test timed out", "red") except socket.error as e: @@ -364,10 +365,10 @@ def do_tests(): result = instance.result if (result): total_pass += 1 - print(instance.bin_path.name + " PASSED") + cprint(instance.bin_path.name + " PASSED", "light_green") else: total_fail += 1 - print(instance.bin_path.name + " FAILED") + cprint(instance.bin_path.name + " FAILED", "red", attrs=["bold"]) print("Summary: PASSED-{}, FAILED-{}, TOTAL-{}" .format(total_pass, total_fail, len(instances))) From 0e2681e586c67d9b4c4d93d18cf3ebf011f65c75 Mon Sep 17 00:00:00 2001 From: Septicake Date: Mon, 4 Nov 2024 17:37:59 -0500 Subject: [PATCH 53/70] Implement several of the suggested changes, more to do but committing to save progress --- src/lib/device/ps2.c | 86 +++++++++--------- src/lib/video/VGA_text.c | 126 ++++++++++++++------------- src/lib/video/VGA_text.h | 15 +++- tests/Makefile | 2 +- tests/requirements.txt | 1 + tests/src/lib/stdlib/test_keyboard.c | 57 +++++++----- tests/src/test_helper.h | 39 +++------ 7 files changed, 173 insertions(+), 153 deletions(-) create mode 100644 tests/requirements.txt diff --git a/src/lib/device/ps2.c b/src/lib/device/ps2.c index 4256b75..0636122 100644 --- a/src/lib/device/ps2.c +++ b/src/lib/device/ps2.c @@ -72,50 +72,48 @@ const struct PS2Device *getPortType(int portnum) { // temporary include for #7 #include "video/VGA_text.h" -int highlight_offset = 0; - -void specialHandler(struct PS2Buf_t out) { - if (!(out.keyEvent.modifiers & KEY_MOD_SHIFT)) { - switch (out.keyEvent.code) { +void specialHandler(KeyPress out) { + if (!(out.modifiers & KEY_MOD_SHIFT)) { + switch (out.code) { case Key_backspace: - if (highlight_offset) { - highlightDeletePrev(highlight_offset); - highlight_offset = 0; + if (cursor.highlight_offset) { + highlightDeletePrev(cursor.highlight_offset); + cursor.highlight_offset = 0; } else deletePrevChar(); break; case Key_delete: - if (highlight_offset) { - highlightDeleteCurrent(highlight_offset); - highlight_offset = 0; + if (cursor.highlight_offset) { + highlightDeleteCurrent(cursor.highlight_offset); + cursor.highlight_offset = 0; } else deleteCurrentChar(); break; case Key_left: - if (highlight_offset) { - cursorHighlightLeft(highlight_offset); - highlight_offset = 0; + if (cursor.highlight_offset) { + cursorHighlightLeft(cursor.highlight_offset); + cursor.highlight_offset = 0; } else cursorLeft(); break; case Key_down: - if (highlight_offset) { - cursorHighlightDown(highlight_offset); - highlight_offset = 0; + if (cursor.highlight_offset) { + cursorHighlightDown(cursor.highlight_offset); + cursor.highlight_offset = 0; } else cursorDown(); break; case Key_up: - if (highlight_offset) { - cursorHighlightUp(highlight_offset); - highlight_offset = 0; + if (cursor.highlight_offset) { + cursorHighlightUp(cursor.highlight_offset); + cursor.highlight_offset = 0; } else cursorUp(); break; case Key_right: - if (highlight_offset) { - cursorHighlightRight(highlight_offset); - highlight_offset = 0; + if (cursor.highlight_offset) { + cursorHighlightRight(cursor.highlight_offset); + cursor.highlight_offset = 0; } else cursorRight(); break; @@ -123,72 +121,72 @@ void specialHandler(struct PS2Buf_t out) { break; } } else { - switch (out.keyEvent.code) { + switch (out.code) { case Key_up: if (!cursorIsAtStart()) { - if (!highlight_offset) + if (!cursor.highlight_offset) highlightCurrentChar(); for (int i = 0; i < VGA_WIDTH && !cursorIsAtStart(); i++) { - if (highlight_offset > 0) { + if (cursor.highlight_offset > 0) { highlightCurrentChar(); cursorLeft(); } else { cursorLeft(); highlightCurrentChar(); } - highlight_offset--; + cursor.highlight_offset--; } - if (!highlight_offset) + if (!cursor.highlight_offset) highlightCurrentChar(); } break; case Key_down: if (!cursorIsAtEnd()) { - if (!highlight_offset) + if (!cursor.highlight_offset) highlightCurrentChar(); for (int i = 0; i < VGA_WIDTH && !cursorIsAtEnd(); i++) { - if (highlight_offset < 0) { + if (cursor.highlight_offset < 0) { highlightCurrentChar(); cursorRight(); } else { cursorRight(); highlightCurrentChar(); } - highlight_offset++; + cursor.highlight_offset++; } - if (!highlight_offset) + if (!cursor.highlight_offset) highlightCurrentChar(); } break; case Key_left: if (!cursorIsAtStart()) { - if (!highlight_offset) + if (!cursor.highlight_offset) highlightCurrentChar(); - if (highlight_offset > 0) { + if (cursor.highlight_offset > 0) { highlightCurrentChar(); cursorLeft(); } else { cursorLeft(); highlightCurrentChar(); } - highlight_offset--; - if (!highlight_offset) + cursor.highlight_offset--; + if (!cursor.highlight_offset) highlightCurrentChar(); } break; case Key_right: if (!cursorIsAtEnd()) { - if (!highlight_offset) + if (!cursor.highlight_offset) highlightCurrentChar(); - if (highlight_offset < 0) { + if (cursor.highlight_offset < 0) { highlightCurrentChar(); cursorRight(); } else { cursorRight(); highlightCurrentChar(); } - highlight_offset++; - if (!highlight_offset) + cursor.highlight_offset++; + if (!cursor.highlight_offset) highlightCurrentChar(); } break; @@ -206,15 +204,15 @@ void vgaEditor(struct PS2Buf_t out) { case Key_down: case Key_up: case Key_right: - specialHandler(out); + specialHandler(out.keyEvent); break; default: char buf[2] = " "; buf[0] = keyPressToASCII(out.keyEvent); if (buf[0] != 0) { - if (highlight_offset) { - highlightDeletePrev(highlight_offset); - highlight_offset = 0; + if (cursor.highlight_offset) { + highlightDeletePrev(cursor.highlight_offset); + cursor.highlight_offset = 0; } print(buf, white); } diff --git a/src/lib/video/VGA_text.c b/src/lib/video/VGA_text.c index 0214b36..081a5f3 100644 --- a/src/lib/video/VGA_text.c +++ b/src/lib/video/VGA_text.c @@ -2,7 +2,7 @@ #include "../../os/hard/port_io.h" -VGA_Char *cursor = VGA_MEMORY; +cursor_struct cursor = {VGA_MEMORY, 0}; VGA_Char getVGAchar(unsigned char chr, VGA_Color foreground, VGA_Color background) { @@ -27,22 +27,22 @@ void writeText(const char *str, int x, int y, VGA_Color color) { } } -inline int cursorIsAtStart() { - return cursor == VGA_MEMORY; +inline bool cursorIsAtStart(void) { + return cursor.pos == VGA_MEMORY; } -inline int cursorIsAtEnd() { - return cursor == VGA_END - 1; +inline bool cursorIsAtEnd(void) { + return cursor.pos == VGA_END - 1; } -static inline VGA_Color invert(VGA_Color color) { +inline VGA_Color invert(VGA_Color color) { return 15 - (unsigned)color; } void updateCursorPos(void) { // evil (but useful) pointer arithmetic - uint16_t pos = (cursor - VGA_MEMORY); + uint16_t pos = (cursor.pos - VGA_MEMORY); // low (mostly x but some y too) outb(VGA_ADDR_PORT, 0x0F); @@ -55,20 +55,20 @@ void updateCursorPos(void) { // checks and fixes the cursor, may do nothing void adjustCursor(void) { - if (cursor < VGA_MEMORY) { - cursor = VGA_MEMORY; - } else if (cursor >= VGA_END) { + if (cursor.pos < VGA_MEMORY) { + cursor.pos = VGA_MEMORY; + } else if (cursor.pos >= VGA_END) { scroll(); // set cursor to start of last line - cursor = VGA_MEMORY + VGA_SIZE - VGA_WIDTH; + cursor.pos = VGA_MEMORY + VGA_SIZE - VGA_WIDTH; } updateCursorPos(); } void highlightCurrentChar(void) { - *cursor = getVGAchar(cursor->chr, invert(cursor->color & 0xf), - invert((cursor->color >> 4) & 0xf)); + *cursor.pos = getVGAchar(cursor.pos->chr, invert(cursor.pos->color & 0xf), + invert((cursor.pos->color >> 4) & 0xf)); } #define CLEAR_CHAR(ptr) (getVGAchar(' ', white, (ptr)->color >> 4)) @@ -77,135 +77,139 @@ void highlightCurrentChar(void) { void highlightDeletePrev(int offset) { if (offset < 0) - cursor -= offset; + cursor.pos -= offset; int abs_offset = SIGNUM(offset) * offset; for (int i = abs_offset; i >= 0; i--) { highlightCurrentChar(); - *cursor = CLEAR_CHAR(cursor); - cursor--; + *cursor.pos = CLEAR_CHAR(cursor.pos); + cursor.pos--; } - cursor++; + cursor.pos++; adjustCursor(); } void deletePrevChar(void) { if (!cursorIsAtStart()) { // preserve background - VGA_Char clearChar = CLEAR_CHAR(cursor - 1); - *--cursor = clearChar; + VGA_Char clearChar = CLEAR_CHAR(cursor.pos - 1); + *--cursor.pos = clearChar; } adjustCursor(); } void highlightDeleteCurrent(int offset) { if (offset > 0) - cursor -= offset; + cursor.pos -= offset; int abs_offset = SIGNUM(offset) * offset; for (int i = abs_offset; i >= 0; i--) { highlightCurrentChar(); - *cursor = CLEAR_CHAR(cursor); - cursor++; + *cursor.pos = CLEAR_CHAR(cursor.pos); + cursor.pos++; } - cursor--; + cursor.pos--; adjustCursor(); } void deleteCurrentChar(void) { if (!cursorIsAtEnd()) { // preserve background - VGA_Char clearChar = CLEAR_CHAR(cursor); - *cursor++ = clearChar; + VGA_Char clearChar = CLEAR_CHAR(cursor.pos); + *cursor.pos++ = clearChar; } adjustCursor(); } void cursorHighlightDown(int offset) { - cursor -= offset; + cursor.pos -= offset; int sign = SIGNUM(offset); int abs_offset = sign * offset; for (int i = abs_offset; i >= 0; i--) { - *cursor = getVGAchar(cursor->chr, invert(cursor->color & 0xf), - invert((cursor->color >> 4) & 0xf)); - cursor += sign; + *cursor.pos = + getVGAchar(cursor.pos->chr, invert(cursor.pos->color & 0xf), + invert((cursor.pos->color >> 4) & 0xf)); + cursor.pos += sign; } - cursor -= sign; + cursor.pos -= sign; cursorDown(); adjustCursor(); } void cursorDown(void) { - if (cursor < VGA_END - VGA_WIDTH) - cursor += VGA_WIDTH; + if (cursor.pos < VGA_END - VGA_WIDTH) + cursor.pos += VGA_WIDTH; else - cursor = VGA_END - 1; + cursor.pos = VGA_END - 1; adjustCursor(); } void cursorHighlightUp(int offset) { - cursor -= offset; + cursor.pos -= offset; int sign = SIGNUM(offset); int abs_offset = sign * offset; for (int i = abs_offset; i >= 0; i--) { - *cursor = getVGAchar(cursor->chr, invert(cursor->color & 0xf), - invert((cursor->color >> 4) & 0xf)); - cursor += sign; + *cursor.pos = + getVGAchar(cursor.pos->chr, invert(cursor.pos->color & 0xf), + invert((cursor.pos->color >> 4) & 0xf)); + cursor.pos += sign; } - cursor -= sign; + cursor.pos -= sign; cursorUp(); adjustCursor(); } void cursorUp(void) { - if (cursor > VGA_MEMORY + VGA_WIDTH) - cursor -= VGA_WIDTH; + if (cursor.pos > VGA_MEMORY + VGA_WIDTH) + cursor.pos -= VGA_WIDTH; else - cursor = VGA_MEMORY; + cursor.pos = VGA_MEMORY; adjustCursor(); } void cursorHighlightLeft(int offset) { if (offset < 0) - cursor -= offset; + cursor.pos -= offset; int abs_offset = SIGNUM(offset) * offset; for (int i = abs_offset; i >= 0; i--) { - *cursor = getVGAchar(cursor->chr, invert(cursor->color & 0xf), - invert((cursor->color >> 4) & 0xf)); - cursor--; + *cursor.pos = + getVGAchar(cursor.pos->chr, invert(cursor.pos->color & 0xf), + invert((cursor.pos->color >> 4) & 0xf)); + cursor.pos--; } - cursor++; + cursor.pos++; adjustCursor(); } void cursorLeft(void) { if (!cursorIsAtStart()) - cursor--; + cursor.pos--; adjustCursor(); } void cursorHighlightRight(int offset) { if (offset > 0) - cursor -= offset; + cursor.pos -= offset; int abs_offset = SIGNUM(offset) * offset; for (int i = abs_offset; i >= 0; i--) { - *cursor = getVGAchar(cursor->chr, invert(cursor->color & 0xf), - invert((cursor->color >> 4) & 0xf)); - cursor++; + *cursor.pos = + getVGAchar(cursor.pos->chr, invert(cursor.pos->color & 0xf), + invert((cursor.pos->color >> 4) & 0xf)); + cursor.pos++; } - cursor--; + cursor.pos--; adjustCursor(); } void cursorRight(void) { if (!cursorIsAtEnd()) - cursor++; + cursor.pos++; adjustCursor(); } void print(const char *str, VGA_Color color) { while (*str != 0) { // preserve background - VGA_Char chr = {*str++, color ^ (cursor->color & 0xf0)}; - *cursor++ = chr; + VGA_Char chr = {*str++, color ^ (cursor.pos->color & 0xf0)}; + *cursor.pos++ = chr; // prevent writing out of bounds! adjustCursor(); @@ -216,16 +220,16 @@ void println(const char *str, VGA_Color color) { print(str, color); // update cursor position to next line - cursor += VGA_WIDTH; - int remain = (int)(cursor - VGA_MEMORY) % (VGA_WIDTH); - cursor -= remain; + cursor.pos += VGA_WIDTH; + int remain = (int)(cursor.pos - VGA_MEMORY) % (VGA_WIDTH); + cursor.pos -= remain; adjustCursor(); // bounds check } void scroll() { - cursor -= VGA_WIDTH; // move cursor up - adjustCursor(); // bounds check + cursor.pos -= VGA_WIDTH; // move cursor up + adjustCursor(); // bounds check VGA_Char *current = VGA_MEMORY; VGA_Char *next = VGA_MEMORY + VGA_WIDTH; @@ -252,6 +256,6 @@ void clearScreenC(VGA_Char character) { for (unsigned short i = 0; i < VGA_SIZE; ++i) { VGA_MEMORY[i] = character; } - cursor = VGA_MEMORY; // reset cursor + cursor.pos = VGA_MEMORY; // reset cursor adjustCursor(); } \ No newline at end of file diff --git a/src/lib/video/VGA_text.h b/src/lib/video/VGA_text.h index cb0770c..4fce1f7 100644 --- a/src/lib/video/VGA_text.h +++ b/src/lib/video/VGA_text.h @@ -1,6 +1,8 @@ #ifndef VGA_TEXT_H #define VGA_TEXT_H +#include + // note VGA's width is equal to it's stride in text mode #define VGA_MEMORY ((VGA_Char *)(0xB8000)) @@ -41,6 +43,14 @@ typedef struct { unsigned char color; } VGA_Char; +typedef struct { + VGA_Char *pos; + int highlight_offset; +} cursor_struct; + +// is this a normal thing to do? no clue, I'll let god and/or Trevor decide +extern cursor_struct cursor; + // returns a VGA_Char with the supplied attributes VGA_Char getVGAchar(unsigned char chr, VGA_Color foreground, VGA_Color background); @@ -48,8 +58,9 @@ VGA_Char getVGAchar(unsigned char chr, VGA_Color foreground, // prints text at location, will NOT wrap void writeText(const char *str, int x, int y, VGA_Color color); -int cursorIsAtStart(void); -int cursorIsAtEnd(void); +bool cursorIsAtStart(void); +bool cursorIsAtEnd(void); +VGA_Color invert(VGA_Color color); void highlightCurrentChar(void); diff --git a/tests/Makefile b/tests/Makefile index 149144e..2395e9b 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -13,7 +13,7 @@ all: $(MOS_ELF) $(BIN_NAMES) venv_setup venv_setup: python3 -m venv $(VENV) - $(VENV_PY) -m pip install termcolor + $(VENV_PY) -m pip install -r requirements.txt %.bin: %.o test_entry.o $(LD) -o $@.elf $(LFLAGS) -T link.ld $^ --just-symbols=$(MOS_ELF) diff --git a/tests/requirements.txt b/tests/requirements.txt new file mode 100644 index 0000000..f3d82a4 --- /dev/null +++ b/tests/requirements.txt @@ -0,0 +1 @@ +termcolor==2.5.0 \ No newline at end of file diff --git a/tests/src/lib/stdlib/test_keyboard.c b/tests/src/lib/stdlib/test_keyboard.c index fb4b597..23522dc 100644 --- a/tests/src/lib/stdlib/test_keyboard.c +++ b/tests/src/lib/stdlib/test_keyboard.c @@ -12,9 +12,6 @@ #define END_COL (VGA_WIDTH - 1) #define END_LINE (VGA_HEIGHT - 1) -extern int highlight_offset; -extern VGA_Char *cursor; - // enum representing the kinds of commands available enum CMD { keyPress, checkOffset, checkPosition, setPosition, end }; @@ -58,28 +55,29 @@ struct TestCMD endCMD() { } // execute the supplied command based on its `cmd` field -int execCMD(struct TestCMD cmd) { +int execCMD(struct TestCMD cmd, int idx) { switch (cmd.cmd) { case checkOffset: // asserts that the current highlight offset matches the // supplied offset - ASSERT_M(highlight_offset == cmd.data.offset, - "Highlight difference | Expected: %i, Actual: %i", - cmd.data.offset, highlight_offset); + ASSERT_M(cursor.highlight_offset == cmd.data.offset, + "CMD %i: Highlight difference | Expected: %i, Actual: %i", idx, + cmd.data.offset, cursor.highlight_offset); break; case checkPosition: // asserts that the relative position from the start of // vga memory matches the supplied position - ASSERT_M(cursor - VGA_MEMORY == cmd.data.offset, - "Position difference | Expected: %i, Actual: %i", - cmd.data.offset, cursor - VGA_MEMORY); + ASSERT_M(cursor.pos - VGA_MEMORY == cmd.data.offset, + "CMD %i: Position difference | Expected: %i, Actual: %i", idx, + cmd.data.offset, cursor.pos - VGA_MEMORY); break; case setPosition: // sets the cursor position, checks that the position is // in bounds if (cmd.data.offset < 0 || cmd.data.offset >= VGA_SIZE) { - FAIL_M("Offset of %i is out of bounds for VGA of length %i.", - cmd.data.offset, VGA_SIZE); + FAIL_M( + "CMD %i: Offset of %i is out of bounds for VGA of length %i.", + idx, cmd.data.offset, VGA_SIZE); return 1; } - cursor = VGA_MEMORY + cmd.data.offset; + cursor.pos = VGA_MEMORY + cmd.data.offset; break; case keyPress: // simulates a keypress vgaEditor(cmd.data.kb); @@ -88,24 +86,30 @@ int execCMD(struct TestCMD cmd) { // terminator break; default: - FAIL_M("Unexpected command type: %i", cmd.cmd); + FAIL_M("CMD %i: Unexpected command type: %i", idx, cmd.cmd); return 1; } return 0; } void test_main() { - cursor = VGA_MEMORY + 160; struct TestCMD b[] = { - // The position checks assume that only 2 lines of text have been - // written during boot + // set cursor position to a known position to prevent breaking if the + // boot text changes + setPosCMD(2, 0), + // make sure that the position is set properly chkPosCMD(2, 0), + kbCMD(Key_a, KeyPressed, 0), chkOffCMD(0), chkPosCMD(2, 1), + kbCMD(Key_left, KeyPressed, KEY_MOD_SHIFT), chkOffCMD(-1), chkPosCMD(2, 0), + + // make sure keys that do not produce a character do not affect the + // highlight offset kbCMD(Key_Lctrl, KeyPressed, 0), chkOffCMD(-1), kbCMD(Key_Rctrl, KeyPressed, 0), @@ -122,37 +126,50 @@ void test_main() { chkOffCMD(-1), kbCMD(Key_pgDown, KeyPressed, 0), chkOffCMD(-1), + + // check that highlighting works properly kbCMD(Key_up, KeyPressed, KEY_MOD_SHIFT), chkOffCMD(-VGA_WIDTH - 1), chkPosCMD(1, 0), kbCMD(Key_up, KeyPressed, KEY_MOD_SHIFT), chkOffCMD(-(2 * VGA_WIDTH) - 1), chkPosCMD(0, 0), + + // check that key press removes highlight and sets cursor position to + // after typed character kbCMD(Key_b, KeyPressed, 0), chkOffCMD(0), chkPosCMD(0, 1), + + // check that vertical keypresses move cursor properly while + // highlighting kbCMD(Key_down, KeyPressed, KEY_MOD_SHIFT), chkOffCMD(VGA_WIDTH), chkPosCMD(1, 1), kbCMD(Key_up, KeyPressed, 0), chkOffCMD(0), chkPosCMD(0, 1), + + // check wrapping setPosCMD(0, END_COL), kbCMD(Key_right, KeyPressed, 0), chkPosCMD(1, 0), kbCMD(Key_left, KeyPressed, 0), chkPosCMD(0, END_COL), + + // check bottom bounds check setPosCMD(END_LINE, 0), kbCMD(Key_down, KeyPressed, 0), chkPosCMD(END_LINE, END_COL), kbCMD(Key_up, KeyPressed, KEY_MOD_SHIFT), kbCMD(Key_down, KeyPressed, 0), chkPosCMD(END_LINE, END_COL), - // Remember to end command sequence! + endCMD(), }; - for (int i = 0; b[i].cmd != end; i++) { - if (execCMD(b[i])) { + for (int i = 0; b[i].cmd != end && i < sizeof(b) / sizeof(struct TestCMD); + i++) { + if (execCMD(b[i], i)) { char err[] = "test_keyboard errored at command "; serialWrite(COM1, (uint8_t *)err, sizeof(err) - 1); char buf[4]; diff --git a/tests/src/test_helper.h b/tests/src/test_helper.h index a8a81b8..d4cd714 100644 --- a/tests/src/test_helper.h +++ b/tests/src/test_helper.h @@ -3,31 +3,23 @@ #include "device/serial.h" #include "stdio.h" +#include "string.h" #include -#define ERR_BUFF_SIZE 256 - -void _assert_fail_m(char *fmt, const char *assertion, unsigned line, - const char *function, ...) { +void _assert_fail_m(char *fmt, const char *msg, ...) { va_list args; - va_start(args, function); + va_start(args, msg); // buffer to write the messages to char buff[256]; - // "{function name}:{line number} Assertion '{assertion as a string}' - // failed." - char errfmt[] = "%s:%i Assertion '%s' failed.\n"; - - int len = snprintf(buff, sizeof(buff), errfmt, function, line, assertion); while (!serialWriteReady(COM1)) - ; - serialWrite(COM1, (uint8_t *)buff, len); + serialWrite(COM1, (uint8_t *)msg, strnlen_s(msg, 256)); // avoid an empty line if (fmt[0] != 0) { - len = vsnprintf(buff, sizeof(buff), fmt, args); + int len = vsnprintf(buff, sizeof(buff), fmt, args); while (!serialWriteReady(COM1)) ; @@ -37,24 +29,19 @@ void _assert_fail_m(char *fmt, const char *assertion, unsigned line, va_end(args); } -void _fail_m(char *fmt, unsigned line, const char *function, ...) { +void _fail_m(char *fmt, const char *msg, ...) { va_list args; - va_start(args, function); + va_start(args, msg); // buffer to write the messages to char buff[256]; - // "{function name}:{line number} Fail assertion reached." - char errfmt[] = "%s:%i Fail assertion reached.\n"; - - int len = snprintf(buff, sizeof(buff), errfmt, function, line); - while (!serialWriteReady(COM1)) ; - serialWrite(COM1, (uint8_t *)buff, len); + serialWrite(COM1, (uint8_t *)msg, strnlen_s(msg, 256)); // avoid an empty line if (fmt[0] != 0) { - len = vsnprintf(buff, sizeof(buff), fmt, args); + int len = vsnprintf(buff, sizeof(buff), fmt, args); while (!serialWriteReady(COM1)) ; @@ -72,12 +59,14 @@ void _fail_m(char *fmt, unsigned line, const char *function, ...) { #define ASSERT_M(condition, fmt, ...) \ if (!(condition)) { \ - _assert_fail_m(fmt "\n", #condition, __LINE__, \ - __func__ __VA_OPT__(, ) __VA_ARGS__); \ + _assert_fail_m(fmt "\n", "Line " STR_LINE ": Assertion '" #condition \ + "' failed.\n" __VA_OPT__(, ) __VA_ARGS__); \ } #define FAIL_M(fmt, ...) \ - _fail_m(fmt "\n", __LINE__, __func__ __VA_OPT__(, ) __VA_ARGS__) + _fail_m(fmt "\n", \ + "Line " STR_LINE ": Fail assertion reached.\n" __VA_OPT__(, ) \ + __VA_ARGS__) #define ASSERT(condition) ASSERT_M(condition, "") From f8fede8524adfe7adbfd0d7634ab5c73a02e8589 Mon Sep 17 00:00:00 2001 From: Septicake Date: Mon, 4 Nov 2024 18:12:09 -0500 Subject: [PATCH 54/70] Rename `cursor_struct` to `VGA_Cursor` --- src/lib/video/VGA_text.c | 2 +- src/lib/video/VGA_text.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib/video/VGA_text.c b/src/lib/video/VGA_text.c index 081a5f3..c83d31f 100644 --- a/src/lib/video/VGA_text.c +++ b/src/lib/video/VGA_text.c @@ -2,7 +2,7 @@ #include "../../os/hard/port_io.h" -cursor_struct cursor = {VGA_MEMORY, 0}; +VGA_Cursor cursor = {VGA_MEMORY, 0}; VGA_Char getVGAchar(unsigned char chr, VGA_Color foreground, VGA_Color background) { diff --git a/src/lib/video/VGA_text.h b/src/lib/video/VGA_text.h index 4fce1f7..e555544 100644 --- a/src/lib/video/VGA_text.h +++ b/src/lib/video/VGA_text.h @@ -46,10 +46,10 @@ typedef struct { typedef struct { VGA_Char *pos; int highlight_offset; -} cursor_struct; +} VGA_Cursor; // is this a normal thing to do? no clue, I'll let god and/or Trevor decide -extern cursor_struct cursor; +extern VGA_Cursor cursor; // returns a VGA_Char with the supplied attributes VGA_Char getVGAchar(unsigned char chr, VGA_Color foreground, From 238d9573c4edfd7e3577546991ac5882c72e5fca Mon Sep 17 00:00:00 2001 From: Septicake Date: Mon, 4 Nov 2024 18:58:19 -0500 Subject: [PATCH 55/70] Replace `extern` for usage of vga cursor with a getter --- src/lib/device/ps2.c | 74 ++++++++++++++-------------- src/lib/video/VGA_text.c | 4 ++ src/lib/video/VGA_text.h | 3 +- tests/src/lib/stdlib/test_keyboard.c | 10 ++-- 4 files changed, 47 insertions(+), 44 deletions(-) diff --git a/src/lib/device/ps2.c b/src/lib/device/ps2.c index 0636122..e084475 100644 --- a/src/lib/device/ps2.c +++ b/src/lib/device/ps2.c @@ -76,44 +76,44 @@ void specialHandler(KeyPress out) { if (!(out.modifiers & KEY_MOD_SHIFT)) { switch (out.code) { case Key_backspace: - if (cursor.highlight_offset) { - highlightDeletePrev(cursor.highlight_offset); - cursor.highlight_offset = 0; + if (getCursor()->highlight_offset) { + highlightDeletePrev(getCursor()->highlight_offset); + getCursor()->highlight_offset = 0; } else deletePrevChar(); break; case Key_delete: - if (cursor.highlight_offset) { - highlightDeleteCurrent(cursor.highlight_offset); - cursor.highlight_offset = 0; + if (getCursor()->highlight_offset) { + highlightDeleteCurrent(getCursor()->highlight_offset); + getCursor()->highlight_offset = 0; } else deleteCurrentChar(); break; case Key_left: - if (cursor.highlight_offset) { - cursorHighlightLeft(cursor.highlight_offset); - cursor.highlight_offset = 0; + if (getCursor()->highlight_offset) { + cursorHighlightLeft(getCursor()->highlight_offset); + getCursor()->highlight_offset = 0; } else cursorLeft(); break; case Key_down: - if (cursor.highlight_offset) { - cursorHighlightDown(cursor.highlight_offset); - cursor.highlight_offset = 0; + if (getCursor()->highlight_offset) { + cursorHighlightDown(getCursor()->highlight_offset); + getCursor()->highlight_offset = 0; } else cursorDown(); break; case Key_up: - if (cursor.highlight_offset) { - cursorHighlightUp(cursor.highlight_offset); - cursor.highlight_offset = 0; + if (getCursor()->highlight_offset) { + cursorHighlightUp(getCursor()->highlight_offset); + getCursor()->highlight_offset = 0; } else cursorUp(); break; case Key_right: - if (cursor.highlight_offset) { - cursorHighlightRight(cursor.highlight_offset); - cursor.highlight_offset = 0; + if (getCursor()->highlight_offset) { + cursorHighlightRight(getCursor()->highlight_offset); + getCursor()->highlight_offset = 0; } else cursorRight(); break; @@ -124,69 +124,69 @@ void specialHandler(KeyPress out) { switch (out.code) { case Key_up: if (!cursorIsAtStart()) { - if (!cursor.highlight_offset) + if (!getCursor()->highlight_offset) highlightCurrentChar(); for (int i = 0; i < VGA_WIDTH && !cursorIsAtStart(); i++) { - if (cursor.highlight_offset > 0) { + if (getCursor()->highlight_offset > 0) { highlightCurrentChar(); cursorLeft(); } else { cursorLeft(); highlightCurrentChar(); } - cursor.highlight_offset--; + getCursor()->highlight_offset--; } - if (!cursor.highlight_offset) + if (!getCursor()->highlight_offset) highlightCurrentChar(); } break; case Key_down: if (!cursorIsAtEnd()) { - if (!cursor.highlight_offset) + if (!getCursor()->highlight_offset) highlightCurrentChar(); for (int i = 0; i < VGA_WIDTH && !cursorIsAtEnd(); i++) { - if (cursor.highlight_offset < 0) { + if (getCursor()->highlight_offset < 0) { highlightCurrentChar(); cursorRight(); } else { cursorRight(); highlightCurrentChar(); } - cursor.highlight_offset++; + getCursor()->highlight_offset++; } - if (!cursor.highlight_offset) + if (!getCursor()->highlight_offset) highlightCurrentChar(); } break; case Key_left: if (!cursorIsAtStart()) { - if (!cursor.highlight_offset) + if (!getCursor()->highlight_offset) highlightCurrentChar(); - if (cursor.highlight_offset > 0) { + if (getCursor()->highlight_offset > 0) { highlightCurrentChar(); cursorLeft(); } else { cursorLeft(); highlightCurrentChar(); } - cursor.highlight_offset--; - if (!cursor.highlight_offset) + getCursor()->highlight_offset--; + if (!getCursor()->highlight_offset) highlightCurrentChar(); } break; case Key_right: if (!cursorIsAtEnd()) { - if (!cursor.highlight_offset) + if (!getCursor()->highlight_offset) highlightCurrentChar(); - if (cursor.highlight_offset < 0) { + if (getCursor()->highlight_offset < 0) { highlightCurrentChar(); cursorRight(); } else { cursorRight(); highlightCurrentChar(); } - cursor.highlight_offset++; - if (!cursor.highlight_offset) + getCursor()->highlight_offset++; + if (!getCursor()->highlight_offset) highlightCurrentChar(); } break; @@ -210,9 +210,9 @@ void vgaEditor(struct PS2Buf_t out) { char buf[2] = " "; buf[0] = keyPressToASCII(out.keyEvent); if (buf[0] != 0) { - if (cursor.highlight_offset) { - highlightDeletePrev(cursor.highlight_offset); - cursor.highlight_offset = 0; + if (getCursor()->highlight_offset) { + highlightDeletePrev(getCursor()->highlight_offset); + getCursor()->highlight_offset = 0; } print(buf, white); } diff --git a/src/lib/video/VGA_text.c b/src/lib/video/VGA_text.c index c83d31f..d925734 100644 --- a/src/lib/video/VGA_text.c +++ b/src/lib/video/VGA_text.c @@ -4,6 +4,10 @@ VGA_Cursor cursor = {VGA_MEMORY, 0}; +VGA_Cursor *getCursor(void) { + return &cursor; +} + VGA_Char getVGAchar(unsigned char chr, VGA_Color foreground, VGA_Color background) { VGA_Char out = {chr, ((background << 4) | foreground)}; diff --git a/src/lib/video/VGA_text.h b/src/lib/video/VGA_text.h index e555544..595a363 100644 --- a/src/lib/video/VGA_text.h +++ b/src/lib/video/VGA_text.h @@ -48,8 +48,7 @@ typedef struct { int highlight_offset; } VGA_Cursor; -// is this a normal thing to do? no clue, I'll let god and/or Trevor decide -extern VGA_Cursor cursor; +VGA_Cursor *getCursor(void); // returns a VGA_Char with the supplied attributes VGA_Char getVGAchar(unsigned char chr, VGA_Color foreground, diff --git a/tests/src/lib/stdlib/test_keyboard.c b/tests/src/lib/stdlib/test_keyboard.c index 23522dc..c3dfa99 100644 --- a/tests/src/lib/stdlib/test_keyboard.c +++ b/tests/src/lib/stdlib/test_keyboard.c @@ -59,15 +59,15 @@ int execCMD(struct TestCMD cmd, int idx) { switch (cmd.cmd) { case checkOffset: // asserts that the current highlight offset matches the // supplied offset - ASSERT_M(cursor.highlight_offset == cmd.data.offset, + ASSERT_M(getCursor()->highlight_offset == cmd.data.offset, "CMD %i: Highlight difference | Expected: %i, Actual: %i", idx, - cmd.data.offset, cursor.highlight_offset); + cmd.data.offset, getCursor()->highlight_offset); break; case checkPosition: // asserts that the relative position from the start of // vga memory matches the supplied position - ASSERT_M(cursor.pos - VGA_MEMORY == cmd.data.offset, + ASSERT_M(getCursor()->pos - VGA_MEMORY == cmd.data.offset, "CMD %i: Position difference | Expected: %i, Actual: %i", idx, - cmd.data.offset, cursor.pos - VGA_MEMORY); + cmd.data.offset, getCursor()->pos - VGA_MEMORY); break; case setPosition: // sets the cursor position, checks that the position is // in bounds @@ -77,7 +77,7 @@ int execCMD(struct TestCMD cmd, int idx) { idx, cmd.data.offset, VGA_SIZE); return 1; } - cursor.pos = VGA_MEMORY + cmd.data.offset; + getCursor()->pos = VGA_MEMORY + cmd.data.offset; break; case keyPress: // simulates a keypress vgaEditor(cmd.data.kb); From c113f5a772abed2743439b413242187b95280209 Mon Sep 17 00:00:00 2001 From: Septicake Date: Mon, 4 Nov 2024 19:14:31 -0500 Subject: [PATCH 56/70] Used a tab instead of spaces --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index fae44ca..b97eda0 100644 --- a/Makefile +++ b/Makefile @@ -52,7 +52,7 @@ OBJ_NAMES := src/os/main.o src/os/test.o os_entry.o src/lib/video/VGA_text.o \ src/lib/device/serial.o src/lib/device/ps2.o src/lib/device/keyboard.o \ src/lib/container/ring_buffer.o \ src/lib/stdlib/stdio.o src/lib/stdlib/stdlib.o src/lib/stdlib/string.o \ - src/lib/pit/pit.o + src/lib/pit/pit.o .PHONY: clean qemu test From c9d465eb95408da7a076ea3e56cdc0384961fd6e Mon Sep 17 00:00:00 2001 From: Septicake Date: Mon, 4 Nov 2024 19:59:20 -0500 Subject: [PATCH 57/70] Correct empty line prevention in assertion macros --- tests/src/test_helper.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/src/test_helper.h b/tests/src/test_helper.h index d4cd714..fa8061c 100644 --- a/tests/src/test_helper.h +++ b/tests/src/test_helper.h @@ -18,7 +18,8 @@ void _assert_fail_m(char *fmt, const char *msg, ...) { serialWrite(COM1, (uint8_t *)msg, strnlen_s(msg, 256)); // avoid an empty line - if (fmt[0] != 0) { + // must be index 1 since a newline is appended by the macro + if (fmt[1] != 0) { int len = vsnprintf(buff, sizeof(buff), fmt, args); while (!serialWriteReady(COM1)) @@ -40,7 +41,8 @@ void _fail_m(char *fmt, const char *msg, ...) { serialWrite(COM1, (uint8_t *)msg, strnlen_s(msg, 256)); // avoid an empty line - if (fmt[0] != 0) { + // must be index 1 since a newline is appended by the macro + if (fmt[1] != 0) { int len = vsnprintf(buff, sizeof(buff), fmt, args); while (!serialWriteReady(COM1)) From d5e24140637f0fbe04ed8e30a910eb11128ea302 Mon Sep 17 00:00:00 2001 From: Septicake Date: Mon, 4 Nov 2024 20:00:04 -0500 Subject: [PATCH 58/70] Add expected number of characters written as a parameter, add 0 edge case test --- tests/src/lib/stdlib/test_stdio.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/tests/src/lib/stdlib/test_stdio.c b/tests/src/lib/stdlib/test_stdio.c index 1769797..56236ca 100644 --- a/tests/src/lib/stdlib/test_stdio.c +++ b/tests/src/lib/stdlib/test_stdio.c @@ -9,7 +9,7 @@ // "expected" is the first argument because variable args need to be the last // argument void test_vsnprintf(char *expected, char *buffer, size_t bufsz, char *fmt, - int argn, ...) { + int num, int argn, ...) { int n; memset(buffer, '#', BUFSZ); @@ -21,6 +21,7 @@ void test_vsnprintf(char *expected, char *buffer, size_t bufsz, char *fmt, // serialWrite(COM1, (uint8_t*)(buffer), BUFSZ); ASSERT(n <= bufsz); + ASSERT(n == num); ASSERT(strncmp(buffer, expected, 2) == 0); ASSERT(buffer[bufsz] == '\0'); } @@ -29,15 +30,16 @@ void test_main() { char buffer[BUFSZ + 1]; buffer[BUFSZ] = '\0'; - test_vsnprintf("Hello!\n", buffer, BUFSZ, "%s\n", 1, "Hello!"); - test_vsnprintf("i=5\n", buffer, BUFSZ, "i=%i\n", 1, 5); - test_vsnprintf("i=42\n", buffer, BUFSZ, "i=%i\n", 1, 42); - test_vsnprintf("i=-42\n", buffer, BUFSZ, "i=%i\n", 1, -42); + test_vsnprintf("Hello!\n", buffer, BUFSZ, "%s\n", 7, 1, "Hello!"); + test_vsnprintf("i=5\n", buffer, BUFSZ, "i=%i\n", 4, 1, 5); + test_vsnprintf("i=42\n", buffer, BUFSZ, "i=%i\n", 5, 1, 42); + test_vsnprintf("i=-42\n", buffer, BUFSZ, "i=%i\n", 6, 1, -42); test_vsnprintf("just a regular string\n", buffer, BUFSZ, - "just a regular string\n", 0); - test_vsnprintf("i=-42%\n", buffer, BUFSZ, "i=%i%%\n", 1, 42); - test_vsnprintf("1, 2, 3, 4, 5\n", buffer, BUFSZ, "%i, %i, %i, %i, %i\n", 5, + "just a regular string\n", 22, 0); + test_vsnprintf("i=-42%\n", buffer, BUFSZ, "i=%i%%\n", 6, 1, 42); + test_vsnprintf("1, 2, 3, 4, 5\n", buffer, BUFSZ, "%i, %i, %i, %i, %i\n", 14, 5, 1, 2, 3, 4, 5); + test_vsnprintf("i=0\n", buffer, BUFSZ, "i=%i\n", 4, 1, 0); char done[] = "test_stdio done\n"; serialWrite(COM1, (uint8_t *)(done), sizeof(done) - 1); From 23d6a1a582c30f88d20ef93d9a40ca09d2b46065 Mon Sep 17 00:00:00 2001 From: Septicake Date: Mon, 4 Nov 2024 20:43:03 -0500 Subject: [PATCH 59/70] Formatting... again --- tests/src/lib/stdlib/test_stdio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/src/lib/stdlib/test_stdio.c b/tests/src/lib/stdlib/test_stdio.c index 56236ca..96cba99 100644 --- a/tests/src/lib/stdlib/test_stdio.c +++ b/tests/src/lib/stdlib/test_stdio.c @@ -37,8 +37,8 @@ void test_main() { test_vsnprintf("just a regular string\n", buffer, BUFSZ, "just a regular string\n", 22, 0); test_vsnprintf("i=-42%\n", buffer, BUFSZ, "i=%i%%\n", 6, 1, 42); - test_vsnprintf("1, 2, 3, 4, 5\n", buffer, BUFSZ, "%i, %i, %i, %i, %i\n", 14, 5, - 1, 2, 3, 4, 5); + test_vsnprintf("1, 2, 3, 4, 5\n", buffer, BUFSZ, "%i, %i, %i, %i, %i\n", 14, + 5, 1, 2, 3, 4, 5); test_vsnprintf("i=0\n", buffer, BUFSZ, "i=%i\n", 4, 1, 0); char done[] = "test_stdio done\n"; From 7b8de96828e499cb25a67536a79c63d5e80f8b64 Mon Sep 17 00:00:00 2001 From: Septicake Date: Mon, 4 Nov 2024 20:44:12 -0500 Subject: [PATCH 60/70] Consolidate both assert functions into one --- tests/src/test_helper.h | 39 ++++++++------------------------------- 1 file changed, 8 insertions(+), 31 deletions(-) diff --git a/tests/src/test_helper.h b/tests/src/test_helper.h index fa8061c..8b1e4e8 100644 --- a/tests/src/test_helper.h +++ b/tests/src/test_helper.h @@ -7,35 +7,10 @@ #include -void _assert_fail_m(char *fmt, const char *msg, ...) { +void _print_assert(char *fmt, const char *msg, ...) { va_list args; va_start(args, msg); - // buffer to write the messages to - char buff[256]; - while (!serialWriteReady(COM1)) - ; - serialWrite(COM1, (uint8_t *)msg, strnlen_s(msg, 256)); - - // avoid an empty line - // must be index 1 since a newline is appended by the macro - if (fmt[1] != 0) { - int len = vsnprintf(buff, sizeof(buff), fmt, args); - - while (!serialWriteReady(COM1)) - ; - serialWrite(COM1, (uint8_t *)buff, len); - } - - va_end(args); -} - -void _fail_m(char *fmt, const char *msg, ...) { - va_list args; - va_start(args, msg); - - // buffer to write the messages to - char buff[256]; while (!serialWriteReady(COM1)) ; serialWrite(COM1, (uint8_t *)msg, strnlen_s(msg, 256)); @@ -43,6 +18,8 @@ void _fail_m(char *fmt, const char *msg, ...) { // avoid an empty line // must be index 1 since a newline is appended by the macro if (fmt[1] != 0) { + // buffer to write the message to + char buff[256]; int len = vsnprintf(buff, sizeof(buff), fmt, args); while (!serialWriteReady(COM1)) @@ -61,14 +38,14 @@ void _fail_m(char *fmt, const char *msg, ...) { #define ASSERT_M(condition, fmt, ...) \ if (!(condition)) { \ - _assert_fail_m(fmt "\n", "Line " STR_LINE ": Assertion '" #condition \ - "' failed.\n" __VA_OPT__(, ) __VA_ARGS__); \ + _print_assert(fmt "\n", "Line " STR_LINE ": Assertion '" #condition \ + "' failed.\n" __VA_OPT__(, ) __VA_ARGS__); \ } #define FAIL_M(fmt, ...) \ - _fail_m(fmt "\n", \ - "Line " STR_LINE ": Fail assertion reached.\n" __VA_OPT__(, ) \ - __VA_ARGS__) + _print_assert(fmt "\n", \ + "Line " STR_LINE \ + ": Fail assertion reached.\n" __VA_OPT__(, ) __VA_ARGS__) #define ASSERT(condition) ASSERT_M(condition, "") From 9707d952ecf2c186c22f75b6ae5fb04e1180850d Mon Sep 17 00:00:00 2001 From: Septicake Date: Mon, 4 Nov 2024 20:49:12 -0500 Subject: [PATCH 61/70] Make `fmt` of snprintf and vsnprintf `const` --- src/lib/stdlib/stdio.c | 10 ++++++---- src/lib/stdlib/stdio.h | 4 ++-- tests/src/test_helper.h | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/lib/stdlib/stdio.c b/src/lib/stdlib/stdio.c index 968c8be..3f74e58 100644 --- a/src/lib/stdlib/stdio.c +++ b/src/lib/stdlib/stdio.c @@ -5,11 +5,12 @@ #define MAX_SNPRINTF_STRING 100 -int snprintf(char *restrict buffer, size_t bufsz, char *format, ...); -int vsnprintf(char *restrict buffer, size_t bufsz, char *format, va_list ap); +int snprintf(char *restrict buffer, size_t bufsz, const char *format, ...); +int vsnprintf(char *restrict buffer, size_t bufsz, const char *format, + va_list ap); // Inspired by chapter 7.3 of The C Programming Language -int snprintf(char *restrict buffer, size_t bufsz, char *format, ...) { +int snprintf(char *restrict buffer, size_t bufsz, const char *format, ...) { va_list ap; int retval; va_start(ap, format); @@ -19,7 +20,8 @@ int snprintf(char *restrict buffer, size_t bufsz, char *format, ...) { return retval; } -int vsnprintf(char *restrict buffer, size_t bufsz, char *format, va_list ap) { +int vsnprintf(char *restrict buffer, size_t bufsz, const char *format, + va_list ap) { char *p; // valid types diff --git a/src/lib/stdlib/stdio.h b/src/lib/stdlib/stdio.h index 01322fc..731f3cd 100644 --- a/src/lib/stdlib/stdio.h +++ b/src/lib/stdlib/stdio.h @@ -3,6 +3,6 @@ #include #include -int snprintf(char *restrict buffer, size_t bufsz, char *format, ...); +int snprintf(char *restrict buffer, size_t bufsz, const char *format, ...); -int vsnprintf(char *restrict buffer, size_t bufsz, char *format, va_list ap); +int vsnprintf(char *restrict buffer, size_t bufsz, const char *format, va_list ap); diff --git a/tests/src/test_helper.h b/tests/src/test_helper.h index 8b1e4e8..efd9bdb 100644 --- a/tests/src/test_helper.h +++ b/tests/src/test_helper.h @@ -7,7 +7,7 @@ #include -void _print_assert(char *fmt, const char *msg, ...) { +void _print_assert(const char *fmt, const char *msg, ...) { va_list args; va_start(args, msg); From 745d6d9a03cdd991c213d4b221c3c6a21e28f776 Mon Sep 17 00:00:00 2001 From: Septicake Date: Mon, 4 Nov 2024 20:50:41 -0500 Subject: [PATCH 62/70] Formatting once more --- src/lib/stdlib/stdio.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lib/stdlib/stdio.h b/src/lib/stdlib/stdio.h index 731f3cd..8d5085d 100644 --- a/src/lib/stdlib/stdio.h +++ b/src/lib/stdlib/stdio.h @@ -5,4 +5,5 @@ int snprintf(char *restrict buffer, size_t bufsz, const char *format, ...); -int vsnprintf(char *restrict buffer, size_t bufsz, const char *format, va_list ap); +int vsnprintf(char *restrict buffer, size_t bufsz, const char *format, + va_list ap); From 6356409a7db4aff0b0358b24c992c39839e2cf45 Mon Sep 17 00:00:00 2001 From: Septicake Date: Mon, 4 Nov 2024 21:08:00 -0500 Subject: [PATCH 63/70] make `p` const to get the compiler to shut up --- src/lib/stdlib/stdio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/stdlib/stdio.c b/src/lib/stdlib/stdio.c index 3f74e58..e85559f 100644 --- a/src/lib/stdlib/stdio.c +++ b/src/lib/stdlib/stdio.c @@ -22,7 +22,7 @@ int snprintf(char *restrict buffer, size_t bufsz, const char *format, ...) { int vsnprintf(char *restrict buffer, size_t bufsz, const char *format, va_list ap) { - char *p; + const char *p; // valid types unsigned char c; // printf("%c\n", 'c'); From 16ba516e46b8186a8cf75eda9535310dc758c19d Mon Sep 17 00:00:00 2001 From: Septicake Date: Mon, 4 Nov 2024 21:09:47 -0500 Subject: [PATCH 64/70] Extracted a decent chunk of duplicate code, it is likely possible to extract more but I can't quite figure out how --- src/lib/device/ps2.c | 83 +++++++++++++++++++------------------------- 1 file changed, 36 insertions(+), 47 deletions(-) diff --git a/src/lib/device/ps2.c b/src/lib/device/ps2.c index e084475..0fe4a0a 100644 --- a/src/lib/device/ps2.c +++ b/src/lib/device/ps2.c @@ -121,47 +121,18 @@ void specialHandler(KeyPress out) { break; } } else { + if (((out.code == Key_up || out.code == Key_left) && + cursorIsAtStart()) || + ((out.code == Key_down || out.code == Key_right) && + cursorIsAtEnd())) + return; + if ((out.code == Key_up || out.code == Key_left || + out.code == Key_down || out.code == Key_right) && + !getCursor()->highlight_offset) + highlightCurrentChar(); switch (out.code) { case Key_up: - if (!cursorIsAtStart()) { - if (!getCursor()->highlight_offset) - highlightCurrentChar(); - for (int i = 0; i < VGA_WIDTH && !cursorIsAtStart(); i++) { - if (getCursor()->highlight_offset > 0) { - highlightCurrentChar(); - cursorLeft(); - } else { - cursorLeft(); - highlightCurrentChar(); - } - getCursor()->highlight_offset--; - } - if (!getCursor()->highlight_offset) - highlightCurrentChar(); - } - break; - case Key_down: - if (!cursorIsAtEnd()) { - if (!getCursor()->highlight_offset) - highlightCurrentChar(); - for (int i = 0; i < VGA_WIDTH && !cursorIsAtEnd(); i++) { - if (getCursor()->highlight_offset < 0) { - highlightCurrentChar(); - cursorRight(); - } else { - cursorRight(); - highlightCurrentChar(); - } - getCursor()->highlight_offset++; - } - if (!getCursor()->highlight_offset) - highlightCurrentChar(); - } - break; - case Key_left: - if (!cursorIsAtStart()) { - if (!getCursor()->highlight_offset) - highlightCurrentChar(); + for (int i = 0; i < VGA_WIDTH && !cursorIsAtStart(); i++) { if (getCursor()->highlight_offset > 0) { highlightCurrentChar(); cursorLeft(); @@ -170,14 +141,10 @@ void specialHandler(KeyPress out) { highlightCurrentChar(); } getCursor()->highlight_offset--; - if (!getCursor()->highlight_offset) - highlightCurrentChar(); } break; - case Key_right: - if (!cursorIsAtEnd()) { - if (!getCursor()->highlight_offset) - highlightCurrentChar(); + case Key_down: + for (int i = 0; i < VGA_WIDTH && !cursorIsAtEnd(); i++) { if (getCursor()->highlight_offset < 0) { highlightCurrentChar(); cursorRight(); @@ -186,13 +153,35 @@ void specialHandler(KeyPress out) { highlightCurrentChar(); } getCursor()->highlight_offset++; - if (!getCursor()->highlight_offset) - highlightCurrentChar(); } break; + case Key_left: + if (getCursor()->highlight_offset > 0) { + highlightCurrentChar(); + cursorLeft(); + } else { + cursorLeft(); + highlightCurrentChar(); + } + getCursor()->highlight_offset--; + break; + case Key_right: + if (getCursor()->highlight_offset < 0) { + highlightCurrentChar(); + cursorRight(); + } else { + cursorRight(); + highlightCurrentChar(); + } + getCursor()->highlight_offset++; + break; default: break; } + if ((out.code == Key_up || out.code == Key_left || + out.code == Key_down || out.code == Key_right) && + !getCursor()->highlight_offset) + highlightCurrentChar(); } } From 1a57af65030aa868da01c9adfcd57325ea3c2e24 Mon Sep 17 00:00:00 2001 From: Real-Septicake Date: Wed, 6 Nov 2024 16:29:43 -0500 Subject: [PATCH 65/70] Update dependencies listed in README --- tests/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/README.md b/tests/README.md index 4e70007..fed786b 100644 --- a/tests/README.md +++ b/tests/README.md @@ -36,3 +36,4 @@ The `.expect` file consists of all the output the `.c` file will produce when ev Testing requires the same dependencies as normal operation along with the following: * Python 3.8 + * Python virtualenv From caeef148d06cd784f81026f7db4dd86a6c427c46 Mon Sep 17 00:00:00 2001 From: Real-Septicake Date: Tue, 12 Nov 2024 16:44:29 -0500 Subject: [PATCH 66/70] `venv` not `virtualenv` --- tests/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/README.md b/tests/README.md index fed786b..4a0915b 100644 --- a/tests/README.md +++ b/tests/README.md @@ -36,4 +36,4 @@ The `.expect` file consists of all the output the `.c` file will produce when ev Testing requires the same dependencies as normal operation along with the following: * Python 3.8 - * Python virtualenv + * Python venv From f3f88481f95ab5cbed0d0aa3670b441143fccb16 Mon Sep 17 00:00:00 2001 From: Real-Septicake Date: Tue, 19 Nov 2024 14:24:43 -0500 Subject: [PATCH 67/70] Create file for handling special key cases --- Makefile | 2 +- src/lib/device/key_handlers.c | 115 ++++++++++++++++++++++++++++++++++ src/lib/device/key_handlers.h | 8 +++ src/lib/device/ps2.c | 114 +-------------------------------- 4 files changed, 125 insertions(+), 114 deletions(-) create mode 100644 src/lib/device/key_handlers.c create mode 100644 src/lib/device/key_handlers.h diff --git a/Makefile b/Makefile index b97eda0..b965aaa 100644 --- a/Makefile +++ b/Makefile @@ -52,7 +52,7 @@ OBJ_NAMES := src/os/main.o src/os/test.o os_entry.o src/lib/video/VGA_text.o \ src/lib/device/serial.o src/lib/device/ps2.o src/lib/device/keyboard.o \ src/lib/container/ring_buffer.o \ src/lib/stdlib/stdio.o src/lib/stdlib/stdlib.o src/lib/stdlib/string.o \ - src/lib/pit/pit.o + src/lib/pit/pit.o src/lib/device/key_handlers.o .PHONY: clean qemu test diff --git a/src/lib/device/key_handlers.c b/src/lib/device/key_handlers.c new file mode 100644 index 0000000..bad0d85 --- /dev/null +++ b/src/lib/device/key_handlers.c @@ -0,0 +1,115 @@ +#include "key_handlers.h" +#include "video/VGA_text.h" + +void specialHandler(KeyPress out) { + if (!(out.modifiers & KEY_MOD_SHIFT)) { + switch (out.code) { + case Key_backspace: + if (getCursor()->highlight_offset) { + highlightDeletePrev(getCursor()->highlight_offset); + getCursor()->highlight_offset = 0; + } else + deletePrevChar(); + break; + case Key_delete: + if (getCursor()->highlight_offset) { + highlightDeleteCurrent(getCursor()->highlight_offset); + getCursor()->highlight_offset = 0; + } else + deleteCurrentChar(); + break; + case Key_left: + if (getCursor()->highlight_offset) { + cursorHighlightLeft(getCursor()->highlight_offset); + getCursor()->highlight_offset = 0; + } else + cursorLeft(); + break; + case Key_down: + if (getCursor()->highlight_offset) { + cursorHighlightDown(getCursor()->highlight_offset); + getCursor()->highlight_offset = 0; + } else + cursorDown(); + break; + case Key_up: + if (getCursor()->highlight_offset) { + cursorHighlightUp(getCursor()->highlight_offset); + getCursor()->highlight_offset = 0; + } else + cursorUp(); + break; + case Key_right: + if (getCursor()->highlight_offset) { + cursorHighlightRight(getCursor()->highlight_offset); + getCursor()->highlight_offset = 0; + } else + cursorRight(); + break; + default: + break; + } + } else { + if (((out.code == Key_up || out.code == Key_left) && + cursorIsAtStart()) || + ((out.code == Key_down || out.code == Key_right) && + cursorIsAtEnd())) + return; + if ((out.code == Key_up || out.code == Key_left || + out.code == Key_down || out.code == Key_right) && + !getCursor()->highlight_offset) + highlightCurrentChar(); + switch (out.code) { + case Key_up: + for (int i = 0; i < VGA_WIDTH && !cursorIsAtStart(); i++) { + if (getCursor()->highlight_offset > 0) { + highlightCurrentChar(); + cursorLeft(); + } else { + cursorLeft(); + highlightCurrentChar(); + } + getCursor()->highlight_offset--; + } + break; + case Key_down: + for (int i = 0; i < VGA_WIDTH && !cursorIsAtEnd(); i++) { + if (getCursor()->highlight_offset < 0) { + highlightCurrentChar(); + cursorRight(); + } else { + cursorRight(); + highlightCurrentChar(); + } + getCursor()->highlight_offset++; + } + break; + case Key_left: + if (getCursor()->highlight_offset > 0) { + highlightCurrentChar(); + cursorLeft(); + } else { + cursorLeft(); + highlightCurrentChar(); + } + getCursor()->highlight_offset--; + break; + case Key_right: + if (getCursor()->highlight_offset < 0) { + highlightCurrentChar(); + cursorRight(); + } else { + cursorRight(); + highlightCurrentChar(); + } + getCursor()->highlight_offset++; + break; + default: + break; + } + if ((out.code == Key_up || out.code == Key_left || + out.code == Key_down || out.code == Key_right) && + !getCursor()->highlight_offset) + highlightCurrentChar(); + } +} \ No newline at end of file diff --git a/src/lib/device/key_handlers.h b/src/lib/device/key_handlers.h new file mode 100644 index 0000000..c93ff22 --- /dev/null +++ b/src/lib/device/key_handlers.h @@ -0,0 +1,8 @@ +#ifndef KEY_HANDLERS_H +#define KEY_HANDLERS_H + +#include "keyboard.h" + +void specialHandler(KeyPress out); + +#endif \ No newline at end of file diff --git a/src/lib/device/ps2.c b/src/lib/device/ps2.c index 0fe4a0a..0a3f763 100644 --- a/src/lib/device/ps2.c +++ b/src/lib/device/ps2.c @@ -3,6 +3,7 @@ #include "../../os/hard/idt.h" #include "../../os/hard/port_io.h" #include "container/ring_buffer.h" +#include "key_handlers.h" #define PS2_BUF_SIZE 64 #define PS2_TIMEOUT 100000 @@ -72,119 +73,6 @@ const struct PS2Device *getPortType(int portnum) { // temporary include for #7 #include "video/VGA_text.h" -void specialHandler(KeyPress out) { - if (!(out.modifiers & KEY_MOD_SHIFT)) { - switch (out.code) { - case Key_backspace: - if (getCursor()->highlight_offset) { - highlightDeletePrev(getCursor()->highlight_offset); - getCursor()->highlight_offset = 0; - } else - deletePrevChar(); - break; - case Key_delete: - if (getCursor()->highlight_offset) { - highlightDeleteCurrent(getCursor()->highlight_offset); - getCursor()->highlight_offset = 0; - } else - deleteCurrentChar(); - break; - case Key_left: - if (getCursor()->highlight_offset) { - cursorHighlightLeft(getCursor()->highlight_offset); - getCursor()->highlight_offset = 0; - } else - cursorLeft(); - break; - case Key_down: - if (getCursor()->highlight_offset) { - cursorHighlightDown(getCursor()->highlight_offset); - getCursor()->highlight_offset = 0; - } else - cursorDown(); - break; - case Key_up: - if (getCursor()->highlight_offset) { - cursorHighlightUp(getCursor()->highlight_offset); - getCursor()->highlight_offset = 0; - } else - cursorUp(); - break; - case Key_right: - if (getCursor()->highlight_offset) { - cursorHighlightRight(getCursor()->highlight_offset); - getCursor()->highlight_offset = 0; - } else - cursorRight(); - break; - default: - break; - } - } else { - if (((out.code == Key_up || out.code == Key_left) && - cursorIsAtStart()) || - ((out.code == Key_down || out.code == Key_right) && - cursorIsAtEnd())) - return; - if ((out.code == Key_up || out.code == Key_left || - out.code == Key_down || out.code == Key_right) && - !getCursor()->highlight_offset) - highlightCurrentChar(); - switch (out.code) { - case Key_up: - for (int i = 0; i < VGA_WIDTH && !cursorIsAtStart(); i++) { - if (getCursor()->highlight_offset > 0) { - highlightCurrentChar(); - cursorLeft(); - } else { - cursorLeft(); - highlightCurrentChar(); - } - getCursor()->highlight_offset--; - } - break; - case Key_down: - for (int i = 0; i < VGA_WIDTH && !cursorIsAtEnd(); i++) { - if (getCursor()->highlight_offset < 0) { - highlightCurrentChar(); - cursorRight(); - } else { - cursorRight(); - highlightCurrentChar(); - } - getCursor()->highlight_offset++; - } - break; - case Key_left: - if (getCursor()->highlight_offset > 0) { - highlightCurrentChar(); - cursorLeft(); - } else { - cursorLeft(); - highlightCurrentChar(); - } - getCursor()->highlight_offset--; - break; - case Key_right: - if (getCursor()->highlight_offset < 0) { - highlightCurrentChar(); - cursorRight(); - } else { - cursorRight(); - highlightCurrentChar(); - } - getCursor()->highlight_offset++; - break; - default: - break; - } - if ((out.code == Key_up || out.code == Key_left || - out.code == Key_down || out.code == Key_right) && - !getCursor()->highlight_offset) - highlightCurrentChar(); - } -} - void vgaEditor(struct PS2Buf_t out) { switch (out.keyEvent.code) { case Key_backspace: From 4bc987e2c1261174b36aeb6c7b03577493c9662b Mon Sep 17 00:00:00 2001 From: Real-Septicake Date: Tue, 19 Nov 2024 14:29:07 -0500 Subject: [PATCH 68/70] Formatting once again --- src/lib/device/key_handlers.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib/device/key_handlers.c b/src/lib/device/key_handlers.c index bad0d85..9c3bfdc 100644 --- a/src/lib/device/key_handlers.c +++ b/src/lib/device/key_handlers.c @@ -1,4 +1,5 @@ #include "key_handlers.h" + #include "video/VGA_text.h" void specialHandler(KeyPress out) { From 77dbb853c40d1f1c3b6e4eeab52d4f1e102bbd19 Mon Sep 17 00:00:00 2001 From: Real-Septicake Date: Mon, 23 Dec 2024 17:39:29 -0500 Subject: [PATCH 69/70] Attempt at a quick fix for termcolor not respecting Windows' terminals lack of ansi color support --- tests/test.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/tests/test.py b/tests/test.py index ef9a113..5bee39d 100644 --- a/tests/test.py +++ b/tests/test.py @@ -6,9 +6,12 @@ import errno import shutil import sys +import platform from termcolor import cprint +no_color = platform.system().find('Windows') != -1 + BASE_PORT = 1111 MAX_PORT = 1234 @@ -113,7 +116,7 @@ def beginQemu(self): self._qemu = subprocess.Popen(command, stdin=subprocess.PIPE, stderr=subprocess.PIPE, stdout=subprocess.PIPE) time.sleep(1) #give qemu some time to open self._ready = True - cprint(self.bin_path.name + " has started.", "green") + cprint(self.bin_path.name + " has started.", "green", no_color=no_color) def beginTest(self): self.test = Thread(target=test, args=[self]) @@ -138,13 +141,13 @@ def endQemu(self): except: # force qemu to quit since it refuses to exit normally - cprint(self.bin_path.name + " was forcefully closed.", "red", attrs=["bold"]) + cprint(self.bin_path.name + " was forcefully closed.", "red", attrs=["bold"], no_color=no_color) self._qemu.kill() self._qemu.wait(5) self._qemu = None self._ready = False - cprint(self.bin_path.name + " has exited.", "cyan") + cprint(self.bin_path.name + " has exited.", "cyan", no_color=no_color) os.remove(self._qemu_file) def end(self): @@ -274,7 +277,7 @@ def test(instance: TestInstance): return test_end_stub(instance, passed) except socket.timeout: - cprint(instance.bin_path.name + " | test timed out", "red") + cprint(instance.bin_path.name + " | test timed out", "red", no_color=no_color) except socket.error as e: @@ -365,10 +368,10 @@ def do_tests(): result = instance.result if (result): total_pass += 1 - cprint(instance.bin_path.name + " PASSED", "light_green") + cprint(instance.bin_path.name + " PASSED", "light_green", no_color=no_color) else: total_fail += 1 - cprint(instance.bin_path.name + " FAILED", "red", attrs=["bold"]) + cprint(instance.bin_path.name + " FAILED", "red", attrs=["bold"], no_color=no_color) print("Summary: PASSED-{}, FAILED-{}, TOTAL-{}" .format(total_pass, total_fail, len(instances))) From 4f4125db832dcb70bf2e8996bd446b8c8fdd94ba Mon Sep 17 00:00:00 2001 From: Real-Septicake Date: Mon, 23 Dec 2024 17:51:20 -0500 Subject: [PATCH 70/70] Use colorama instead of the inelegant selective disabling of color on Windows --- tests/requirements.txt | 3 ++- tests/test.py | 16 ++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/tests/requirements.txt b/tests/requirements.txt index f3d82a4..9cc8ab2 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1 +1,2 @@ -termcolor==2.5.0 \ No newline at end of file +termcolor==2.5.0 +colorama==0.4.6 \ No newline at end of file diff --git a/tests/test.py b/tests/test.py index 5bee39d..d19a702 100644 --- a/tests/test.py +++ b/tests/test.py @@ -6,11 +6,11 @@ import errno import shutil import sys -import platform from termcolor import cprint +from colorama import just_fix_windows_console -no_color = platform.system().find('Windows') != -1 +just_fix_windows_console() BASE_PORT = 1111 MAX_PORT = 1234 @@ -116,7 +116,7 @@ def beginQemu(self): self._qemu = subprocess.Popen(command, stdin=subprocess.PIPE, stderr=subprocess.PIPE, stdout=subprocess.PIPE) time.sleep(1) #give qemu some time to open self._ready = True - cprint(self.bin_path.name + " has started.", "green", no_color=no_color) + cprint(self.bin_path.name + " has started.", "green") def beginTest(self): self.test = Thread(target=test, args=[self]) @@ -141,13 +141,13 @@ def endQemu(self): except: # force qemu to quit since it refuses to exit normally - cprint(self.bin_path.name + " was forcefully closed.", "red", attrs=["bold"], no_color=no_color) + cprint(self.bin_path.name + " was forcefully closed.", "red", attrs=["bold"]) self._qemu.kill() self._qemu.wait(5) self._qemu = None self._ready = False - cprint(self.bin_path.name + " has exited.", "cyan", no_color=no_color) + cprint(self.bin_path.name + " has exited.", "cyan") os.remove(self._qemu_file) def end(self): @@ -277,7 +277,7 @@ def test(instance: TestInstance): return test_end_stub(instance, passed) except socket.timeout: - cprint(instance.bin_path.name + " | test timed out", "red", no_color=no_color) + cprint(instance.bin_path.name + " | test timed out", "red") except socket.error as e: @@ -368,10 +368,10 @@ def do_tests(): result = instance.result if (result): total_pass += 1 - cprint(instance.bin_path.name + " PASSED", "light_green", no_color=no_color) + cprint(instance.bin_path.name + " PASSED", "light_green") else: total_fail += 1 - cprint(instance.bin_path.name + " FAILED", "red", attrs=["bold"], no_color=no_color) + cprint(instance.bin_path.name + " FAILED", "red", attrs=["bold"]) print("Summary: PASSED-{}, FAILED-{}, TOTAL-{}" .format(total_pass, total_fail, len(instances)))