Compare commits

...

17 commits

Author SHA1 Message Date
00995188aa
(broken) mouse redrawing works for top window 2026-05-08 01:04:08 +02:00
11eb3e7468
merge mouse 2026-05-08 00:40:05 +02:00
5506c4eda3
smaller coloring changes 2026-05-08 00:30:20 +02:00
orangerot
0112bce1a3 feat(console): render mouse + click on text to execute command 2025-11-20 11:11:04 +01:00
orangerot
0829e56fb5 feat: ps2 mouse driver + event listener 2025-11-20 11:10:21 +01:00
aeeb4907f6 Made LAPIC recalibration more aggressive 2025-11-13 01:17:01 +01:00
74171d4252 (Hopefully) improved initial TSC calibration 2025-11-13 01:12:42 +01:00
735be7f3cd Added a 'help' command 2025-11-13 01:01:16 +01:00
ebca767837 Centered snake, city on the screen 2025-11-13 00:53:16 +01:00
c73a2101de Clear the screen before a task plays 2025-11-13 00:47:23 +01:00
9ccebc0d93 Stopping the console when a task is in foreground 2025-11-13 00:43:28 +01:00
5d11d37470 snake can now be quit via the escape key 2025-11-13 00:35:30 +01:00
fd1270fa60 Unregistering key event listeners. 2025-11-13 00:31:00 +01:00
bc66ebc884 Use arrow keys + esc for snake; fixed keycode 0 2025-11-13 00:21:10 +01:00
847f46d3bf City demo now uses arrow keys 2025-11-12 21:44:52 +01:00
420e7bf459 Ported a cityscape 3D rendering demo 2025-11-12 21:31:18 +01:00
59bc9b5e3f Timer Queue: Fix timers dropping from the queue 2025-11-12 21:13:55 +01:00
19 changed files with 19789 additions and 174 deletions

View file

@ -32,6 +32,7 @@ KERNEL_SOURCES := \
src/kernmsg.c \
src/framebuffer.c \
src/kernel.c \
src/mouse.c \
src/pci.c \
src/ram.c \
src/tar.c \
@ -88,7 +89,7 @@ build/tests/test_tex: tests/test_tex.c $(TEST_TEX_DEPS) build/tests
build/tests:
mkdir -p $@
build/src/%.o: src/%.[cS] | build/src
build/src/%.o: src/%.[cS] | build/src build/src/small3dlib
@printf "CC %s\n" $@
@"$(CC)" $(CFLAGS) -MMD -MP -c -o $@ $< $(CPPFLAGS)
@ -111,6 +112,9 @@ build:
build/src:
mkdir -p $@
build/src/small3dlib:
mkdir -p $@
build/boot:
mkdir -p $@

View file

@ -21,8 +21,9 @@ struct Component {
struct Stack { struct Component *first_child; bool horizontal; } stack;
} data;
// this is filled automatically; DO NOT FILL THIS MANUALLY!
// this is filled automatically (unless you use the `_manual` functions)
struct Component *next;
// this is always filled automatically
struct rect rect;
};

View file

@ -5,7 +5,8 @@
#include <stdint.h>
// Keycodes are defined in a row:3 col:5 bit-pattern.
#define KC(row, col) (((row) << 5) | (col))
// col starts at 1 instead of 0 so that no valid keycode has the value 0.
#define KC(row, col) (((row) << 5) | ((col)+1))
#define KC_ROW(c) ((c) >> 5)
#define KC_COL(c) ((c) & 0x1f)

18
include/mouse.h Normal file
View file

@ -0,0 +1,18 @@
#ifndef KARLOS_MOUSED_H
#define KARLOS_MOUSED_H
#include <stdbool.h>
#include <stdint.h>
#define MOUSE_BUTTON_MIDDLE (1 << 2)
#define MOUSE_BUTTON_RIGHT (1 << 1)
#define MOUSE_BUTTON_LEFT (1 << 0)
void on_mouse_event(int8_t mouse_x, int8_t mouse_y, uint8_t buttons);
typedef void (*mouse_event_listener)(int8_t mouse_x, int8_t mouse_y, uint8_t buttons);
void register_mouse_event_listener(mouse_event_listener ls);
void unregister_mouse_event_listener(mouse_event_listener ls);
#endif // KARLOS_MOUSED_H

View file

@ -1 +1 @@
void snake_start(void);
void snake_main(void);

View file

@ -2,6 +2,7 @@
#include "address.h"
#include "framebuffer.h"
#include "keyboard.h"
#include "mouse.h"
#include "ram.h"
#include "rect.h"
#include "std.h"
@ -116,6 +117,7 @@ atomic_bool app_initialized;
font_handle app_font;
struct tex app_background;
int mouse_x = 0, mouse_y = 0;
void app_init_global(void) {
// allocate and color background
@ -150,6 +152,8 @@ void app_init_global(void) {
// listeners
void app_key_event_listener(struct key_event event);
register_key_event_listener(app_key_event_listener);
void app_mouse_event_listener(int8_t mouse_x, int8_t mouse_y, uint8_t buttons);
register_mouse_event_listener(app_mouse_event_listener);
// base app
@ -259,8 +263,8 @@ void app_component_redraw(void *app, struct Component *cpnt) {
app_draw_text(app, cpnt->data.button.text, cpnt->rect.x + 3, cpnt->rect.y + 3, COLOR_LUMA(0), COLOR_LUMA(150));
break;
case CPNT_TYPE_LABEL:
component_draw_border(app, cpnt, COLOR_LUMA(255));
app_draw_text(app, cpnt->data.label.text, cpnt->rect.x + 3, cpnt->rect.y + 3, COLOR_LUMA(0), COLOR_LUMA(255));
component_draw_border(app, cpnt, COLOR_LUMA(200));
app_draw_text(app, cpnt->data.label.text, cpnt->rect.x + 3, cpnt->rect.y + 3, COLOR_LUMA(0), COLOR_LUMA(200));
break;
case CPNT_TYPE_CANVAS:
component_draw_border(app, cpnt, COLOR_LUMA(255));
@ -328,6 +332,19 @@ static void app_redraw_below(struct rect uncovered, struct app_instance *ins) {
fb_damage(uncovered);
}
static void app_redraw_single(struct rect uncovered, struct app_instance *ins) {
struct tex fb_tex = fb_as_tex();
tex_blit(&fb_tex, &app_background, &uncovered, &uncovered);
struct app_instance *cursor = ins;
struct rect local_src = uncovered;
struct rect local_dst = uncovered;
rect_clamp(&local_src, &cursor->pos);
rect_clamp(&local_dst, &cursor->pos);
rect_translate(&local_src, -cursor->pos.x, -cursor->pos.y);
tex_blit(&fb_tex, &cursor->framebuf, &local_src, &local_dst);
fb_damage(uncovered);
}
static void app_redraw_above(struct rect uncovered, struct app_instance *ins) {
ASSERT(ins != NULL);
struct tex fb_tex = fb_as_tex();
@ -627,6 +644,38 @@ void app_key_event_listener(struct key_event event) {
}
}
#define INVERT_MOUSE_Y
void app_mouse_event_listener(int8_t mouse_dx, int8_t mouse_dy, uint8_t buttons) {
struct rect old_rect = RECT_XYWH(mouse_x, mouse_y, 5, 5);
app_redraw_below(old_rect, app_root);
app_redraw_single(old_rect, app_root);
mouse_x += mouse_dx;
if (mouse_x < 0) mouse_x = 0;
if (mouse_x >= fb_width()) mouse_x = fb_width() - 1;
#ifndef INVERT_MOUSE_Y
mouse_y += mouse_dy;
#else
mouse_y -= mouse_dy;
#endif
if (mouse_y < 0) mouse_y = 0;
if (mouse_y >= fb_height()) mouse_y = fb_height() - 1;
struct tex fb_tex = fb_as_tex();
struct rect r = RECT_XYWH(mouse_x, mouse_y, 5, 5);
tex_fill_region(&fb_tex, COLOR_LUMA(20), &r);
fb_damage(r);
// button click
if (buttons & MOUSE_BUTTON_LEFT) {
// search for element that was hit
TODO();
// re-focus to hit element
TODO();
// if it was button, click directly
TODO();
}
}
extern struct app_template app_calculator_template;
extern struct app_template app_squares_template;
extern struct app_template app_kernmsg_template;

View file

@ -71,8 +71,8 @@ end:
void app_calculator_on_selector(void *self, struct Component *btn) {
struct app_calculator *app = self;
char *rt = app->reg_label->data.label.text;
char *at = app->acc_label->data.label.text;
char *rt = app->reg_label->data.label.text + 1;
char *at = app->acc_label->data.label.text + 1;
if (btn == app->reg_btn_left) {
if (*rt > '0') {
(*rt)--;
@ -98,7 +98,7 @@ void app_calculator_on_selector(void *self, struct Component *btn) {
void app_calculator_on_load_result(void *self, struct Component *btn) {
struct app_calculator *app = self;
char to = app->acc_label->data.label.text[0];
char to = app->acc_label->data.label.text[1];
if (to == 'A') {
memcpy(app->a->data.text_input.text, app->out->data.label.text, 64);
app_component_redraw(app, app->a);
@ -110,8 +110,8 @@ void app_calculator_on_load_result(void *self, struct Component *btn) {
void app_calculator_on_load_reg(void *self, struct Component *btn) {
struct app_calculator *app = self;
int reg_idx = app->reg_label->data.label.text[0] - '0';
char to = app->acc_label->data.label.text[0];
int reg_idx = app->reg_label->data.label.text[1] - '0';
char to = app->acc_label->data.label.text[1];
if (to == 'A') {
memcpy(app->a->data.text_input.text, app->registers[reg_idx]->data.label.text, 64);
app_component_redraw(app, app->a);
@ -123,7 +123,7 @@ void app_calculator_on_load_reg(void *self, struct Component *btn) {
void app_calculator_on_save_reg(void *self, struct Component *btn) {
struct app_calculator *app = self;
int reg_idx = app->reg_label->data.label.text[0] - '0';
int reg_idx = app->reg_label->data.label.text[1] - '0';
memcpy(app->registers[reg_idx]->data.label.text, app->out->data.label.text, 64);
app_component_redraw(app, app->registers[reg_idx]);
}
@ -153,10 +153,10 @@ static struct Component *selector(const char *name, const char *default_text, un
label->data.label.width_in_chars = label_width;
struct Component *field = app_component_new_label(default_text);
field->data.label.width_in_chars = field_width;
struct Component *left = app_component_new_button("<", app_calculator_on_selector);
left->data.button.width_in_chars = 1;
struct Component *right = app_component_new_button(">", app_calculator_on_selector);
right->data.button.width_in_chars = 1;
struct Component *left = app_component_new_button(" < ", app_calculator_on_selector);
left->data.button.width_in_chars = 3;
struct Component *right = app_component_new_button(" > ", app_calculator_on_selector);
right->data.button.width_in_chars = 3;
struct Component *stack = app_component_new_stack(true, 4, label, left, field, right);
*save_left = left;
*save_label = field;
@ -168,32 +168,35 @@ struct AppCreation app_calculator_create() {
struct Component *a = labeled_text_input("A", "", 1, 20, &app_calculator_instance.a);
struct Component *b = labeled_text_input("B", "", 1, 20, &app_calculator_instance.b);
struct Component *btn_add = app_component_new_button("+", app_calculator_on_op);
btn_add->data.button.width_in_chars = 1;
struct Component *btn_sub = app_component_new_button("-", app_calculator_on_op);
btn_sub->data.button.width_in_chars = 1;
struct Component *btn_mul = app_component_new_button("*", app_calculator_on_op);
btn_mul->data.button.width_in_chars = 1;
struct Component *btn_div = app_component_new_button("/", app_calculator_on_op);
btn_div->data.button.width_in_chars = 1;
struct Component *btn_add = app_component_new_button(" + ", app_calculator_on_op);
btn_add->data.button.width_in_chars = 3;
struct Component *btn_sub = app_component_new_button(" - ", app_calculator_on_op);
btn_sub->data.button.width_in_chars = 3;
struct Component *btn_mul = app_component_new_button(" * ", app_calculator_on_op);
btn_mul->data.button.width_in_chars = 3;
struct Component *btn_div = app_component_new_button(" / ", app_calculator_on_op);
btn_div->data.button.width_in_chars = 3;
struct Component *stack_btn = app_component_new_stack(true, 4, btn_add, btn_sub, btn_mul, btn_div);
struct Component *sel_acc = selector("acc", "A", 3, 1,
struct Component *sel_acc = selector("acc", " A ", 3, 3,
&app_calculator_instance.acc_btn_left,
&app_calculator_instance.acc_label,
&app_calculator_instance.acc_btn_right
);
struct Component *sel_reg = selector("reg", "0", 3, 1,
struct Component *sel_reg = selector("reg", " 0 ", 3, 3,
&app_calculator_instance.reg_btn_left,
&app_calculator_instance.reg_label,
&app_calculator_instance.reg_btn_right
);
struct Component *btn_load_result = app_component_new_button("load result", app_calculator_on_load_result);
btn_load_result->data.button.width_in_chars = 21;
struct Component *btn_load_reg = app_component_new_button("load from register", app_calculator_on_load_reg);
btn_load_reg->data.button.width_in_chars = 21;
struct Component *btn_save_reg = app_component_new_button("save to register", app_calculator_on_save_reg);
btn_save_reg->data.button.width_in_chars = 21;
struct Component *out = app_component_new_label("");
struct Component *out = labeled_label("O", "", 1, 20, &app_calculator_instance.out);
struct Component *main_stack = app_component_new_stack(false, 9, a, b, stack_btn, sel_acc, sel_reg, btn_load_result, btn_load_reg, btn_save_reg, out);
struct Component *regs[8];
@ -212,7 +215,6 @@ struct AppCreation app_calculator_create() {
app_calculator_instance.btn_sub = btn_sub;
app_calculator_instance.btn_mul = btn_mul;
app_calculator_instance.btn_div = btn_div;
app_calculator_instance.out = out;
struct Component *stack = app_component_new_stack(true, 2, main_stack, reg_stack);
return (struct AppCreation) {
.ptr = &app_calculator_instance,

View file

@ -1,116 +0,0 @@
#include "console.h"
#include "ram.h"
#include "unicode.h"
#include "std.h"
#include "interpreter.h"
#include "time.h"
#include "snake.h"
#include "app.h"
static Timer interpreter_timers[10];
static int interpreter_num_timers;
static bool is_decimal(char c) {
return c >= '0' && c <= '9';
}
static void interpreter_timer_callback(Timer *timer) {
int timer_idx = timer - interpreter_timers;
printf("Timer %d fired.\n", timer_idx);
}
void interpret_handle_input_line(const uint8_t *s) {
printf(">>> %s\n", s);
if (memcmp(s, "echo", 4) == 0) {
s += 4;
while (*s == ' ') {
s++;
}
if (*s != '"') {
printf("expected `echo` to be followed by enquoted string\n");
return;
}
s++;
// TODO escaped double quote
while (1) {
unicode_char c = utf8_next_asserted(&s);
if (c == 0) {
printf("unclosed delimiter\n");
return;
} else if (c == '"') {
break;
} else if (c == '\\') {
c = utf8_next_asserted(&s);
if (c != 'U') {
printf("unknown escape character\n");
return;
}
// TODO error handling
uint32_t codepoint = 0;
for (int i = 0; i < 4; i++) {
codepoint = (codepoint << 4) | hexchar_to_num(utf8_next_asserted(&s));
}
printf("%c", codepoint);
} else {
printf("%c", c);
}
}
putln();
} else if (memcmp(s, "clear", 5) == 0) {
early_clear(COLOR_RGB(0, 0, 0));
} else if (memcmp(s, "timer", 5) == 0) {
s += 5;
while (*s == ' ') {
s++;
}
if (!is_decimal(*s)) {
printf("expected `timer` to be followed by a number\n");
return;
}
int seconds = 0;
while (is_decimal(*s)) {
seconds *= 10;
seconds += *s - '0';
s++;
}
Time time = time_current();
time.sec += seconds;
if (interpreter_num_timers >= 10) {
printf("too many timers have been set.\n");
return;
}
int timer_idx = interpreter_num_timers++;
timer_set_absolute(&interpreter_timers[timer_idx], time, interpreter_timer_callback);
} else if (memcmp(s, "boottime", 8) == 0) {
s += 8;
Time now = time_current();
printf("%lu seconds, %lu nanoseconds\n", now.sec, now.nsec);
} else if (memcmp(s, "snake", 5) == 0) {
extern struct app_template snake_template;
if (!app_push(&snake_template, NULL, &RECT_XYWH(10, 10, 500, 500))) {
printf("could not launch\n");
}
} else if (memcmp(s, "tron", 4) == 0) {
s += 4;
while (*s == ' ') s++;
uint64_t num_players;
if (!parse_u64((const char**)&s, &num_players)) {
printf("could not parse number of players\n");
} else {
extern struct app_template tron_template;
if (!app_push(&tron_template, (void*)num_players, &RECT_XYWH(100, 100, 400, 400))) {
printf("could not launch\n");
}
}
} else if (memcmp(s, "ram", 3) == 0) {
struct ram_info info = ram_get_info();
uint64_t alloced = info.bytes_total - info.bytes_free;
uint64_t thou = 1000 * alloced / info.bytes_total;
printf("%lu total, %lu free, %lu allocated (%d.%d percent)\n", info.bytes_total, info.bytes_free,
alloced, thou/10, thou%10);
} else {
printf("unknown command\n");
}
}

View file

@ -14,6 +14,9 @@
#include "x86_64/ps2_driver.h"
#include "framebuffer.h"
#include "framebuffer.h"
#include "x86_64/interrupt.h"
/* imported virtual addresses, see linker script */
extern BOOTBOOT bootboot; // see bootboot.h
extern unsigned char environment[4096]; // configuration, UTF-8 text key=value pairs
@ -25,6 +28,8 @@ void basic_interrupt_handler(void) {
void early_clear(struct color col);
void (*task)(void);
/******************************************
* Entry point, called by BOOTBOOT Loader *
******************************************/

31
src/mouse.c Normal file
View file

@ -0,0 +1,31 @@
#include "std.h"
#include <stdint.h>
#include "mouse.h"
#define NUM_LISTENERS 10
mouse_event_listener listeners[NUM_LISTENERS];
size_t num_listeners = 0;
void register_mouse_event_listener(mouse_event_listener ls) {
ASSERT(num_listeners < NUM_LISTENERS);
listeners[num_listeners++] = ls;
}
void unregister_mouse_event_listener(mouse_event_listener ls) {
for (size_t i = 0; i < num_listeners; i++) {
if (listeners[i] == ls) {
num_listeners--;
for (size_t j = i; j < num_listeners; j++) {
listeners[j] = listeners[j+1];
}
return;
}
}
}
void on_mouse_event(int8_t mouse_x, int8_t mouse_y, uint8_t buttons) {
for (size_t i = 0; i < num_listeners; i++) {
listeners[i](mouse_x, mouse_y, buttons);
}
}

104
src/small3dlib/carModel.h Normal file
View file

@ -0,0 +1,104 @@
#ifndef CAR_MODEL_H
#define CAR_MODEL_H
#define CAR_VERTEX_COUNT 12
const S3L_Unit carVertices[CAR_VERTEX_COUNT * 3] = {
-51, 14, -108, // 0
-31, 103, -92, // 3
-31, 103, -3, // 6
51, 14, -108, // 9
31, 103, -92, // 12
31, 103, -3, // 15
-48, 59, 31, // 18
48, 59, 31, // 21
-40, 52, 86, // 24
-44, 14, 86, // 27
44, 14, 86, // 30
40, 52, 86 // 33
}; // carVertices
#define CAR_TRIANGLE_COUNT 18
const S3L_Index carTriangleIndices[CAR_TRIANGLE_COUNT * 3] = {
4, 3, 5, // 0
2, 7, 6, // 3
1, 0, 4, // 6
7, 5, 3, // 9
2, 4, 5, // 12
2, 0, 1, // 15
9, 6, 8, // 18
7, 8, 6, // 21
3, 4, 0, // 24
9, 11, 10, // 27
7, 3, 10, // 30
0, 6, 9, // 33
6, 0, 2, // 36
10, 11, 7, // 39
2, 5, 7, // 42
2, 1, 4, // 45
7, 11, 8, // 48
9, 8, 11 // 51
}; // carTriangleIndices
#define CAR_UV_COUNT 24
const S3L_Unit carUVs[CAR_UV_COUNT * 2] = {
451, 476, // 0
459, 509, // 2
422, 477, // 4
422, 476, // 6
409, 451, // 8
409, 476, // 10
451, 476, // 12
484, 476, // 14
451, 451, // 16
409, 492, // 18
422, 451, // 20
422, 477, // 22
459, 509, // 24
451, 476, // 26
398, 509, // 28
409, 492, // 30
398, 493, // 32
397, 476, // 34
484, 451, // 36
386, 476, // 38
397, 451, // 40
386, 451, // 42
398, 509, // 44
398, 493 // 46
}; // carUVs
#define CAR_UV_INDEX_COUNT 18
const S3L_Index carUVIndices[CAR_UV_INDEX_COUNT * 3] = {
0, 1, 2, // 0
3, 4, 5, // 3
6, 7, 8, // 6
9, 2, 1, // 9
3, 8, 10, // 12
11, 12, 13, // 15
14, 15, 16, // 18
4, 17, 5, // 21
18, 8, 7, // 24
19, 20, 21, // 27
9, 1, 22, // 30
12, 15, 14, // 33
15, 12, 11, // 36
22, 23, 9, // 39
3, 10, 4, // 42
3, 6, 8, // 45
4, 20, 17, // 48
19, 17, 20 // 51
}; // carUVIndices
S3L_Model3D carModel;
void carModelInit(void)
{
S3L_model3DInit(
carVertices,
CAR_VERTEX_COUNT,
carTriangleIndices,
CAR_TRIANGLE_COUNT,
&carModel);
}
#endif // guard

291
src/small3dlib/city.c Normal file
View file

@ -0,0 +1,291 @@
/*
Example program for small3dlib -- a GTA-like game demo.
author: Miloslav Ciz
license: CC0 1.0
*/
//#include <stdio.h>
#include <time.h>
#define S3L_FLAT 0
#define S3L_NEAR_CROSS_STRATEGY 3
#define S3L_PERSPECTIVE_CORRECTION 2
#define S3L_SORT 0
#define S3L_STENCIL_BUFFER 0
#define S3L_Z_BUFFER 2
#define S3L_PIXEL_FUNCTION drawPixel
#define S3L_RESOLUTION_X 640
#define S3L_RESOLUTION_Y 480
#include "small3dlib.h"
#include "cityModel.h"
#include "cityTexture.h"
#include "carModel.h"
#define TEXTURE_W 256
#define TEXTURE_H 256
#include "sdl_helper.h"
#define MAX_VELOCITY 1000
#define ACCELERATION 700
#define TURN_SPEED 300
#define FRICTION 600
S3L_Model3D models[2];
const uint8_t collisionMap[8 * 10] =
{
1,1,1,1,1,1,1,1,
1,1,1,1,0,0,0,1,
1,1,1,1,0,1,0,1,
2,2,1,0,0,0,0,3,
1,2,1,0,1,1,3,1,
2,0,0,0,1,1,3,3,
1,0,1,0,0,1,1,1,
1,0,0,0,1,1,1,1,
1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1
};
S3L_Scene scene;
uint32_t frame = 0;
void clearScreenBlue()
{
uint32_t index = 0;
for (uint16_t y = 0; y < S3L_RESOLUTION_Y; ++y)
{
S3L_Unit t = S3L_min(S3L_F,((y * S3L_F) / S3L_RESOLUTION_Y) * 4);
uint32_t r = S3L_interpolateByUnit(200,242,t);
uint32_t g = S3L_interpolateByUnit(102,255,t);
uint32_t b = S3L_interpolateByUnit(255,230,t);
//uint32_t color = (r << 24) | (g << 16 ) | (b << 8);
for (uint16_t x = 0; x < S3L_RESOLUTION_X; ++x)
{
//pixels[index] = color;
setPixel(x, y, r, g, b);
index++;
}
}
}
uint32_t previousTriangle = -1;
S3L_Vec4 uv0, uv1, uv2;
void drawPixel(S3L_PixelInfo *p)
{
if (p->triangleID != previousTriangle)
{
const S3L_Index *uvIndices;
const S3L_Unit *uvs;
if (p->modelIndex == 0)
{
uvIndices = cityUVIndices;
uvs = cityUVs;
}
else
{
uvIndices = carUVIndices;
uvs = carUVs;
}
S3L_getIndexedTriangleValues(p->triangleIndex,uvIndices,uvs,2,&uv0,&uv1,&uv2);
previousTriangle = p->triangleID;
}
uint8_t r, g, b;
S3L_Unit uv[2];
uv[0] = S3L_interpolateBarycentric(uv0.x,uv1.x,uv2.x,p->barycentric);
uv[1] = S3L_interpolateBarycentric(uv0.y,uv1.y,uv2.y,p->barycentric);
sampleTexture(cityTexture,uv[0] >> 1,uv[1] >> 1,&r,&g,&b);
setPixel(p->x,p->y,r,g,b);
}
void draw()
{
S3L_newFrame();
clearScreenBlue();
S3L_drawScene(scene);
}
static inline uint8_t collision(S3L_Vec4 worldPosition)
{
worldPosition.x /= S3L_F;
worldPosition.z /= -S3L_F;
uint16_t index = worldPosition.z * 8 + worldPosition.x;
return collisionMap[index];
}
static inline void handleCollision(S3L_Vec4 *pos, S3L_Vec4 previousPos)
{
S3L_Vec4 newPos = *pos;
newPos.x = previousPos.x;
if (collision(newPos))
{
newPos = *pos;
newPos.z = previousPos.z;
if (collision(newPos))
newPos = previousPos;
}
*pos = newPos;
}
int16_t fps = 0;
void city_main(void)
{
sdlInit();
cityModelInit();
carModelInit();
models[0] = cityModel;
models[1] = carModel;
S3L_sceneInit(models,2,&scene);
S3L_transform3DSet(1909,16,-3317,0,-510,0,512,512,512,&(models[1].transform));
int running = 1;
S3L_Vec4 carDirection;
S3L_vec4Init(&carDirection);
scene.camera.transform.translation.y = S3L_F / 2;
scene.camera.transform.rotation.x = -S3L_F / 16;
int16_t velocity = 0;
clock_t frameStartT = clock();
while (running) // main loop
{
models[1].transform.rotation.y += models[1].transform.rotation.z; // overturn the car for the rendering
draw();
models[1].transform.rotation.y -= models[1].transform.rotation.z; // turn the car back for the physics
fps++;
clock_t nowT = clock();
int16_t frameDiffMs = (nowT - frameStartT) * 1000 / CLOCKS_PER_SEC;
const uint8_t *state = SDL_GetKeyboardState(NULL);
int16_t step = (velocity * frameDiffMs) / 1000;
int16_t stepFriction = (FRICTION * frameDiffMs) / 1000;
int16_t stepRotation = TURN_SPEED * frameDiffMs * S3L_max(0,velocity - 200) / (MAX_VELOCITY * 1000);
int16_t stepVelocity = S3L_nonZero((ACCELERATION * frameDiffMs) / 1000);
if (stepRotation == 0 && S3L_abs(velocity) >= 200)
stepRotation = 1;
if (velocity < 0)
stepRotation *= -1;
if (state[SDL_SCANCODE_ESCAPE])
running = 0;
else if (state[SDL_SCANCODE_LEFT])
{
models[1].transform.rotation.y += stepRotation;
models[1].transform.rotation.z =
S3L_min(S3L_abs(velocity) / 64, models[1].transform.rotation.z + 1);
}
else if (state[SDL_SCANCODE_RIGHT])
{
models[1].transform.rotation.y -= stepRotation;
models[1].transform.rotation.z =
S3L_max(-S3L_abs(velocity) / 64, models[1].transform.rotation.z - 1);
}
else
models[1].transform.rotation.z = (models[1].transform.rotation.z * 3) / 4;
S3L_rotationToDirections(models[1].transform.rotation,S3L_F,&carDirection,0,0);
S3L_Vec4 previousCarPos = models[1].transform.translation;
int16_t friction = 0;
if (state[SDL_SCANCODE_UP])
velocity = S3L_min(MAX_VELOCITY,velocity + (velocity < 0 ? (2 * stepVelocity) : stepVelocity));
else if (state[SDL_SCANCODE_DOWN])
velocity = S3L_max(-MAX_VELOCITY,velocity - (velocity > 0 ? (2 * stepVelocity) : stepVelocity));
else
friction = 1;
models[1].transform.translation.x += (carDirection.x * step) / S3L_F;
models[1].transform.translation.z += (carDirection.z * step) / S3L_F;
uint8_t coll = collision(models[1].transform.translation);
if (coll != 0)
{
if (coll == 1)
{
handleCollision(&(models[1].transform.translation),previousCarPos);
friction = 2;
}
else if (coll == 2)
{
// teleport the car
models[1].transform.translation.x += 5 * S3L_F;
models[1].transform.translation.z += 2 * S3L_F;
}
else
{
// teleport the car
models[1].transform.translation.x -= 5 * S3L_F;
models[1].transform.translation.z -= 2 * S3L_F;
}
}
if (velocity > 0)
velocity = S3L_max(0,velocity - stepFriction * friction);
else
velocity = S3L_min(0,velocity + stepFriction * friction);
S3L_Unit cameraDistance =
S3L_interpolate(S3L_F / 2,(3 * S3L_F) / 4,S3L_abs(velocity),MAX_VELOCITY);
scene.camera.transform.translation.x =
scene.models[1].transform.translation.x - (carDirection.x * cameraDistance) / S3L_F;
scene.camera.transform.translation.z =
scene.models[1].transform.translation.z - (carDirection.z * cameraDistance) / S3L_F;
scene.camera.transform.rotation.y = models[1].transform.rotation.y;
sdlUpdate();
frameStartT = nowT;
frame++;
}
clearScreenBlue();
sdlUpdate();
}

958
src/small3dlib/cityModel.h Normal file
View file

@ -0,0 +1,958 @@
#ifndef CITY_MODEL_H
#define CITY_MODEL_H
#define CITY_VERTEX_COUNT 155
const S3L_Unit cityVertices[CITY_VERTEX_COUNT * 3] = {
0, 2, -2048, // 0
-512, 2, -1536, // 3
-1024, 2, -2560, // 6
-1024, 2, -3072, // 9
-1024, 2, -3584, // 12
-512, 2, -3072, // 15
-512, 2, -2560, // 18
512, 2, -1536, // 21
512, 2, -2048, // 24
1024, 2, -1536, // 27
512, 2, -2560, // 30
0, 2, -2560, // 33
563, 889, -1996, // 36
563, 889, -2611, // 39
-51, 889, -2611, // 42
-238, 790, -3072, // 45
512, 792, -3072, // 48
-1024, 388, -3072, // 51
-1024, 388, -3584, // 54
512, 388, -1536, // 57
1024, 388, -1536, // 60
-512, 698, -1536, // 63
-1024, 698, -2560, // 66
-1024, 388, -2560, // 69
-512, 698, -2560, // 72
512, 698, -1536, // 75
512, 407, -938, // 78
512, 698, -938, // 81
-512, 148, -3072, // 84
-238, 148, -3072, // 87
-512, 148, -3347, // 90
-1372, 297, -2017, // 93
-1145, 297, -1737, // 96
-1395, 1403, -2044, // 99
-1122, 1403, -1709, // 102
2560, 2, -1024, // 105
2048, 2, -512, // 108
1024, 2, -3072, // 111
1024, 2, -3584, // 114
512, 2, -4096, // 117
1024, 2, -4096, // 120
2048, 2, -3584, // 123
2048, 2, -4096, // 126
1536, 2, -3584, // 129
1536, 2, -3072, // 132
1024, 2, -2560, // 135
512, 2, -3072, // 138
1536, 2, -1536, // 141
1536, 2, -2048, // 144
1536, 2, -2560, // 147
2048, 2, -2048, // 150
2048, 2, -1536, // 153
3072, 2, -512, // 156
3072, 2, -1024, // 159
3584, 2, -512, // 162
3072, 2, -2048, // 165
2560, 2, -1536, // 168
2560, 2, -3072, // 171
2560, 2, -3584, // 174
2048, 2, -3072, // 177
998, 155, -3046, // 180
998, 155, -3609, // 183
1561, 155, -3609, // 186
1561, 155, -3046, // 189
2508, 889, -972, // 192
3123, 889, -972, // 195
3123, 889, -1587, // 198
2508, 889, -1587, // 201
1024, 316, -4096, // 204
2048, 316, -4096, // 207
512, 792, -4096, // 210
1024, 298, -4710, // 213
2321, 790, -2048, // 216
3072, 792, -2048, // 219
2048, 790, -3072, // 222
512, 792, -4710, // 225
1280, 297, -3328, // 228
2560, 790, -3072, // 231
2560, 259, -3072, // 234
2560, 259, -3584, // 237
1024, 388, -2560, // 240
1536, 388, -2048, // 243
1536, 388, -2560, // 246
3072, 388, -512, // 249
3584, 388, -512, // 252
2048, 698, -512, // 255
1536, 698, -1536, // 258
1536, 388, -1536, // 261
2048, 698, -1536, // 264
3072, 698, -512, // 267
3072, 407, 85, // 270
3072, 698, 85, // 273
1536, 698, -647, // 276
1536, 388, -647, // 279
2048, 148, -2048, // 282
2321, 148, -2048, // 285
2048, 148, -2323, // 288
2048, 790, -2323, // 291
2048, 1484, -3584, // 294
2048, 1227, -4096, // 297
2560, 1484, -3584, // 300
2443, -253, -5243, // 303
2721, -253, -4712, // 306
2443, 1078, -5243, // 309
2721, 1078, -4712, // 312
1187, 297, -993, // 315
1414, 297, -713, // 318
1177, 1403, -1022, // 321
1450, 1403, -687, // 324
1055, 297, -700, // 327
1019, 1403, -671, // 330
3584, 2, -2048, // 333
3584, 2, -2560, // 336
3072, 2, -3072, // 339
3584, 2, -3072, // 342
4608, 2, -2560, // 345
4608, 2, -3072, // 348
4096, 2, -2560, // 351
4096, 2, -2048, // 354
3584, 2, -1536, // 357
3072, 2, -1536, // 360
4096, 2, -1536, // 363
4608, 2, -1024, // 366
5120, 2, -2048, // 369
5120, 2, -2560, // 372
4608, 2, -2048, // 375
3558, 155, -2022, // 378
3558, 155, -2585, // 381
4121, 155, -2022, // 384
3584, 316, -3072, // 387
4608, 316, -3072, // 390
3072, 792, -3072, // 393
4881, 790, -1024, // 396
4608, 790, -2048, // 399
3840, 297, -2304, // 402
5120, 259, -2048, // 405
5120, 259, -2560, // 408
3584, 388, -1536, // 411
4096, 388, -1536, // 414
4881, 148, -1024, // 417
4608, 148, -1299, // 420
4608, 790, -1299, // 423
4608, 1484, -2560, // 426
4608, 1227, -3072, // 429
5120, 1484, -2560, // 432
5003, -253, -4219, // 435
5281, -253, -3688, // 438
5003, 1078, -4219, // 441
5281, 1078, -3688, // 444
3747, 297, 30, // 447
3974, 297, 310, // 450
3737, 1403, 1, // 453
4010, 1403, 336, // 456
3615, 297, 323, // 459
3579, 1403, 352 // 462
}; // cityVertices
#define CITY_TRIANGLE_COUNT 197
const S3L_Index cityTriangleIndices[CITY_TRIANGLE_COUNT * 3] = {
0, 1, 6, // 0
2, 3, 5, // 3
5, 3, 4, // 6
11, 5, 46, // 9
0, 6, 11, // 12
1, 0, 7, // 15
8, 45, 9, // 18
8, 10, 45, // 21
46, 10, 11, // 24
5, 11, 6, // 27
0, 8, 7, // 30
8, 9, 7, // 33
5, 6, 2, // 36
11, 13, 14, // 39
10, 8, 12, // 42
3, 18, 4, // 45
9, 19, 7, // 48
9, 45, 80, // 51
1, 7, 19, // 54
22, 23, 24, // 57
19, 21, 1, // 60
1, 24, 6, // 63
25, 21, 19, // 66
2, 23, 17, // 69
24, 23, 6, // 72
2, 17, 3, // 75
25, 26, 27, // 78
6, 23, 2, // 81
29, 28, 30, // 84
28, 29, 5, // 87
5, 29, 46, // 90
46, 29, 16, // 93
29, 15, 16, // 96
3, 17, 18, // 99
1, 21, 24, // 102
11, 10, 13, // 105
10, 12, 13, // 108
9, 20, 19, // 111
9, 80, 20, // 114
25, 19, 26, // 117
34, 31, 32, // 120
34, 33, 31, // 123
35, 36, 51, // 126
38, 46, 39, // 129
40, 38, 39, // 132
42, 41, 43, // 135
43, 40, 42, // 138
41, 59, 43, // 141
45, 37, 44, // 144
10, 46, 37, // 147
47, 48, 50, // 150
49, 59, 50, // 153
50, 48, 49, // 156
56, 50, 55, // 159
35, 51, 56, // 162
36, 35, 52, // 165
53, 119, 54, // 168
53, 120, 119, // 171
55, 120, 56, // 174
59, 44, 43, // 177
59, 49, 44, // 180
50, 56, 51, // 183
35, 53, 52, // 186
53, 54, 52, // 189
50, 51, 47, // 192
40, 43, 38, // 195
38, 37, 46, // 198
37, 45, 10, // 201
44, 49, 45, // 204
57, 59, 41, // 207
41, 58, 57, // 210
44, 37, 60, // 213
37, 38, 61, // 216
62, 43, 44, // 219
43, 61, 38, // 222
62, 63, 76, // 225
56, 66, 67, // 228
56, 64, 35, // 231
120, 53, 65, // 234
35, 65, 53, // 237
40, 69, 42, // 240
98, 79, 41, // 243
68, 70, 75, // 246
39, 46, 16, // 249
39, 70, 68, // 252
39, 68, 40, // 255
60, 76, 63, // 258
41, 79, 58, // 261
78, 74, 59, // 264
58, 78, 57, // 267
96, 97, 95, // 270
45, 49, 82, // 273
48, 82, 49, // 276
54, 83, 52, // 279
54, 119, 137, // 282
36, 52, 83, // 285
86, 87, 88, // 288
83, 85, 36, // 291
36, 88, 51, // 294
89, 85, 83, // 297
47, 87, 81, // 300
88, 87, 51, // 303
47, 81, 48, // 306
89, 90, 91, // 309
51, 87, 47, // 312
87, 86, 92, // 315
76, 60, 61, // 318
61, 62, 76, // 321
74, 97, 96, // 324
96, 59, 74, // 327
57, 78, 59, // 330
59, 96, 50, // 333
94, 50, 96, // 336
95, 94, 96, // 339
94, 95, 50, // 342
50, 95, 55, // 345
55, 95, 73, // 348
95, 72, 73, // 351
97, 72, 95, // 354
42, 69, 41, // 357
69, 98, 41, // 360
40, 68, 69, // 363
68, 75, 71, // 366
45, 82, 80, // 369
48, 81, 82, // 372
39, 16, 70, // 375
36, 85, 88, // 378
87, 92, 93, // 381
56, 120, 66, // 384
56, 67, 64, // 387
120, 65, 66, // 390
35, 64, 65, // 393
98, 100, 79, // 396
58, 79, 78, // 399
78, 77, 74, // 402
98, 69, 99, // 405
44, 60, 63, // 408
37, 61, 60, // 411
62, 44, 63, // 414
43, 62, 61, // 417
54, 84, 83, // 420
54, 137, 84, // 423
89, 83, 90, // 426
101, 104, 102, // 429
101, 103, 104, // 432
108, 105, 106, // 435
110, 105, 107, // 438
108, 107, 105, // 441
110, 109, 105, // 444
112, 55, 113, // 447
114, 112, 113, // 450
117, 114, 116, // 453
115, 125, 117, // 456
119, 111, 118, // 459
120, 55, 111, // 462
121, 125, 122, // 465
125, 118, 117, // 468
125, 121, 118, // 471
114, 117, 112, // 474
112, 111, 55, // 477
111, 119, 120, // 480
118, 121, 119, // 483
123, 125, 115, // 486
115, 124, 123, // 489
118, 111, 126, // 492
111, 112, 127, // 495
114, 130, 116, // 498
142, 136, 115, // 501
113, 55, 73, // 504
113, 131, 129, // 507
113, 129, 114, // 510
126, 134, 128, // 513
115, 136, 124, // 516
124, 135, 123, // 519
140, 141, 139, // 522
119, 121, 138, // 525
134, 126, 127, // 528
133, 141, 140, // 531
140, 125, 133, // 534
125, 140, 122, // 537
141, 132, 139, // 540
116, 130, 115, // 543
130, 142, 115, // 546
114, 129, 130, // 549
119, 138, 137, // 552
113, 73, 131, // 555
142, 144, 136, // 558
124, 136, 135, // 561
142, 130, 143, // 564
118, 126, 128, // 567
111, 127, 126, // 570
145, 148, 146, // 573
145, 147, 148, // 576
152, 149, 150, // 579
154, 149, 151, // 582
152, 151, 149, // 585
154, 153, 149 // 588
}; // cityTriangleIndices
#define CITY_UV_COUNT 377
const S3L_Unit cityUVs[CITY_UV_COUNT * 2] = {
125, 125, // 0
1, 1, // 2
1, 249, // 4
2, 1, // 6
2, 126, // 8
126, 126, // 10
2, 262, // 12
126, 262, // 14
126, 386, // 16
126, 387, // 18
2, 511, // 20
2, 262, // 22
125, 249, // 24
1, 2, // 26
125, 126, // 28
1, 251, // 30
126, 125, // 32
2, 249, // 34
2, 1, // 36
126, 249, // 38
126, 262, // 40
126, 511, // 42
125, 251, // 44
126, 1, // 46
126, 1, // 48
258, 253, // 50
386, 1, // 52
258, 1, // 54
260, 253, // 56
405, 253, // 58
405, 2, // 60
253, 511, // 62
130, 386, // 64
130, 511, // 66
381, 508, // 68
256, 386, // 70
256, 508, // 72
130, 509, // 74
380, 509, // 76
380, 386, // 78
258, 253, // 80
510, 253, // 82
510, 114, // 84
354, 3, // 86
354, 115, // 88
510, 3, // 90
258, 3, // 92
507, 252, // 94
255, 2, // 96
255, 252, // 98
510, 3, // 100
376, 511, // 102
376, 386, // 104
253, 386, // 106
510, 254, // 108
258, 3, // 110
475, 112, // 112
475, 3, // 114
354, 254, // 116
245, 319, // 118
190, 264, // 120
135, 319, // 122
509, 209, // 124
443, 209, // 126
509, 253, // 128
259, 253, // 130
259, 16, // 132
443, 16, // 134
507, 2, // 136
386, 253, // 138
260, 2, // 140
381, 386, // 142
130, 386, // 144
258, 112, // 146
509, 352, // 148
261, 259, // 150
261, 352, // 152
509, 259, // 154
125, 125, // 156
1, 1, // 158
1, 249, // 160
127, 125, // 162
3, 249, // 164
3, 1, // 166
127, 1, // 168
1, 2, // 170
125, 2, // 172
125, 126, // 174
1, 250, // 176
125, 254, // 178
125, 129, // 180
1, 254, // 182
126, 128, // 184
1, 128, // 186
1, 252, // 188
130, 1, // 190
130, 125, // 192
254, 125, // 194
2, 1, // 196
2, 126, // 198
126, 126, // 200
126, 386, // 202
2, 510, // 204
2, 262, // 206
2, 262, // 208
126, 262, // 210
126, 386, // 212
126, 387, // 214
2, 511, // 216
2, 262, // 218
125, 249, // 220
1, 2, // 222
125, 126, // 224
1, 251, // 226
126, 125, // 228
2, 249, // 230
2, 1, // 232
126, 249, // 234
126, 262, // 236
1, 129, // 238
126, 510, // 240
126, 511, // 242
125, 251, // 244
126, 1, // 246
126, 1, // 248
125, 250, // 250
127, 249, // 252
254, 1, // 254
126, 252, // 256
253, 130, // 258
129, 130, // 260
129, 254, // 262
253, 254, // 264
387, 448, // 266
508, 448, // 268
508, 386, // 270
387, 446, // 272
508, 446, // 274
508, 388, // 276
385, 390, // 278
385, 446, // 280
510, 446, // 282
511, 447, // 284
386, 388, // 286
386, 447, // 288
254, 259, // 290
131, 259, // 292
192, 321, // 294
258, 253, // 296
386, 1, // 298
258, 1, // 300
510, 252, // 302
385, 2, // 304
385, 252, // 306
260, 253, // 308
405, 253, // 310
405, 2, // 312
510, 254, // 314
384, 0, // 316
384, 254, // 318
381, 511, // 320
131, 434, // 322
131, 511, // 324
510, 350, // 326
302, 261, // 328
259, 350, // 330
221, 324, // 332
221, 257, // 334
163, 257, // 336
259, 252, // 338
511, 252, // 340
511, 15, // 342
259, 352, // 344
404, 352, // 346
317, 258, // 348
259, 258, // 350
130, 259, // 352
191, 320, // 354
253, 259, // 356
259, 261, // 358
259, 176, // 360
414, 16, // 362
414, 254, // 364
253, 382, // 366
129, 327, // 368
129, 382, // 370
477, 210, // 372
477, 15, // 374
354, 210, // 376
222, 509, // 378
352, 509, // 380
352, 386, // 382
253, 511, // 384
130, 386, // 386
130, 511, // 388
381, 508, // 390
256, 386, // 392
256, 508, // 394
130, 509, // 396
380, 509, // 398
380, 386, // 400
258, 253, // 402
510, 253, // 404
510, 114, // 406
354, 3, // 408
354, 115, // 410
510, 3, // 412
258, 3, // 414
507, 252, // 416
255, 2, // 418
255, 252, // 420
510, 3, // 422
376, 511, // 424
376, 386, // 426
253, 386, // 428
510, 254, // 430
258, 3, // 432
475, 112, // 434
475, 3, // 436
354, 254, // 438
509, 117, // 440
509, 2, // 442
259, 2, // 444
191, 321, // 446
254, 258, // 448
128, 258, // 450
252, 259, // 452
131, 259, // 454
192, 320, // 456
260, 16, // 458
442, 16, // 460
442, 211, // 462
260, 255, // 464
259, 254, // 466
509, 255, // 468
509, 211, // 470
245, 319, // 472
190, 264, // 474
135, 319, // 476
509, 209, // 478
443, 209, // 480
509, 253, // 482
259, 253, // 484
259, 16, // 486
443, 16, // 488
354, 15, // 490
260, 350, // 492
312, 350, // 494
260, 264, // 496
509, 264, // 498
381, 434, // 500
163, 324, // 502
222, 386, // 504
259, 15, // 506
507, 2, // 508
259, 117, // 510
386, 253, // 512
510, 2, // 514
260, 2, // 516
510, 0, // 518
510, 261, // 520
253, 327, // 522
259, 16, // 524
466, 350, // 526
387, 386, // 528
387, 388, // 530
510, 390, // 532
511, 388, // 534
381, 386, // 536
130, 386, // 538
258, 112, // 540
509, 251, // 542
351, 1, // 544
351, 251, // 546
509, 1, // 548
509, 352, // 550
261, 259, // 552
261, 352, // 554
509, 260, // 556
261, 351, // 558
509, 351, // 560
509, 259, // 562
261, 260, // 564
127, 125, // 566
3, 249, // 568
3, 1, // 570
127, 1, // 572
125, 126, // 574
1, 250, // 576
1, 2, // 578
125, 254, // 580
125, 129, // 582
1, 254, // 584
126, 128, // 586
1, 128, // 588
1, 252, // 590
130, 1, // 592
130, 125, // 594
254, 125, // 596
126, 386, // 598
2, 510, // 600
2, 262, // 602
1, 129, // 604
126, 510, // 606
125, 250, // 608
127, 249, // 610
254, 1, // 612
126, 252, // 614
253, 130, // 616
129, 130, // 618
129, 254, // 620
253, 254, // 622
387, 448, // 624
508, 448, // 626
508, 386, // 628
387, 446, // 630
508, 446, // 632
508, 388, // 634
381, 511, // 636
131, 434, // 638
131, 511, // 640
510, 350, // 642
302, 261, // 644
259, 350, // 646
259, 252, // 648
511, 252, // 650
511, 15, // 652
259, 352, // 654
404, 352, // 656
317, 258, // 658
259, 258, // 660
130, 259, // 662
191, 320, // 664
253, 259, // 666
259, 261, // 668
253, 382, // 670
129, 327, // 672
129, 382, // 674
477, 210, // 676
477, 15, // 678
354, 210, // 680
222, 509, // 682
352, 509, // 684
352, 386, // 686
191, 321, // 688
254, 258, // 690
128, 258, // 692
260, 16, // 694
442, 16, // 696
442, 211, // 698
260, 255, // 700
509, 255, // 702
354, 15, // 704
260, 350, // 706
312, 350, // 708
260, 264, // 710
509, 264, // 712
381, 434, // 714
222, 386, // 716
259, 15, // 718
510, 261, // 720
253, 327, // 722
466, 350, // 724
387, 386, // 726
387, 388, // 728
509, 251, // 730
351, 1, // 732
351, 251, // 734
509, 1, // 736
509, 352, // 738
261, 259, // 740
261, 352, // 742
509, 260, // 744
261, 351, // 746
509, 351, // 748
509, 259, // 750
261, 260 // 752
}; // cityUVs
#define CITY_UV_INDEX_COUNT 197
const S3L_Index cityUVIndices[CITY_UV_INDEX_COUNT * 3] = {
0, 1, 2, // 0
3, 4, 5, // 3
6, 7, 8, // 6
9, 10, 11, // 9
0, 2, 12, // 12
13, 14, 15, // 15
16, 17, 18, // 18
16, 19, 17, // 21
11, 20, 9, // 24
10, 9, 21, // 27
14, 22, 15, // 30
16, 18, 23, // 33
5, 24, 3, // 36
25, 26, 27, // 39
28, 29, 30, // 42
31, 32, 33, // 45
34, 35, 36, // 48
37, 38, 39, // 51
40, 41, 42, // 54
43, 44, 45, // 57
42, 46, 40, // 60
47, 48, 49, // 63
50, 46, 42, // 66
51, 52, 53, // 69
45, 44, 54, // 72
51, 53, 31, // 75
55, 56, 57, // 78
54, 44, 58, // 81
59, 60, 61, // 84
62, 63, 64, // 87
64, 63, 65, // 90
65, 63, 66, // 93
63, 67, 66, // 96
31, 53, 32, // 99
47, 68, 48, // 102
25, 69, 26, // 105
28, 30, 70, // 108
34, 71, 35, // 111
37, 39, 72, // 114
55, 73, 56, // 117
74, 75, 76, // 120
74, 77, 75, // 123
78, 79, 80, // 126
81, 82, 83, // 129
84, 81, 83, // 132
85, 86, 87, // 135
87, 88, 85, // 138
89, 90, 91, // 141
92, 93, 94, // 144
95, 96, 97, // 147
98, 99, 100, // 150
101, 102, 103, // 153
104, 105, 106, // 156
107, 108, 109, // 159
78, 80, 110, // 162
111, 112, 113, // 165
114, 115, 116, // 168
114, 117, 115, // 171
109, 118, 107, // 174
90, 119, 91, // 177
102, 101, 120, // 180
108, 107, 121, // 183
112, 122, 113, // 186
114, 116, 123, // 189
100, 124, 98, // 192
88, 87, 125, // 195
81, 126, 82, // 198
97, 127, 95, // 201
94, 128, 92, // 204
129, 130, 131, // 207
131, 132, 129, // 210
133, 134, 135, // 213
136, 137, 138, // 216
139, 140, 141, // 219
142, 143, 144, // 222
145, 146, 147, // 225
148, 149, 150, // 228
151, 152, 153, // 231
154, 155, 156, // 234
157, 158, 159, // 237
160, 161, 162, // 240
163, 164, 165, // 243
166, 167, 168, // 246
169, 170, 171, // 249
172, 173, 174, // 252
172, 174, 175, // 255
176, 177, 178, // 258
165, 164, 179, // 261
180, 181, 182, // 264
183, 184, 185, // 267
186, 187, 188, // 270
189, 190, 191, // 273
192, 193, 194, // 276
195, 196, 197, // 279
198, 199, 200, // 282
201, 202, 203, // 285
204, 205, 206, // 288
203, 207, 201, // 291
208, 209, 210, // 294
211, 207, 203, // 297
212, 213, 214, // 300
206, 205, 215, // 303
212, 214, 192, // 306
216, 217, 218, // 309
215, 205, 219, // 312
220, 221, 222, // 315
223, 224, 225, // 318
226, 227, 228, // 321
229, 230, 231, // 324
231, 232, 229, // 327
233, 180, 182, // 330
232, 231, 234, // 333
235, 234, 231, // 336
236, 237, 238, // 339
239, 240, 241, // 342
241, 240, 242, // 345
242, 240, 243, // 348
240, 244, 243, // 351
187, 245, 188, // 354
246, 247, 248, // 357
247, 249, 248, // 360
160, 250, 161, // 363
166, 168, 251, // 366
189, 191, 252, // 369
192, 214, 193, // 372
169, 171, 253, // 375
208, 254, 209, // 378
220, 222, 255, // 381
148, 256, 149, // 384
151, 257, 152, // 387
154, 156, 258, // 390
157, 259, 158, // 393
163, 260, 164, // 396
183, 261, 184, // 399
180, 262, 181, // 402
249, 247, 263, // 405
133, 135, 264, // 408
136, 138, 265, // 411
139, 141, 266, // 414
142, 267, 143, // 417
195, 268, 196, // 420
198, 200, 269, // 423
216, 270, 217, // 426
271, 272, 273, // 429
271, 274, 272, // 432
275, 276, 277, // 435
278, 279, 280, // 438
275, 281, 276, // 441
278, 282, 279, // 444
283, 284, 285, // 447
286, 283, 285, // 450
287, 288, 289, // 453
290, 291, 292, // 456
293, 294, 295, // 459
296, 297, 298, // 462
299, 300, 301, // 465
291, 302, 292, // 468
300, 299, 303, // 471
288, 287, 304, // 474
283, 305, 284, // 477
298, 306, 296, // 480
295, 307, 293, // 483
308, 309, 310, // 486
310, 311, 308, // 489
312, 313, 314, // 492
315, 316, 317, // 495
318, 319, 320, // 498
321, 322, 323, // 501
324, 325, 326, // 504
327, 328, 329, // 507
327, 329, 330, // 510
331, 332, 333, // 513
323, 322, 334, // 516
335, 336, 337, // 519
338, 339, 340, // 522
341, 342, 343, // 525
344, 345, 346, // 528
347, 348, 349, // 531
349, 350, 347, // 534
350, 349, 351, // 537
339, 352, 340, // 540
353, 354, 355, // 543
354, 356, 355, // 546
318, 357, 319, // 549
341, 343, 358, // 552
324, 326, 359, // 555
321, 360, 322, // 558
335, 361, 336, // 561
356, 354, 362, // 564
312, 314, 363, // 567
315, 317, 364, // 570
365, 366, 367, // 573
365, 368, 366, // 576
369, 370, 371, // 579
372, 373, 374, // 582
369, 375, 370, // 585
372, 376, 373 // 588
}; // cityUVIndices
S3L_Model3D cityModel;
void cityModelInit(void)
{
S3L_model3DInit(
cityVertices,
CITY_VERTEX_COUNT,
cityTriangleIndices,
CITY_TRIANGLE_COUNT,
&cityModel);
}
#endif // guard

15134
src/small3dlib/cityTexture.h Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,81 @@
#include "std.h"
#include "ram.h"
#include "time.h"
#include "framebuffer.h"
#include "keyboard.h"
#define CLOCKS_PER_SEC NSEC_PER_SEC
typedef uint64_t clock_t;
clock_t clock(void)
{
return TIME_TO_NS(time_current());
}
#define SDL_SCANCODE_ESCAPE KEY_ESC
#define SDL_SCANCODE_LEFT KEY_ARROW_LEFT
#define SDL_SCANCODE_RIGHT KEY_ARROW_RIGHT
#define SDL_SCANCODE_UP KEY_ARROW_UP
#define SDL_SCANCODE_DOWN KEY_ARROW_DOWN
uint8_t keyboard_state[256];
struct fb_region region;
void sdl_key_event_listener(enum keycode code, bool pressed)
{
keyboard_state[code] = pressed;
}
void sdlInit(void)
{
register_raw_key_event_listener(sdl_key_event_listener);
unsigned padX = (fb_width() - S3L_RESOLUTION_X) / 2;
unsigned padY = (fb_height() - S3L_RESOLUTION_Y) / 2;
struct rect desiredRect = RECT_XYWH(
padX, padY,
S3L_RESOLUTION_X,
S3L_RESOLUTION_Y);
fb_access_region(desiredRect, &region);
}
void sdlEnd(void)
{
unregister_raw_key_event_listener(sdl_key_event_listener);
}
void sdlUpdate(void)
{
fb_damage(region.rect);
fb_refresh();
}
void clearScreen(void)
{
memset(region.pointer, 200, region.stride * (region.rect.y2 - region.rect.y1));
fb_damage(region.rect);
}
static inline void setPixel(int x, int y, uint8_t red, uint8_t green, uint8_t blue)
{
uint32_t *pixel = region.pointer + y * region.stride + 4 * x;
*pixel = (uint32_t)red << 16 | (uint32_t)green << 8 | (uint32_t)blue;
}
void sampleTexture(const uint8_t *tex, int32_t u, int32_t v, uint8_t *r, uint8_t *g, uint8_t *b)
{
u = S3L_wrap(u,TEXTURE_W);
v = S3L_wrap(v,TEXTURE_H);
const uint8_t *t = tex + (v * TEXTURE_W + u) * 4;
*r = *t;
t++;
*g = *t;
t++;
*b = *t;
}
uint8_t *SDL_GetKeyboardState(void *ptr)
{
(void)ptr;
return keyboard_state;
}

2997
src/small3dlib/small3dlib.h Normal file

File diff suppressed because it is too large Load diff

View file

@ -64,8 +64,8 @@ snake_draw_tile(struct snake_game *game, int tx, int ty, enum tile type)
}
struct rect desiredRect = RECT_XYWH(
tx * SNAKE_TILE_SIZE,
ty * SNAKE_TILE_SIZE,
padX + tx * SNAKE_TILE_SIZE,
padY + ty * SNAKE_TILE_SIZE,
SNAKE_TILE_SIZE,
SNAKE_TILE_SIZE);
app_draw_rect(game, col, &desiredRect);
@ -232,3 +232,18 @@ void snake_destroy(void *self) {
timer_cancel(&game->timer);
ram_free(ppn_from_aligned_pa(pa_from_pointer(self)));
}
void
snake_main(void)
{
snake_running = true;
snake_start();
while (snake_running) {
fb_refresh();
__asm__ ("hlt");
}
timer_cancel(&snake_timer);
unregister_raw_key_event_listener(snake_key_event_listener);
}

View file

@ -72,20 +72,6 @@ hwclock_rtc_irq_handler(void)
{
struct hwclock_cpu_local *local = &hwclock_cpu_local;
hwclock_rtc_counter++;
if (hwclock_rtc_counter >= HWCLOCK_RTC_FREQUENCY) {
hwclock_rtc_counter = 0;
hwclock_seconds++;
uint64_t tsc_value = rdtsc();
uint64_t tsc_ticks = tsc_value - local->tsc_second_start;
local->tsc_second_start = tsc_value;
local->tsc_scale_factor = (NSEC_PER_SEC << 32) / local->tsc_ticks_per_second;
local->tsc_ticks_per_second *= 128 - 4;
local->tsc_ticks_per_second += 4 * tsc_ticks;
local->tsc_ticks_per_second /= 128;
}
switch (local->calibration_state) {
case HWCLOCK_CALIBRATION_START:
{
@ -118,6 +104,7 @@ hwclock_rtc_irq_handler(void)
local->tsc_scale_factor = (NSEC_PER_SEC << 32) / local->tsc_ticks_per_second;
local->tsc_second_start = tsc_value;
local->calibration_state = HWCLOCK_CALIBRATION_DONE;
break;
}
@ -143,8 +130,8 @@ hwclock_lapic_irq_handler(void)
Time elapsed = time_subtract(now, local->lapic_timer_start);
uint64_t elapsed_ns = TIME_TO_NS(elapsed);
if (elapsed_ns > 0) {
local->lapic_ticks_per_second *= 128 - 1;
local->lapic_ticks_per_second += 1 * ((uint64_t)initial * NSEC_PER_SEC / elapsed_ns);
local->lapic_ticks_per_second *= 128 - 16;
local->lapic_ticks_per_second += 16 * ((uint64_t)initial * NSEC_PER_SEC / elapsed_ns);
local->lapic_ticks_per_second /= 128;
}
}

View file

@ -1,6 +1,7 @@
#include <stdint.h>
#include "cpu.h"
#include "mouse.h"
#include "std.h"
#include "x86_64/apic.h"
#include "x86_64/asm.h"
@ -173,11 +174,10 @@ uint8_t ps2_code_to_keycode(uint8_t ps2_code) {
uint8_t ps2_code_ext_to_keycode(uint8_t ps2_code) {
switch (ps2_code) {
case 0x11: return KEY_RALT;
case 0x74: return KEY_ARROW_RIGHT;
case 0x6b: return KEY_ARROW_LEFT;
case 0x75: return KEY_ARROW_UP;
case 0x72: return KEY_ARROW_DOWN;
case 0x75: return KEY_ARROW_UP;
case 0x72: return KEY_ARROW_DOWN;
case 0x6B: return KEY_ARROW_LEFT;
case 0x74: return KEY_ARROW_RIGHT;
default: return 0;
}
}
@ -255,15 +255,57 @@ void port1_handler(void) {
#endif
}
#define MOUSE_PACKET_Y_OVERFLOW 7
#define MOUSE_PACKET_X_OVERFLOW 6
#define MOUSE_PACKET_Y_SIGN 5
#define MOUSE_PACKET_X_SIGN 4
#define MOUSE_PACKET_ONE 3
#define MOUSE_PACKET_BUTTON_MIDDLE 2
#define MOUSE_PACKET_BUTTON_RIGHT 1
#define MOUSE_PACKET_BUTTON_LEFT 0
size_t mouse_packet_byte = 0;
union {
uint8_t arr[3];
struct mouse_packet {
uint8_t buttons, x, y;
} mouse;
} mouse;
void port2_handler(void) {
if (!ps2_can_read()) {
// Assume spurious interrupt. Maybe from another device?
return;
}
uint8_t data = ps2_read_data();
(void)data;
DEBUG_PRINTF("keycode from port 2: %X8\n", data);
uint8_t data = ps2_read_data();
DEBUG_PRINTF("keycode from port 2: %X8\n", data);
if ((mouse_packet_byte == 0) && ((data & (1 << MOUSE_PACKET_ONE)) == 0)) {
return;
}
int8_t x = mouse.mouse.x - ((mouse.mouse.buttons << 4) & 0x100);
int8_t y = mouse.mouse.y - ((mouse.mouse.buttons << 3) & 0x100);
mouse.arr[mouse_packet_byte++] = data;
if (mouse_packet_byte == 3) {
mouse_packet_byte = 0;
on_mouse_event(x, y, mouse.mouse.buttons & (MOUSE_BUTTON_MIDDLE | MOUSE_BUTTON_RIGHT | MOUSE_BUTTON_LEFT));
DEBUG_PRINTF(
"mouse event: %u %u %u %u %u %u %u, X: %d, Y: %d, [%u, %u]\n",
mouse.mouse.buttons >> MOUSE_PACKET_Y_OVERFLOW & 1,
mouse.mouse.buttons >> MOUSE_PACKET_X_OVERFLOW & 1,
mouse.mouse.buttons >> MOUSE_PACKET_Y_SIGN & 1,
mouse.mouse.buttons >> MOUSE_PACKET_X_SIGN & 1,
mouse.mouse.buttons >> MOUSE_PACKET_BUTTON_MIDDLE & 1,
mouse.mouse.buttons >> MOUSE_PACKET_BUTTON_RIGHT & 1,
mouse.mouse.buttons >> MOUSE_PACKET_BUTTON_LEFT & 1,
x,
y,
mouse.mouse.x,
mouse.mouse.y
);
}
}
#define PS2_INIT_PRINT
@ -285,14 +327,14 @@ void ps2_init() {
/* Flush Outputbuffer */
ps2_empty_output_buffer();
/* Set Configbyte */
config_byte = ps2_cmd_response(CMD_CONFIGBYTE_READ);
config_byte &= ~(1 << CONFIG_BIT_PORT1_INT_ENABLED);
config_byte &= ~(1 << CONFIG_BIT_PORT1_CLOCK_DISABLED);
config_byte &= ~(1 << CONFIG_BIT_PORT1_TRANSLATION);
ps2_cmd_with_data(CMD_CONFIGBYTE_WRITE, config_byte);
/* Selftest */
uint8_t test = ps2_cmd_response(CMD_TEST);
PS2_TEST("self-test", test, 0x55);
@ -302,7 +344,8 @@ void ps2_init() {
config_byte = ps2_cmd_response(CMD_CONFIGBYTE_READ);
bool port_2_enabled = ((config_byte >> 5) & 1) == 0;
if (port_2_enabled) {
ps2_write_cmd(CMD_PORT2_DISABLE);
DEBUG_PRINTF("port 2 enabled\n");
ps2_write_cmd(CMD_PORT2_DISABLE);
config_byte = ps2_cmd_response(CMD_CONFIGBYTE_READ);
config_byte &= ~(1 << CONFIG_BIT_PORT2_INT_ENABLED);
config_byte &= ~(1 << CONFIG_BIT_PORT2_CLOCK_DISABLED);
@ -341,6 +384,16 @@ void ps2_init() {
ps2_write_data(0xFF);
ps2_read_data();
// TODO reset port 2
if (port_2_enabled) {
ps2_write_cmd(0xD4);
ps2_write_data(0xFF);
// ps2_read_data();
ps2_empty_output_buffer();
ps2_write_cmd(0xD4);
ps2_write_data(0xF4);
ps2_empty_output_buffer();
// ps2_read_data();
}
/* Enable interrupts */
config_byte = ps2_cmd_response(CMD_CONFIGBYTE_READ);
@ -351,5 +404,5 @@ void ps2_init() {
ps2_cmd_with_data(CMD_CONFIGBYTE_WRITE, config_byte);
/* Flush Outputbuffer again because it doesn't work otherwise */
//ps2_empty_output_buffer();
ps2_empty_output_buffer();
}