Started Implementing a BASIC interpriter

This commit is contained in:
OusmBlueNinja 2024-12-30 15:52:32 -06:00
parent e82fb49c04
commit 3eee0f8269
73 changed files with 984 additions and 644 deletions

22
.vscode/c_cpp_properties.json vendored Normal file
View File

@ -0,0 +1,22 @@
{
"configurations": [
{
"name": "Win32",
"includePath": [
"${default}",
"${workspaceFolder}/**"
],
"defines": [
"_DEBUG",
"UNICODE",
"_UNICODE"
],
"windowsSdkVersion": "10.0.22621.0",
"compilerPath": "C:/msys64/mingw64/bin/gcc.exe",
"cStandard": "c17",
"cppStandard": "c++17",
"intelliSenseMode": "linux-gcc-x64"
}
],
"version": 4
}

Binary file not shown.

Binary file not shown.

BIN
build/x86_64/basic.o Normal file

Binary file not shown.

BIN
build/x86_64/strings.o Normal file

Binary file not shown.

BIN
dist/x86_64/kernel.bin vendored Normal file

Binary file not shown.

View File

@ -10,11 +10,9 @@
#include "window.h"
#include "fs.h"
#include "fat12.h"
#include "basic.h"
#define COMMAND_BUFFER_SIZE 256 // Increase buffer size to handle longer commands
#define COMMAND_BUFFER_SIZE 256 // Increase buffer size to handle longer commands
#define BACKSPACE_KEY 8
#define HISTORY_SIZE 10
#define COMMAND_BUFFER_SIZE 256
@ -22,29 +20,31 @@
extern void kpanic(int error_code);
void shutdown_system() {
__asm__ (
"movl $1, %eax\n" // syscall number for sys_reboot (1 in this case)
"movl $0, %ebx\n" // reboot flags
"movl $0, %ecx\n" // no additional arguments
"movl $0, %edx\n" // no additional arguments
"int $0x80\n" // interrupt to invoke syscall
void shutdown_system()
{
__asm__(
"movl $1, %eax\n" // syscall number for sys_reboot (1 in this case)
"movl $0, %ebx\n" // reboot flags
"movl $0, %ecx\n" // no additional arguments
"movl $0, %edx\n" // no additional arguments
"int $0x80\n" // interrupt to invoke syscall
);
}
char commandHistory[HISTORY_SIZE][COMMAND_BUFFER_SIZE];
int currentHistoryIndex = 0;
int historyCount = 0;
void add_to_history(const char* command) {
if (historyCount < HISTORY_SIZE) {
void add_to_history(const char *command)
{
if (historyCount < HISTORY_SIZE)
{
historyCount++;
} else {
for (int i = 1; i < HISTORY_SIZE; i++) {
}
else
{
for (int i = 1; i < HISTORY_SIZE; i++)
{
strcpy(commandHistory[i - 1], commandHistory[i]);
}
}
@ -52,23 +52,26 @@ void add_to_history(const char* command) {
currentHistoryIndex = historyCount;
}
const char* get_previous_command() {
if (currentHistoryIndex > 0) {
const char *get_previous_command()
{
if (currentHistoryIndex > 0)
{
currentHistoryIndex--;
return commandHistory[currentHistoryIndex];
}
return NULL;
}
const char* get_next_command() {
if (currentHistoryIndex < historyCount - 1) {
const char *get_next_command()
{
if (currentHistoryIndex < historyCount - 1)
{
currentHistoryIndex++;
return commandHistory[currentHistoryIndex];
}
return NULL;
}
const void clear()
{
print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLACK); // Set text color
@ -79,113 +82,127 @@ const void clear()
print_setup_prompt();
}
void halt(){
void halt()
{
print_str("[ WARN ] HALT\n");
while (1) {}
while (1)
{
}
}
void commandHandler(char* command) {
void commandHandler(char *command)
{
printf("\n");
if (strcmp(command, "cls") == 0) {
if (strcmp(command, "cls") == 0)
{
clear();
} else if (strcmp(command, "knp") == 0) {
}
else if (strcmp(command, "knp") == 0)
{
kpanic(1);
} else if (int_strncmp(command, "echo ", 5) == 0) {
char* message = command + 5; // Skip the "echo " part
}
else if (int_strncmp(command, "echo ", 5) == 0)
{
char *message = command + 5; // Skip the "echo " part
print_str("\n");
print_str(message);
print_str("\n");
} else if (int_strncmp(command, "cwin", 4) == 0) {
}
else if (int_strncmp(command, "cwin", 4) == 0)
{
// Define window properties
Window myWindow;
int x = 8; // X position of the window
int y = 4; // Y position of the window
int width = 30; // Width of the window
int height = 10; // Height of the window
uint8_t borderColor = PRINT_COLOR_RED; // Border color
int x = 8; // X position of the window
int y = 4; // Y position of the window
int width = 30; // Width of the window
int height = 10; // Height of the window
uint8_t borderColor = PRINT_COLOR_RED; // Border color
uint8_t backgroundColor = PRINT_COLOR_BLUE; // Background color
// Create and display the window
create_window(&myWindow, x, y, width, height, borderColor, backgroundColor, "Main Window");
// Print text inside the window
print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLUE); // Set text color
print_text_in_window(&myWindow, 2, 2, "Window Manager is a ");
print_text_in_window(&myWindow, 2, 3, "Work in progress, Sorry :("); // Print text inside the window
print_text_in_window(&myWindow, 2, 4, "do [ cls ] to clear"); // Print text inside the window
} else if (int_strncmp(command, "exit", 4) == 0) {
print_text_in_window(&myWindow, 2, 4, "do [ cls ] to clear"); // Print text inside the window
}
else if (int_strncmp(command, "exit", 4) == 0)
{
printf("Driver Call [ shutdown_system(); ] \n");
shutdown_system();
} else if (int_strncmp(command, "panic_test", 10) == 0) {
int _y = 1/0;
}
else if (int_strncmp(command, "panic_test", 10) == 0)
{
int _y = 1 / 0;
printf("Output %d\n", _y);
} else if (int_strncmp(command, "test", 4) == 0) {
}
else if (int_strncmp(command, "test", 4) == 0)
{
//// Test custom malloc and free
//void* block1 = malloc(32);
//void* block2 = malloc(64);
//void* block3 = malloc(128);
//
// void* block1 = malloc(32);
// void* block2 = malloc(64);
// void* block3 = malloc(128);
//
//// List used blocks
//list_used_blocks();
//
// list_used_blocks();
//
//// Free a block and check again
//free(block2);
//printf("\nAfter freeing block2:\n");
//list_used_blocks();
// free(block2);
// printf("\nAfter freeing block2:\n");
// list_used_blocks();
//
//void* block4 = malloc(64);
// void* block4 = malloc(64);
//
//list_used_blocks();
// list_used_blocks();
create_game();
} else if (int_strncmp(command, "split", 5) == 0) {
}
else if (int_strncmp(command, "split", 5) == 0)
{
printf("Kernel Call [ split_string(); ]\n");
// Check the length of the command string and use it properly
char** new_command = split_string(command, ",", strlen(command));
//char** new_command = {{NULL, NULL, NULL, NULL}};
if (new_command) {
char **new_command = split_string(command, ",", strlen(command));
// char** new_command = {{NULL, NULL, NULL, NULL}};
if (new_command)
{
// Add a loop to print all the elements in the new_command array for debugging
for (int i = 0; new_command[i] != NULL; i++) {
for (int i = 0; new_command[i] != NULL; i++)
{
printf("new_command[%d]: %s\n", i, new_command[i]);
}
//halt(); // Debug halt
// halt(); // Debug halt
// Ensure that new_command[1] exists before accessing it
if (new_command[1] != NULL) {
if (new_command[1] != NULL)
{
printf("%s\n", new_command[1]);
} else {
}
else
{
printf("Error: new_command[1] is NULL\n");
}
} else {
printf("Error: split_string returned NULL\n");
}
else
{
printf("Error: split_string returned NULL\n");
}
}
} else {
else
{
printf("Unknown command: %s\n", command);
}
}
void print_setup_prompt() {
void print_setup_prompt()
{
move_cursor(0, 0);
print_set_color(PRINT_COLOR_LIGHT_RED, PRINT_COLOR_BLACK);
print_str("-------------------- ");
@ -197,34 +214,58 @@ void print_setup_prompt() {
print_str("V 1.5.01\n");
}
int test_basic()
{
InterpreterState state;
init_state(&state);
const char *program[] = {
"LET A = 10",
"LET B = 20",
"PRINT A + B",
"LET A = \"Hello\"",
"LET B = \" World\"",
"PRINT A + B",
"END",
};
for (size_t i = 0; i < sizeof(program) / sizeof(program[0]); i++)
{
execute_line(&state, program[i]);
if (!state.running)
break;
}
return 0;
}
void kernel_main()
{
void kernel_main() {
init_keyboard_driver();
idt_install();
print_str("[ WARN ] Skipping File System Initialization...\n[ INFO ] Do [ fsinit ] to initalize the filesystem\n");
if (fat12_init() == 0) {
if (fat12_init() == 0)
{
printf("Filesystem mounted\n");
fat12_read_root_directory();
fat12_dir_entry_t entry;
if (fat12_find_file("HELLOTXT", &entry)) {
if (fat12_find_file("HELLOTXT", &entry))
{
printf("File found: HELLO.TXT\n");
}
}
print_setup_prompt();
clear();
test_basic();
print_setup_prompt();
print_str(" > ");
@ -232,57 +273,64 @@ void kernel_main() {
char key;
bool keydown = false;
char commandBuffer[COMMAND_BUFFER_SIZE];
size_t commandLength = 0; // To track the length of the current command
size_t commandLength = 0; // To track the length of the current command
while (1) {
while (1)
{
key = read_key();
if (key != 0) {
if (!keydown) {
if (key != 0)
{
if (!keydown)
{
CursorPosition pos = get_print_cursor_pos();
move_cursor(pos.x,pos.y);
if (key == 10) { // Enter key
commandBuffer[commandLength] = '\0'; // Null-terminate the command
move_cursor(pos.x, pos.y);
if (key == 10)
{ // Enter key
commandBuffer[commandLength] = '\0'; // Null-terminate the command
commandHandler(commandBuffer);
// Reset command buffer for the next input
commandLength = 0;
print_str(" > ");
} else if (key == BACKSPACE_KEY) { // Backspace key
if (commandLength > 0) {
}
else if (key == BACKSPACE_KEY)
{ // Backspace key
if (commandLength > 0)
{
// Remove the last character from the buffer
commandLength--;
commandBuffer[commandLength] = '0'; // Null-terminate after removal
commandBuffer[commandLength] = '0'; // Null-terminate after removal
// Clear the character from the screen (overwrite with space)
// Move cursor back one position
offset_print_cursor(-1,0);
print_char(' '); // Overwrite the character
offset_print_cursor(-1,0); // Move cursor back one position(because its moved left one by the rpintf)
offset_print_cursor(-1, 0);
print_char(' '); // Overwrite the character
offset_print_cursor(-1, 0); // Move cursor back one position(because its moved left one by the rpintf)
}
} else {
if (key >= 32 && key <= 126) { // Check if the key is a printable character
if (commandLength < COMMAND_BUFFER_SIZE - 1) {
commandBuffer[commandLength++] = key; // Append character to buffer
}
else
{
if (key >= 32 && key <= 126)
{ // Check if the key is a printable character
if (commandLength < COMMAND_BUFFER_SIZE - 1)
{
commandBuffer[commandLength++] = key; // Append character to buffer
commandBuffer[commandLength] = '\0'; // Null-terminate the buffer
print_char(key); // Print key to the screen
print_char(key); // Print key to the screen
}
}
}
keydown = true;
}
} else {
}
else
{
keydown = false;
}
// int x = 100/0;
}
kpanic(2);
}

184
src/impl/x86_64/basic.c Normal file
View File

@ -0,0 +1,184 @@
#include "memory.h"
#include "print.h"
#include "strings.h"
#include "stdint.h"
#include "stddef.h"
#include "basic.h"
// Utility: Find or create a variable by name
Variable* get_variable(InterpreterState* state, const char* name) {
for (size_t i = 0; i < state->variable_count; i++) {
if (strcmp(state->variables[i].name, name) == 0) {
return &state->variables[i];
}
}
if (state->variable_count < MAX_VARIABLES) {
Variable* var = &state->variables[state->variable_count++];
strncpy(var->name, name, sizeof(var->name) - 1);
var->name[sizeof(var->name) - 1] = '\0';
var->value = 0;
var->str_value = NULL;
return var;
}
return NULL; // No space for more variables
}
// Parse an integer from a string, skipping leading whitespace
int parse_int(const char* str) {
while (*str == ' ') str++; // Skip leading spaces
int result = 0;
int sign = 1;
if (*str == '-') {
sign = -1;
str++;
}
while (*str >= '0' && *str <= '9') {
result = result * 10 + (*str - '0');
str++;
}
return result * sign;
}
const char* evaluate_expression(InterpreterState* state, const char* expr) {
char buffer[64];
strncpy(buffer, expr, sizeof(buffer) - 1);
buffer[sizeof(buffer) - 1] = '\0';
char* plus = strrchr(buffer, '+');
if (plus) {
*plus = '\0';
// Evaluate the left and right sides only once
const char* left = evaluate_expression(state, buffer);
const char* right = evaluate_expression(state, plus + 1);
// Debug output
printf("DEBUG: Left operand: %s\n", left);
printf("DEBUG: Right operand: %s\n", right);
// Check if both sides are numeric
int left_is_number = (left[0] >= '0' && left[0] <= '9') || (left[0] == '-' && left[1] >= '0' && left[1] <= '9');
int right_is_number = (right[0] >= '0' && right[0] <= '9') || (right[0] == '-' && right[1] >= '0' && right[1] <= '9');
static char result[128];
if (left_is_number && right_is_number) {
// Parse the left and right operands
int left_value = parse_int(left);
int right_value = parse_int(right);
// Correct addition logic
int sum = left_value + right_value;
// Debug addition
printf("DEBUG: Adding %d + %d = %d\n", left_value, right_value, sum);
// Format the result as a string
snprintf(result, sizeof(result), "%d", sum);
} else {
// Concatenate strings
snprintf(result, sizeof(result), "%s%s", left, right);
// Debug string concatenation
printf("DEBUG: Concatenating strings: %s + %s = %s\n", left, right, result);
}
return result;
}
// Trim leading and trailing spaces
const char* start = buffer;
while (*start == ' ') start++;
char* end = buffer + strlen(buffer) - 1;
while (end > start && *end == ' ') *end-- = '\0';
if (start[0] >= 'A' && start[0] <= 'Z') {
Variable* var = get_variable(state, start);
if (var) {
static char var_result[64];
if (var->str_value) {
strncpy(var_result, var->str_value, sizeof(var_result) - 1);
var_result[sizeof(var_result) - 1] = '\0';
return var_result;
} else {
snprintf(var_result, sizeof(var_result), "%d", var->value);
return var_result;
}
}
}
if (start[0] == '"') {
// String literal
size_t len = strlen(start);
if (start[len - 1] == '"') {
static char str_result[64];
strncpy(str_result, start + 1, len - 2);
str_result[len - 2] = '\0';
return str_result;
}
}
static char int_result[16];
snprintf(int_result, sizeof(int_result), "%d", parse_int(start));
return int_result;
}
// Interpret a single line of code
void interpret_line(InterpreterState* state, const char* line) {
if (strncmp(line, "LET", 3) == 0) {
const char* rest = line + 3;
while (*rest == ' ') rest++;
const char* equals = strchr(rest, '=');
if (!equals) return;
char var_name[16];
strncpy(var_name, rest, equals - rest);
var_name[equals - rest] = '\0';
// Trim trailing spaces from var_name
size_t len = strlen(var_name);
while (len > 0 && var_name[len - 1] == ' ') {
var_name[--len] = '\0';
}
Variable* var = get_variable(state, var_name);
if (var) {
const char* value = evaluate_expression(state, equals + 1);
if (value[0] >= '0' && value[0] <= '9') {
var->value = parse_int(value);
var->str_value = NULL;
} else {
var->str_value = malloc(strlen(value) + 1);
strcpy(var->str_value, value);
}
}
} else if (strncmp(line, "PRINT", 5) == 0) {
const char* rest = line + 5;
while (*rest == ' ') rest++;
const char* value = evaluate_expression(state, rest);
printf("%s\n", value);
} else if (strncmp(line, "END", 3) == 0) {
printf("Program terminated.\n");
state->running = 0;
}
}
// Initialize interpreter state
void init_state(InterpreterState* state) {
state->variable_count = 0;
state->running = 1;
}
// Execute a single line in the context of a state
void execute_line(InterpreterState* state, const char* line) {
printf("Executing line: %s\n", line); // Debugging
interpret_line(state, line);
}

View File

@ -1,139 +1,139 @@
; isr.asm - ISR assembly stubs
global isr0, isr1, isr2, isr3, isr4, isr5, isr6, isr7, isr8, isr9, isr10, isr11, isr12, isr13, isr14, isr15
global isr16, isr17, isr18, isr19, isr20, isr21, isr22, isr23, isr24, isr25, isr26, isr27, isr28, isr29, isr30, isr31
extern isr_common_handler
section .text
; ISRs 0 to 13 (no error code pushed by CPU)
isr0:
cli
push 0 ; Push error code (none for isr0)
push 0 ; Push interrupt number
jmp isr_common_handler
isr1:
cli
push 0
push 1
jmp isr_common_handler
isr2:
cli
push 0
push 2
jmp isr_common_handler
isr3:
cli
push 0
push 3
jmp isr_common_handler
isr4:
cli
push 0
push 4
jmp isr_common_handler
isr5:
cli
push 0
push 5
jmp isr_common_handler
isr6:
cli
push 0
push 6
jmp isr_common_handler
isr7:
cli
push 0
push 7
jmp isr_common_handler
isr8:
cli
push 0
push 8
jmp isr_common_handler
isr9:
cli
push 0
push 9
jmp isr_common_handler
isr10:
cli
push 0
push 10
jmp isr_common_handler
isr11:
cli
push 0
push 11
jmp isr_common_handler
isr12:
cli
push 0
push 12
jmp isr_common_handler
isr13:
cli
push 0
push 13
jmp isr_common_handler
; ISR 14 (Page Fault) requires error code pushed by CPU
isr14:
cli
push 14 ; Push interrupt number
jmp isr_common_handler
; ISRs 15 to 31 (no error code pushed by CPU)
isr15:
cli
push 0
push 15
jmp isr_common_handler
isr16:
cli
push 0
push 16
jmp isr_common_handler
isr17:
cli
push 0
push 17
jmp isr_common_handler
isr18:
cli
push 0
push 18
jmp isr_common_handler
isr19:
cli
push 0
push 19
jmp isr_common_handler
isr20:
cli
push 0
push 20
jmp isr_common_handler
; isr.asm - ISR assembly stubs
global isr0, isr1, isr2, isr3, isr4, isr5, isr6, isr7, isr8, isr9, isr10, isr11, isr12, isr13, isr14, isr15
global isr16, isr17, isr18, isr19, isr20, isr21, isr22, isr23, isr24, isr25, isr26, isr27, isr28, isr29, isr30, isr31
extern isr_common_handler
section .text
; ISRs 0 to 13 (no error code pushed by CPU)
isr0:
cli
push 0 ; Push error code (none for isr0)
push 0 ; Push interrupt number
jmp isr_common_handler
isr1:
cli
push 0
push 1
jmp isr_common_handler
isr2:
cli
push 0
push 2
jmp isr_common_handler
isr3:
cli
push 0
push 3
jmp isr_common_handler
isr4:
cli
push 0
push 4
jmp isr_common_handler
isr5:
cli
push 0
push 5
jmp isr_common_handler
isr6:
cli
push 0
push 6
jmp isr_common_handler
isr7:
cli
push 0
push 7
jmp isr_common_handler
isr8:
cli
push 0
push 8
jmp isr_common_handler
isr9:
cli
push 0
push 9
jmp isr_common_handler
isr10:
cli
push 0
push 10
jmp isr_common_handler
isr11:
cli
push 0
push 11
jmp isr_common_handler
isr12:
cli
push 0
push 12
jmp isr_common_handler
isr13:
cli
push 0
push 13
jmp isr_common_handler
; ISR 14 (Page Fault) requires error code pushed by CPU
isr14:
cli
push 14 ; Push interrupt number
jmp isr_common_handler
; ISRs 15 to 31 (no error code pushed by CPU)
isr15:
cli
push 0
push 15
jmp isr_common_handler
isr16:
cli
push 0
push 16
jmp isr_common_handler
isr17:
cli
push 0
push 17
jmp isr_common_handler
isr18:
cli
push 0
push 18
jmp isr_common_handler
isr19:
cli
push 0
push 19
jmp isr_common_handler
isr20:
cli
push 0
push 20
jmp isr_common_handler

View File

@ -1,43 +1,43 @@
// disk_io.c
#include "disk_io.h"
#include "print.h" // Assuming you have a function for kernel printing
#define SECTOR_SIZE 512
// Function to read sectors from disk
int disk_read(uint32_t lba, void *buffer, uint32_t size) {
// lba: logical block address
// buffer: where to store the read data
// size: number of bytes to read
if (size % SECTOR_SIZE != 0) {
printf("Read size must be a multiple of 512 bytes\n");
return -1;
}
for (uint32_t i = 0; i < size / SECTOR_SIZE; i++) {
// Placeholder for actual disk sector read. Replace with proper implementation
if (!bios_read_sector(lba + i, buffer + (i * SECTOR_SIZE))) {
printf("Error reading sector from disk\n");
return -1;
}
}
return 0;
}
// Placeholder function to simulate reading sectors from the disk
// Replace this with actual disk reading logic depending on the platform
int bios_read_sector(uint32_t lba, void *buffer) {
// Simulate disk sector read
// In an actual kernel, you'd use interrupts or other mechanisms to read from disk
// For now, just zero out the buffer to simulate
for (int i = 0; i < SECTOR_SIZE; i++) {
((uint8_t*)buffer)[i] = 0; // Fill buffer with zeros
}
return 1; // Success
}
// disk_io.c
#include "disk_io.h"
#include "print.h" // Assuming you have a function for kernel printing
#define SECTOR_SIZE 512
// Function to read sectors from disk
int disk_read(uint32_t lba, void *buffer, uint32_t size) {
// lba: logical block address
// buffer: where to store the read data
// size: number of bytes to read
if (size % SECTOR_SIZE != 0) {
printf("Read size must be a multiple of 512 bytes\n");
return -1;
}
for (uint32_t i = 0; i < size / SECTOR_SIZE; i++) {
// Placeholder for actual disk sector read. Replace with proper implementation
if (!bios_read_sector(lba + i, buffer + (i * SECTOR_SIZE))) {
printf("Error reading sector from disk\n");
return -1;
}
}
return 0;
}
// Placeholder function to simulate reading sectors from the disk
// Replace this with actual disk reading logic depending on the platform
int bios_read_sector(uint32_t lba, void *buffer) {
// Simulate disk sector read
// In an actual kernel, you'd use interrupts or other mechanisms to read from disk
// For now, just zero out the buffer to simulate
for (int i = 0; i < SECTOR_SIZE; i++) {
((uint8_t*)buffer)[i] = 0; // Fill buffer with zeros
}
return 1; // Success
}

View File

@ -334,6 +334,48 @@ int my_sscanf(const char *input, const char *format, char *output) {
return match_count;
}
snprintf(char* buffer, size_t size, const char* format, ...) {
va_list args;
va_start(args, format);
const char* traverse = format;
size_t written = 0;
while (*traverse && written < size - 1) {
if (*traverse == '%' && *(traverse + 1)) {
traverse++;
if (*traverse == 's') {
const char* str = va_arg(args, const char*);
while (*str && written < size - 1) {
buffer[written++] = *str++;
}
} else if (*traverse == 'd') {
int num = va_arg(args, int);
char num_buffer[16];
int num_len = 0;
if (num < 0) {
if (written < size - 1) buffer[written++] = '-';
num = -num;
}
do {
num_buffer[num_len++] = '0' + (num % 10);
num /= 10;
} while (num > 0);
while (num_len > 0 && written < size - 1) {
buffer[written++] = num_buffer[--num_len];
}
}
} else {
buffer[written++] = *traverse;
}
traverse++;
}
buffer[written] = '\0';
va_end(args);
return written;
}
void printf(const char* format, ...) {
va_list args;

View File

@ -1,80 +1,80 @@
#include "vector.h"
// Initial capacity for a new vector
#define VECTOR_INITIAL_CAPACITY 4
// Create a new vector
vector* vector_create() {
vector* v = (vector*)malloc(sizeof(vector));
if (!v) return NULL; // Return NULL if allocation fails
v->capacity = VECTOR_INITIAL_CAPACITY;
v->size = 0;
v->items = (void**)malloc(sizeof(void*) * v->capacity);
if (!v->items) {
free(v); // Free the vector if item allocation fails
return NULL;
}
return v;
}
// Destroy the vector and free allocated memory
void vector_destroy(vector* v) {
if (v) {
free(v->items);
free(v);
}
}
// Push an item to the back of the vector
int vector_push_back(vector* v, void* item) {
// Resize the vector if it's full
if (v->size == v->capacity) {
if (vector_resize(v, v->capacity * 2) != 0) {
return -1; // Return -1 on failure to resize
}
}
v->items[v->size++] = item; // Add the new item
return 0; // Success
}
// Get the item at a specific index
void* vector_get(vector* v, size_t index) {
if (index >= v->size) return NULL; // Return NULL if index is out of bounds
return v->items[index];
}
// Set an item at a specific index
int vector_set(vector* v, size_t index, void* item) {
if (index >= v->size) return -1; // Return -1 if index is out of bounds
v->items[index] = item;
return 0; // Success
}
// Get the size of the vector
size_t vector_size(vector* v) {
return v->size;
}
// Resize the vector's internal array
int vector_resize(vector* v, size_t new_capacity) {
// Allocate new memory for the resized array
void** new_items = (void**)malloc(sizeof(void*) * new_capacity);
if (!new_items) return -1; // Return -1 on failure
// Copy the old items into the new array
for (size_t i = 0; i < v->size; i++) {
new_items[i] = v->items[i];
}
// Free the old memory
free(v->items);
// Update the vector's internal state
v->items = new_items;
v->capacity = new_capacity;
return 0; // Success
}
#include "vector.h"
// Initial capacity for a new vector
#define VECTOR_INITIAL_CAPACITY 4
// Create a new vector
vector* vector_create() {
vector* v = (vector*)malloc(sizeof(vector));
if (!v) return NULL; // Return NULL if allocation fails
v->capacity = VECTOR_INITIAL_CAPACITY;
v->size = 0;
v->items = (void**)malloc(sizeof(void*) * v->capacity);
if (!v->items) {
free(v); // Free the vector if item allocation fails
return NULL;
}
return v;
}
// Destroy the vector and free allocated memory
void vector_destroy(vector* v) {
if (v) {
free(v->items);
free(v);
}
}
// Push an item to the back of the vector
int vector_push_back(vector* v, void* item) {
// Resize the vector if it's full
if (v->size == v->capacity) {
if (vector_resize(v, v->capacity * 2) != 0) {
return -1; // Return -1 on failure to resize
}
}
v->items[v->size++] = item; // Add the new item
return 0; // Success
}
// Get the item at a specific index
void* vector_get(vector* v, size_t index) {
if (index >= v->size) return NULL; // Return NULL if index is out of bounds
return v->items[index];
}
// Set an item at a specific index
int vector_set(vector* v, size_t index, void* item) {
if (index >= v->size) return -1; // Return -1 if index is out of bounds
v->items[index] = item;
return 0; // Success
}
// Get the size of the vector
size_t vector_size(vector* v) {
return v->size;
}
// Resize the vector's internal array
int vector_resize(vector* v, size_t new_capacity) {
// Allocate new memory for the resized array
void** new_items = (void**)malloc(sizeof(void*) * new_capacity);
if (!new_items) return -1; // Return -1 on failure
// Copy the old items into the new array
for (size_t i = 0; i < v->size; i++) {
new_items[i] = v->items[i];
}
// Free the old memory
free(v->items);
// Update the vector's internal state
v->items = new_items;
v->capacity = new_capacity;
return 0; // Success
}

View File

@ -1,185 +1,185 @@
#include "game.h"
#include "print.h"
#include "keydriver.h"
#include "strings.h"
#include "stdint.h"
// Define constants for the game
#define ROOM_COUNT 5
#define INVENTORY_SIZE 5
// Global variable to hold the game state
static GameState game_state;
// Room descriptions and connected rooms
typedef struct {
const char* description;
int north;
int south;
int east;
int west;
} Room;
static const Room rooms[ROOM_COUNT] = {
{ "You are in a dark forest. There are paths to the north and east.", 1, -1, 2, -1 },
{ "You are on a beach. There is a cave to the west.", -1, 0, -1, 3 },
{ "You are inside a cave. Its damp and dark.", -1, -1, -1, 0 },
{ "You are in a small village. There's a shop to the north and a forest to the east.", 4, -1, -1, -1 },
{ "You are in a shop filled with various items. The village is to the south.", -1, 3, -1, -1 }
};
// Player's inventory
static const char* inventory[INVENTORY_SIZE];
static int inventory_count = 0;
// Command buffer
static char commandBuffer[MAX_COMMAND_LENGTH];
static size_t commandLength = 0;
bool keydown = false;
// Function to handle user input commands
void handle_command(const char* command) {
game_clear();
if (strcmp(command, "look") == 0) {
printf(rooms[game_state.current_room].description);
printf("\n");
} else if (strcmp(command, "north") == 0) {
if (rooms[game_state.current_room].north != -1) {
game_state.current_room = rooms[game_state.current_room].north;
printf("You walk north.\n");
printf("%s\n", rooms[game_state.current_room].description);
} else {
printf("You can't go that way.\n");
}
} else if (strcmp(command, "south") == 0) {
if (rooms[game_state.current_room].south != -1) {
game_state.current_room = rooms[game_state.current_room].south;
printf("You walk south.\n");
printf("%s\n", rooms[game_state.current_room].description);
} else {
printf("You can't go that way.\n");
}
} else if (strcmp(command, "east") == 0) {
if (rooms[game_state.current_room].east != -1) {
game_state.current_room = rooms[game_state.current_room].east;
printf("You walk east.\n");
printf("%s\n", rooms[game_state.current_room].description);
} else {
printf("You can't go that way.\n");
}
} else if (strcmp(command, "west") == 0) {
if (rooms[game_state.current_room].west != -1) {
game_state.current_room = rooms[game_state.current_room].west;
printf("You walk west.\n");
printf("%s\n", rooms[game_state.current_room].description);
} else {
printf("You can't go that way.\n");
}
} else if (strcmp(command, "inventory") == 0) {
printf("You are carrying:\n");
for (int i = 0; i < inventory_count; ++i) {
printf("- %s\n", inventory[i]);
}
if (inventory_count == 0) {
printf("Nothing.\n");
}
} else if (strcmp(command, "take key") == 0) {
if (game_state.current_room == 1) {
if (inventory_count < INVENTORY_SIZE) {
inventory[inventory_count++] = "key";
printf("You picked up a key.\n");
} else {
printf("Your inventory is full.\n");
}
} else {
printf("There is no key here.\n");
}
} else if (strcmp(command, "use key") == 0) {
bool has_key = false;
for (int i = 0; i < inventory_count; ++i) {
if (strcmp(inventory[i], "key") == 0) {
has_key = true;
break;
}
}
if (has_key && game_state.current_room == 2) {
printf("You unlock the door in the cave and find a treasure!\n");
game_state.game_active = false; // End the game
} else {
printf("You can't use the key here.\n");
}
} else if (strcmp(command, "quit") == 0) {
printf("You quit the game.\n");
game_state.game_active = false;
} else {
printf("Unknown command.\n");
}
}
// Function to print the prompt for the player
void print_prompt() {
printf(" > ");
}
const void game_clear()
{
print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLACK); // Set text color
move_print_cursor(0, 0);
move_cursor(0, 0);
print_clear();
}
// Function to initialize and run the game
void create_game() {
// Initialize the game state
game_state.current_room = 0;
game_state.game_active = true;
printf("Welcome to the text adventure game!\n");
printf("Type 'look' to see where you are, 'north', 'south', 'east', 'west' to move, or 'quit' to exit.\n");
printf("You can 'take key' or 'use key' in the appropriate places.\n");
print_prompt();
// Main game loop
while (game_state.game_active) {
char key = read_key(); // Get key input
if (key != 0) {
if (!keydown) {
if (key == 10) { // Enter key
printf("\n");
commandBuffer[commandLength] = '\0'; // Null-terminate the command
handle_command(commandBuffer); // Process the command
commandLength = 0; // Reset command buffer
if (game_state.game_active) {
print_prompt(); // Print prompt for the next command
}
} else if (key == 8) { // Backspace key
if (commandLength > 0) {
commandLength--;
offset_print_cursor(-1, 0);
print_char(' '); // Overwrite the character
offset_print_cursor(-1, 0);
}
} else if (key >= 32 && key <= 126) { // Printable characters
if (commandLength < MAX_COMMAND_LENGTH - 1) {
commandBuffer[commandLength++] = key;
print_char(key); // Display the key on the screen
}
}
keydown = true;
}
} else {
keydown = false;
}
}
printf("Thanks for playing!\n");
}
#include "game.h"
#include "print.h"
#include "keydriver.h"
#include "strings.h"
#include "stdint.h"
// Define constants for the game
#define ROOM_COUNT 5
#define INVENTORY_SIZE 5
// Global variable to hold the game state
static GameState game_state;
// Room descriptions and connected rooms
typedef struct {
const char* description;
int north;
int south;
int east;
int west;
} Room;
static const Room rooms[ROOM_COUNT] = {
{ "You are in a dark forest. There are paths to the north and east.", 1, -1, 2, -1 },
{ "You are on a beach. There is a cave to the west.", -1, 0, -1, 3 },
{ "You are inside a cave. Its damp and dark.", -1, -1, -1, 0 },
{ "You are in a small village. There's a shop to the north and a forest to the east.", 4, -1, -1, -1 },
{ "You are in a shop filled with various items. The village is to the south.", -1, 3, -1, -1 }
};
// Player's inventory
static const char* inventory[INVENTORY_SIZE];
static int inventory_count = 0;
// Command buffer
static char commandBuffer[MAX_COMMAND_LENGTH];
static size_t commandLength = 0;
bool keydown = false;
// Function to handle user input commands
void handle_command(const char* command) {
game_clear();
if (strcmp(command, "look") == 0) {
printf(rooms[game_state.current_room].description);
printf("\n");
} else if (strcmp(command, "north") == 0) {
if (rooms[game_state.current_room].north != -1) {
game_state.current_room = rooms[game_state.current_room].north;
printf("You walk north.\n");
printf("%s\n", rooms[game_state.current_room].description);
} else {
printf("You can't go that way.\n");
}
} else if (strcmp(command, "south") == 0) {
if (rooms[game_state.current_room].south != -1) {
game_state.current_room = rooms[game_state.current_room].south;
printf("You walk south.\n");
printf("%s\n", rooms[game_state.current_room].description);
} else {
printf("You can't go that way.\n");
}
} else if (strcmp(command, "east") == 0) {
if (rooms[game_state.current_room].east != -1) {
game_state.current_room = rooms[game_state.current_room].east;
printf("You walk east.\n");
printf("%s\n", rooms[game_state.current_room].description);
} else {
printf("You can't go that way.\n");
}
} else if (strcmp(command, "west") == 0) {
if (rooms[game_state.current_room].west != -1) {
game_state.current_room = rooms[game_state.current_room].west;
printf("You walk west.\n");
printf("%s\n", rooms[game_state.current_room].description);
} else {
printf("You can't go that way.\n");
}
} else if (strcmp(command, "inventory") == 0) {
printf("You are carrying:\n");
for (int i = 0; i < inventory_count; ++i) {
printf("- %s\n", inventory[i]);
}
if (inventory_count == 0) {
printf("Nothing.\n");
}
} else if (strcmp(command, "take key") == 0) {
if (game_state.current_room == 1) {
if (inventory_count < INVENTORY_SIZE) {
inventory[inventory_count++] = "key";
printf("You picked up a key.\n");
} else {
printf("Your inventory is full.\n");
}
} else {
printf("There is no key here.\n");
}
} else if (strcmp(command, "use key") == 0) {
bool has_key = false;
for (int i = 0; i < inventory_count; ++i) {
if (strcmp(inventory[i], "key") == 0) {
has_key = true;
break;
}
}
if (has_key && game_state.current_room == 2) {
printf("You unlock the door in the cave and find a treasure!\n");
game_state.game_active = false; // End the game
} else {
printf("You can't use the key here.\n");
}
} else if (strcmp(command, "quit") == 0) {
printf("You quit the game.\n");
game_state.game_active = false;
} else {
printf("Unknown command.\n");
}
}
// Function to print the prompt for the player
void print_prompt() {
printf(" > ");
}
const void game_clear()
{
print_set_color(PRINT_COLOR_WHITE, PRINT_COLOR_BLACK); // Set text color
move_print_cursor(0, 0);
move_cursor(0, 0);
print_clear();
}
// Function to initialize and run the game
void create_game() {
// Initialize the game state
game_state.current_room = 0;
game_state.game_active = true;
printf("Welcome to the text adventure game!\n");
printf("Type 'look' to see where you are, 'north', 'south', 'east', 'west' to move, or 'quit' to exit.\n");
printf("You can 'take key' or 'use key' in the appropriate places.\n");
print_prompt();
// Main game loop
while (game_state.game_active) {
char key = read_key(); // Get key input
if (key != 0) {
if (!keydown) {
if (key == 10) { // Enter key
printf("\n");
commandBuffer[commandLength] = '\0'; // Null-terminate the command
handle_command(commandBuffer); // Process the command
commandLength = 0; // Reset command buffer
if (game_state.game_active) {
print_prompt(); // Print prompt for the next command
}
} else if (key == 8) { // Backspace key
if (commandLength > 0) {
commandLength--;
offset_print_cursor(-1, 0);
print_char(' '); // Overwrite the character
offset_print_cursor(-1, 0);
}
} else if (key >= 32 && key <= 126) { // Printable characters
if (commandLength < MAX_COMMAND_LENGTH - 1) {
commandBuffer[commandLength++] = key;
print_char(key); // Display the key on the screen
}
}
keydown = true;
}
} else {
keydown = false;
}
}
printf("Thanks for playing!\n");
}

View File

@ -89,4 +89,14 @@ int strncmp(const char *s1, const char *s2, size_t n) {
} else {
return (*(unsigned char *)s1 - *(unsigned char *)s2);
}
}
}
char* strchr(const char* str, int ch) {
while (*str) {
if (*str == (char)ch) {
return (char*)str;
}
str++;
}
return NULL;
}

32
src/intf/basic.h Normal file
View File

@ -0,0 +1,32 @@
#ifndef BASIC_INTERPRETER_H
#define BASIC_INTERPRETER_H
#include "stdint.h"
#include "stddef.h"
#define MAX_LINE_LENGTH 128
#define MAX_VARIABLES 32
typedef struct {
char name[16];
int value;
char* str_value;
} Variable;
typedef struct {
Variable variables[MAX_VARIABLES];
size_t variable_count;
int running;
} InterpreterState;
// Initialize the interpreter state
void init_state(InterpreterState* state);
// Execute a single line of code in the context of a state
void execute_line(InterpreterState* state, const char* line);
// Utility to evaluate an expression (exposed for potential reuse)
const char* evaluate_expression(InterpreterState* state, const char* expr);
#endif // BASIC_INTERPRETER_H

View File

@ -1,17 +1,17 @@
// disk_io.h
#ifndef DISK_IO_H
#define DISK_IO_H
#include <stdint.h>
// Read sectors from the disk
int disk_read(uint32_t lba, void *buffer, uint32_t size);
// Optional: Write sectors to the disk (not implemented)
int disk_write(uint32_t lba, const void *buffer, uint32_t size);
int bios_read_sector(uint32_t lba, void *buffer);
// disk_io.h
#ifndef DISK_IO_H
#define DISK_IO_H
#include <stdint.h>
// Read sectors from the disk
int disk_read(uint32_t lba, void *buffer, uint32_t size);
// Optional: Write sectors to the disk (not implemented)
int disk_write(uint32_t lba, const void *buffer, uint32_t size);
int bios_read_sector(uint32_t lba, void *buffer);
#endif // DISK_IO_H

View File

@ -1,25 +1,25 @@
#ifndef GAME_H
#define GAME_H
#include "stdint.h"
// Define the maximum length of a command
#define MAX_COMMAND_LENGTH 128
// Game state structure
typedef struct {
int current_room;
bool game_active;
} GameState;
// Function to initialize and run the game
void create_game();
// Function to handle the command input by the player
void handle_command(const char* command);
// Function to print the current prompt
void print_prompt();
#endif
#ifndef GAME_H
#define GAME_H
#include "stdint.h"
// Define the maximum length of a command
#define MAX_COMMAND_LENGTH 128
// Game state structure
typedef struct {
int current_room;
bool game_active;
} GameState;
// Function to initialize and run the game
void create_game();
// Function to handle the command input by the player
void handle_command(const char* command);
// Function to print the current prompt
void print_prompt();
#endif

View File

@ -29,6 +29,7 @@ enum {
};
void sscanf(const char *str, const char *format, char *filename, char *content);
snprintf(char* buffer, size_t size, const char* format, ...);
int my_sscanf(const char *input, const char *format, char *output);
void print_clear();
void print_char(char character);

View File

@ -5,8 +5,9 @@
int strcmp(const char *str1, const char *str2);
size_t strlen(const char *str);
char *strncpy(char *dest, const char *src, size_t n);
int int_strncmp(const char* s1, const char* s2, size_t n);
int int_strncmp(const char *s1, const char *s2, size_t n);
void strcpy(char *dest, const char *src);
char* strrchr(const char* str, char ch);
char *strrchr(const char *str, char ch);
int strncmp(const char *s1, const char *s2, size_t n);
int strncmp(const char *s1, const char *s2, size_t n);
char *strchr(const char *str, int ch);

View File

@ -1,22 +1,22 @@
#ifndef VECTOR_H
#define VECTOR_H
#include <stddef.h>
// Define the vector structure
typedef struct {
void** items; // Pointer to the array of items
size_t capacity; // Maximum number of items the vector can hold
size_t size; // Current number of items in the vector
} vector;
// Function prototypes
vector* vector_create();
void vector_destroy(vector* v);
int vector_push_back(vector* v, void* item);
void* vector_get(vector* v, size_t index);
int vector_set(vector* v, size_t index, void* item);
size_t vector_size(vector* v);
int vector_resize(vector* v, size_t new_capacity);
#endif
#ifndef VECTOR_H
#define VECTOR_H
#include <stddef.h>
// Define the vector structure
typedef struct {
void** items; // Pointer to the array of items
size_t capacity; // Maximum number of items the vector can hold
size_t size; // Current number of items in the vector
} vector;
// Function prototypes
vector* vector_create();
void vector_destroy(vector* v);
int vector_push_back(vector* v, void* item);
void* vector_get(vector* v, size_t index);
int vector_set(vector* v, size_t index, void* item);
size_t vector_size(vector* v);
int vector_resize(vector* v, size_t new_capacity);
#endif

Binary file not shown.