Emscripten Paint Works!!!!!!
This commit is contained in:
parent
dcf348f577
commit
0c72525755
11
Makefile
11
Makefile
|
@ -55,16 +55,15 @@ endif
|
|||
|
||||
# --- EMSCRIPTEN-SPECIFIC ---
|
||||
ifeq ($(PLATFORM), emscripten)
|
||||
LDFLAGS += -s USE_SDL=2 -s WASM=1 \
|
||||
LDFLAGS += -s USE_SDL=2\
|
||||
-s ASYNCIFY \
|
||||
-s ALLOW_MEMORY_GROWTH=1 \
|
||||
-s MAX_WEBGL_VERSION=2 \
|
||||
--preload-file test/paint-bw.rom@paint.rom \
|
||||
-s INITIAL_MEMORY=16MB
|
||||
--preload-file test/paint.rom@paint.rom
|
||||
|
||||
# For release: optimize, strip debug, minimize size
|
||||
ifeq ($(BUILD_MODE), release)
|
||||
PLATFORM_CFLAGS += -O2 -flto
|
||||
LDFLAGS += -O2 -flto
|
||||
PLATFORM_CFLAGS += -O2
|
||||
LDFLAGS += -O2
|
||||
endif
|
||||
|
||||
# Output: HTML + JS + WASM
|
||||
|
|
|
@ -121,29 +121,13 @@ i32 screen_write(void *data, const u8 *buffer, u32 size) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (!screen->screen_buffer) {
|
||||
screen->screen_buffer = (u8*)buffer;
|
||||
}
|
||||
|
||||
// Update texture with new frame data
|
||||
SDL_UpdateTexture(screen->texture, NULL, buffer, screen->width);
|
||||
|
||||
// Clear and render
|
||||
SDL_RenderClear(screen->renderer);
|
||||
|
||||
SDL_Rect output_rect;
|
||||
SDL_RenderGetViewport(screen->renderer, &output_rect);
|
||||
|
||||
// Calculate aspect ratio preserving scaling
|
||||
float scale_x = (float)output_rect.w / screen->width;
|
||||
float scale_y = (float)output_rect.h / screen->height;
|
||||
float scale = SDL_min(scale_x, scale_y);
|
||||
|
||||
SDL_Rect dstrect = {
|
||||
(i32)((output_rect.w - screen->width * scale) / 2),
|
||||
(i32)((output_rect.h - screen->height * scale) / 2),
|
||||
(i32)(screen->width * scale),
|
||||
(i32)(screen->height * scale)
|
||||
};
|
||||
|
||||
SDL_RenderCopy(screen->renderer, screen->texture, NULL, &dstrect);
|
||||
SDL_RenderPresent(screen->renderer);
|
||||
screen->update = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -210,54 +194,6 @@ i32 mouse_read(void *data, u8 *buffer, u32 size) {
|
|||
|
||||
if (size < 12) return -1;
|
||||
|
||||
SDL_PumpEvents();
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
switch (event.type) {
|
||||
// Mouse events
|
||||
case SDL_MOUSEMOTION:
|
||||
mouse_data->x = event.motion.x;
|
||||
mouse_data->y = event.motion.y;
|
||||
break;
|
||||
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
if (event.button.button == SDL_BUTTON_LEFT) mouse_data->btn1 = 1;
|
||||
if (event.button.button == SDL_BUTTON_RIGHT) mouse_data->btn2 = 1;
|
||||
if (event.button.button == SDL_BUTTON_MIDDLE) mouse_data->btn3 = 1;
|
||||
if (event.button.button == SDL_BUTTON_X1) mouse_data->btn4 = 1;
|
||||
break;
|
||||
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
if (event.button.button == SDL_BUTTON_LEFT) mouse_data->btn1 = 0;
|
||||
if (event.button.button == SDL_BUTTON_RIGHT) mouse_data->btn2 = 0;
|
||||
if (event.button.button == SDL_BUTTON_MIDDLE) mouse_data->btn3 = 0;
|
||||
if (event.button.button == SDL_BUTTON_X1) mouse_data->btn4 = 0;
|
||||
break;
|
||||
|
||||
// Touch events (map to mouse_data as left-click equivalent)
|
||||
case SDL_FINGERMOTION:
|
||||
case SDL_FINGERDOWN:
|
||||
case SDL_FINGERUP: {
|
||||
|
||||
float x = event.tfinger.x * 640;
|
||||
float y = event.tfinger.y * 480;
|
||||
|
||||
mouse_data->x = (int)x;
|
||||
mouse_data->y = (int)y;
|
||||
|
||||
// Only treat the first finger as mouse input (ignore multi-touch beyond 1 finger)
|
||||
if (event.tfinger.fingerId == 0) {
|
||||
if (event.type == SDL_FINGERDOWN || event.type == SDL_FINGERMOTION) {
|
||||
mouse_data->btn1 = 1;
|
||||
} else if (event.type == SDL_FINGERUP) {
|
||||
mouse_data->btn1 = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u8 *info = (u8 *)buffer;
|
||||
memcpy(&info[0], &mouse_data->x, sizeof(u32));
|
||||
memcpy(&info[4], &mouse_data->y, sizeof(u32));
|
||||
|
|
|
@ -8,6 +8,8 @@ typedef struct screen_device_data_s {
|
|||
u32 height;
|
||||
u32 pos;
|
||||
u32 size;
|
||||
u8 *screen_buffer;
|
||||
bool update;
|
||||
SDL_Window *window;
|
||||
SDL_Renderer *renderer;
|
||||
SDL_Texture *texture;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include "../../vm/vm.h"
|
||||
#include "../../vm/device.h"
|
||||
#include "../../vm/vm.h"
|
||||
#include "devices.h"
|
||||
#include <SDL2/SDL.h>
|
||||
#include <emscripten.h>
|
||||
|
@ -31,10 +31,171 @@ static DeviceOps console_device_ops = {
|
|||
static ScreenDeviceData screen_data = {0};
|
||||
static MouseDeviceData mouse_data = {0};
|
||||
|
||||
const char *opcode_to_string(Opcode op) {
|
||||
static const char *names[] = {[OP_HALT] = "halt",
|
||||
[OP_JMP] = "jump",
|
||||
[OP_JMPF] = "jump-if-flag",
|
||||
[OP_CALL] = "call",
|
||||
[OP_RETURN] = "return",
|
||||
[OP_LOAD_IMM] = "load-immediate",
|
||||
[OP_GET_8] = "get-8",
|
||||
[OP_GET_16] = "get-16",
|
||||
[OP_GET_32] = "get",
|
||||
[OP_LOAD_8] = "load-8",
|
||||
[OP_LOAD_16] = "load-16",
|
||||
[OP_LOAD_32] = "load",
|
||||
[OP_STORE_8] = "store-8",
|
||||
[OP_STORE_16] = "store-16",
|
||||
[OP_STORE_32] = "store",
|
||||
[OP_PUT_8] = "put-8",
|
||||
[OP_PUT_16] = "put-16",
|
||||
[OP_PUT_32] = "put",
|
||||
[OP_MALLOC] = "malloc",
|
||||
[OP_MEMSET_8] = "memset-8",
|
||||
[OP_MEMSET_16] = "memset-16",
|
||||
[OP_MEMSET_32] = "memset-32",
|
||||
[OP_PUSH] = "push",
|
||||
[OP_POP] = "pop",
|
||||
[OP_REG_MOV] = "register-move",
|
||||
[OP_SYSCALL] = "syscall",
|
||||
[OP_SLL] = "bit-shift-left",
|
||||
[OP_SRL] = "bit-shift-right",
|
||||
[OP_SRE] = "bit-shift-re",
|
||||
[OP_BAND] = "bit-and",
|
||||
[OP_BOR] = "bit-or",
|
||||
[OP_BXOR] = "bit-xor",
|
||||
[OP_ADD_INT] = "add-int",
|
||||
[OP_SUB_INT] = "sub-int",
|
||||
[OP_MUL_INT] = "mul-int",
|
||||
[OP_DIV_INT] = "div-int",
|
||||
[OP_ADD_UINT] = "add-nat",
|
||||
[OP_SUB_UINT] = "sub-nat",
|
||||
[OP_MUL_UINT] = "mul-nat",
|
||||
[OP_DIV_UINT] = "div-nat",
|
||||
[OP_ADD_REAL] = "add-real",
|
||||
[OP_SUB_REAL] = "sub-real",
|
||||
[OP_MUL_REAL] = "mul-real",
|
||||
[OP_DIV_REAL] = "div-real",
|
||||
[OP_INT_TO_REAL] = "int-to-real",
|
||||
[OP_UINT_TO_REAL] = "nat-to-real",
|
||||
[OP_REAL_TO_INT] = "real-to-int",
|
||||
[OP_REAL_TO_UINT] = "real-to-nat",
|
||||
[OP_JEQ_INT] = "jump-eq-int",
|
||||
[OP_JNEQ_INT] = "jump-neq-int",
|
||||
[OP_JGT_INT] = "jump-gt-int",
|
||||
[OP_JLT_INT] = "jump-lt-int",
|
||||
[OP_JLE_INT] = "jump-le-int",
|
||||
[OP_JGE_INT] = "jump-ge-int",
|
||||
[OP_JEQ_UINT] = "jump-eq-nat",
|
||||
[OP_JNEQ_UINT] = "jump-neq-nat",
|
||||
[OP_JGT_UINT] = "jump-gt-nat",
|
||||
[OP_JLT_UINT] = "jump-lt-nat",
|
||||
[OP_JLE_UINT] = "jump-le-nat",
|
||||
[OP_JGE_UINT] = "jump-ge-nat",
|
||||
[OP_JEQ_REAL] = "jump-eq-real",
|
||||
[OP_JNEQ_REAL] = "jump-neq-real",
|
||||
[OP_JGE_REAL] = "jump-ge-real",
|
||||
[OP_JGT_REAL] = "jump-gt-real",
|
||||
[OP_JLT_REAL] = "jump-lt-real",
|
||||
[OP_JLE_REAL] = "jump-le-real",
|
||||
[OP_STRLEN] = "string-length",
|
||||
[OP_STREQ] = "string-eq",
|
||||
[OP_STRCAT] = "string-concat",
|
||||
[OP_STR_GET_CHAR] = "string-get-char",
|
||||
[OP_STR_FIND_CHAR] = "string-find-char",
|
||||
[OP_STR_SLICE] = "string-slice",
|
||||
[OP_INT_TO_STRING] = "int-to-string",
|
||||
[OP_UINT_TO_STRING] = "nat-to-string",
|
||||
[OP_REAL_TO_STRING] = "real-to-string",
|
||||
[OP_STRING_TO_INT] = "string-to-int",
|
||||
[OP_STRING_TO_UINT] = "string-to-nat",
|
||||
[OP_STRING_TO_REAL] = "string-to-real"};
|
||||
|
||||
if (op < 0 || op >= (int)(sizeof(names) / sizeof(names[0]))) {
|
||||
return "<invalid-opcode>";
|
||||
}
|
||||
|
||||
const char *name = names[op];
|
||||
return name ? name : "<unknown-opcode>";
|
||||
}
|
||||
|
||||
void mainloop() {
|
||||
SDL_Event event;
|
||||
SDL_PumpEvents();
|
||||
while (SDL_PollEvent(&event)) {
|
||||
switch (event.type) {
|
||||
// Mouse events
|
||||
case SDL_MOUSEMOTION:
|
||||
mouse_data.x = event.motion.x;
|
||||
mouse_data.y = event.motion.y;
|
||||
break;
|
||||
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
if (event.button.button == SDL_BUTTON_LEFT)
|
||||
mouse_data.btn1 = 1;
|
||||
if (event.button.button == SDL_BUTTON_RIGHT)
|
||||
mouse_data.btn2 = 1;
|
||||
if (event.button.button == SDL_BUTTON_MIDDLE)
|
||||
mouse_data.btn3 = 1;
|
||||
if (event.button.button == SDL_BUTTON_X1)
|
||||
mouse_data.btn4 = 1;
|
||||
break;
|
||||
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
if (event.button.button == SDL_BUTTON_LEFT)
|
||||
mouse_data.btn1 = 0;
|
||||
if (event.button.button == SDL_BUTTON_RIGHT)
|
||||
mouse_data.btn2 = 0;
|
||||
if (event.button.button == SDL_BUTTON_MIDDLE)
|
||||
mouse_data.btn3 = 0;
|
||||
if (event.button.button == SDL_BUTTON_X1)
|
||||
mouse_data.btn4 = 0;
|
||||
break;
|
||||
|
||||
// Touch events (map to mouse_data as left-click equivalent)
|
||||
case SDL_FINGERMOTION:
|
||||
case SDL_FINGERDOWN:
|
||||
case SDL_FINGERUP: {
|
||||
|
||||
float x = event.tfinger.x * 640;
|
||||
float y = event.tfinger.y * 480;
|
||||
|
||||
mouse_data.x = (int)x;
|
||||
mouse_data.y = (int)y;
|
||||
|
||||
// Only treat the first finger as mouse input (ignore multi-touch beyond 1
|
||||
// finger)
|
||||
if (event.tfinger.fingerId == 0) {
|
||||
if (event.type == SDL_FINGERDOWN || event.type == SDL_FINGERMOTION) {
|
||||
mouse_data.btn1 = 1;
|
||||
} else if (event.type == SDL_FINGERUP) {
|
||||
mouse_data.btn1 = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Run VM for a fixed number of cycles or a time slice
|
||||
int cycles_this_frame = 0;
|
||||
int max_cycles_per_frame = 1000; // Adjust this value
|
||||
while (cycles_this_frame < max_cycles_per_frame) {
|
||||
// printf("%s\n", opcode_to_string(vm.code[vm.pc])); // REMOVE THIS LINE
|
||||
if (!step_vm(&vm)) {
|
||||
emscripten_cancel_main_loop();
|
||||
printf("VM execution completed\n");
|
||||
return;
|
||||
}
|
||||
cycles_this_frame++;
|
||||
}
|
||||
|
||||
// Render only if the screen buffer was updated AND at a reasonable rate
|
||||
if (screen_data.update) {
|
||||
if (screen_data.renderer && screen_data.texture) {
|
||||
SDL_RenderCopy(screen_data.renderer, screen_data.texture, NULL, NULL);
|
||||
SDL_RenderPresent(screen_data.renderer);
|
||||
}
|
||||
screen_data.update = false; // Reset flag after rendering
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,9 +245,9 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0");
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#ifdef __EMSCRIPTEN__
|
||||
emscripten_set_canvas_element_size("#canvas", 640, 480);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
loadVM("paint.rom", &vm);
|
||||
printf("VM loaded successfully\n");
|
||||
|
|
|
@ -89,29 +89,13 @@ i32 screen_write(void *data, const u8 *buffer, u32 size) {
|
|||
if (size > screen->size * sizeof(u8)) {
|
||||
return -1;
|
||||
}
|
||||
if (!screen->screen_buffer) {
|
||||
screen->screen_buffer = (u8*)buffer;
|
||||
}
|
||||
|
||||
// Update texture with new frame data
|
||||
SDL_UpdateTexture(screen->texture, NULL, buffer, screen->width);
|
||||
|
||||
// Clear and render
|
||||
SDL_RenderClear(screen->renderer);
|
||||
|
||||
SDL_Rect output_rect;
|
||||
SDL_RenderGetViewport(screen->renderer, &output_rect);
|
||||
|
||||
// Calculate aspect ratio preserving scaling
|
||||
float scale_x = (float)output_rect.w / screen->width;
|
||||
float scale_y = (float)output_rect.h / screen->height;
|
||||
float scale = SDL_min(scale_x, scale_y);
|
||||
|
||||
SDL_Rect dstrect = {
|
||||
(i32)((output_rect.w - screen->width * scale) / 2),
|
||||
(i32)((output_rect.h - screen->height * scale) / 2),
|
||||
(i32)(screen->width * scale),
|
||||
(i32)(screen->height * scale)
|
||||
};
|
||||
|
||||
SDL_RenderCopy(screen->renderer, screen->texture, NULL, &dstrect);
|
||||
SDL_RenderPresent(screen->renderer);
|
||||
screen->update = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,8 @@ typedef struct screen_device_data_s {
|
|||
u32 height;
|
||||
u32 pos;
|
||||
u32 size;
|
||||
u8 *screen_buffer;
|
||||
u32 update;
|
||||
SDL_Window *window;
|
||||
SDL_Renderer *renderer;
|
||||
SDL_Texture *texture;
|
||||
|
|
|
@ -394,8 +394,8 @@ i32 main(i32 argc, char *argv[]) {
|
|||
screen_data.height = 480;
|
||||
screen_data.size = screen_data.width * screen_data.height;
|
||||
|
||||
vm_register_device(&vm, "/dev/screen/0", "screen",
|
||||
&screen_data, &screen_ops);
|
||||
vm_register_device(&vm, "/dev/screen/0", "screen", &screen_data,
|
||||
&screen_ops);
|
||||
|
||||
mouse_data.x = 0;
|
||||
mouse_data.y = 0;
|
||||
|
@ -411,11 +411,104 @@ i32 main(i32 argc, char *argv[]) {
|
|||
vm_register_device(&vm, "/dev/keyboard/0", "keyboard", &keyboard_data,
|
||||
&keyboard_ops);
|
||||
|
||||
SDL_Event event;
|
||||
bool running = true;
|
||||
SDL_PumpEvents();
|
||||
while (running) {
|
||||
if (!step_vm(&vm)) {
|
||||
while (SDL_PollEvent(&event)) {
|
||||
switch (event.type) {
|
||||
case SDL_QUIT:
|
||||
running = false;
|
||||
break;
|
||||
// Mouse events
|
||||
case SDL_MOUSEMOTION:
|
||||
mouse_data.x = event.motion.x;
|
||||
mouse_data.y = event.motion.y;
|
||||
break;
|
||||
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
if (event.button.button == SDL_BUTTON_LEFT)
|
||||
mouse_data.btn1 = 1;
|
||||
if (event.button.button == SDL_BUTTON_RIGHT)
|
||||
mouse_data.btn2 = 1;
|
||||
if (event.button.button == SDL_BUTTON_MIDDLE)
|
||||
mouse_data.btn3 = 1;
|
||||
if (event.button.button == SDL_BUTTON_X1)
|
||||
mouse_data.btn4 = 1;
|
||||
break;
|
||||
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
if (event.button.button == SDL_BUTTON_LEFT)
|
||||
mouse_data.btn1 = 0;
|
||||
if (event.button.button == SDL_BUTTON_RIGHT)
|
||||
mouse_data.btn2 = 0;
|
||||
if (event.button.button == SDL_BUTTON_MIDDLE)
|
||||
mouse_data.btn3 = 0;
|
||||
if (event.button.button == SDL_BUTTON_X1)
|
||||
mouse_data.btn4 = 0;
|
||||
break;
|
||||
|
||||
// Touch events (map to mouse_data as left-click equivalent)
|
||||
case SDL_FINGERMOTION:
|
||||
case SDL_FINGERDOWN:
|
||||
case SDL_FINGERUP: {
|
||||
|
||||
float x = event.tfinger.x * 640;
|
||||
float y = event.tfinger.y * 480;
|
||||
|
||||
mouse_data.x = (int)x;
|
||||
mouse_data.y = (int)y;
|
||||
|
||||
// Only treat the first finger as mouse input (ignore multi-touch
|
||||
// beyond 1 finger)
|
||||
if (event.tfinger.fingerId == 0) {
|
||||
if (event.type == SDL_FINGERDOWN ||
|
||||
event.type == SDL_FINGERMOTION) {
|
||||
mouse_data.btn1 = 1;
|
||||
} else if (event.type == SDL_FINGERUP) {
|
||||
mouse_data.btn1 = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Run VM for a fixed number of cycles or a time slice
|
||||
int cycles_this_frame = 0;
|
||||
int max_cycles_per_frame = 1000; // Adjust this value
|
||||
while (cycles_this_frame < max_cycles_per_frame) {
|
||||
if (!step_vm(&vm)) {
|
||||
running = false;
|
||||
}
|
||||
cycles_this_frame++;
|
||||
}
|
||||
|
||||
// Render only if the screen buffer was updated AND at a reasonable rate
|
||||
if (screen_data.update) {
|
||||
if (screen_data.renderer && screen_data.texture) {
|
||||
// Clear and render
|
||||
SDL_RenderClear(screen_data.renderer);
|
||||
|
||||
SDL_Rect output_rect;
|
||||
SDL_RenderGetViewport(screen_data.renderer, &output_rect);
|
||||
|
||||
// Calculate aspect ratio preserving scaling
|
||||
float scale_x = (float)output_rect.w / screen_data.width;
|
||||
float scale_y = (float)output_rect.h / screen_data.height;
|
||||
float scale = SDL_min(scale_x, scale_y);
|
||||
|
||||
SDL_Rect dstrect = {
|
||||
(i32)((output_rect.w - screen_data.width * scale) / 2),
|
||||
(i32)((output_rect.h - screen_data.height * scale) / 2),
|
||||
(i32)(screen_data.width * scale),
|
||||
(i32)(screen_data.height * scale)};
|
||||
|
||||
SDL_RenderCopy(screen_data.renderer, screen_data.texture, NULL,
|
||||
&dstrect);
|
||||
SDL_RenderPresent(screen_data.renderer);
|
||||
}
|
||||
screen_data.update = false; // Reset flag after rendering
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -1,52 +1,68 @@
|
|||
((code
|
||||
(label main
|
||||
(load-immediate $30 4) ; fat ptr size
|
||||
|
||||
; Open screen
|
||||
; use load immediate because it is a pointer to a string, not a value
|
||||
(load-immediate $0 &screen-namespace)
|
||||
(load-immediate $11 0)
|
||||
(syscall OPEN $0 $11)
|
||||
(syscall OPEN $0 $0 $11)
|
||||
|
||||
(load-immediate $16 1) ; device info call
|
||||
(load-immediate $17 16) ; sizeof screen device info
|
||||
(malloc $18 $17)
|
||||
(syscall IOCTL $0 $16 $18)
|
||||
|
||||
(load-immediate $1 12) ; offset for width
|
||||
(add-nat $19 $18 $1)
|
||||
(get $20 $19) ; load width
|
||||
|
||||
(load-immediate $1 8) ; offset for size
|
||||
(add-nat $19 $18 $1)
|
||||
(get $22 $19) ; load size
|
||||
|
||||
(malloc $21 $22) ; malloc frame buffer
|
||||
|
||||
(load-immediate $16 &mouse-namespace)
|
||||
(load-immediate $3 12) ; malloc sizeof mouse data
|
||||
(malloc $4 $3)
|
||||
(syscall OPEN $16 $16 $4)
|
||||
|
||||
(load-immediate $14 20) ; box size
|
||||
(push $21)
|
||||
(push $20)
|
||||
(load $1 &BLACK)
|
||||
(push $1)
|
||||
(load-immediate $12 1)
|
||||
(push $12)
|
||||
(load-immediate $13 1)
|
||||
(push $13)
|
||||
(call &draw-outlined-swatch)
|
||||
|
||||
(push $21)
|
||||
(push $20)
|
||||
(load $1 &WHITE)
|
||||
(push $1)
|
||||
(load-immediate $12 21)
|
||||
(push $12)
|
||||
(load-immediate $13 1)
|
||||
(push $13)
|
||||
(call &draw-outlined-swatch)
|
||||
|
||||
(syscall WRITE $0 $21 $22)
|
||||
|
||||
|
||||
(label draw-loop
|
||||
; load mouse click data
|
||||
(syscall READ $16 $2 $3 $4)
|
||||
|
||||
(load-immediate $5 4) ; offset for x
|
||||
(add-nat $6 $5 $2)
|
||||
(get $7 $6) ; load x
|
||||
|
||||
(load-immediate $5 8) ; offset for y
|
||||
(add-nat $6 $5 $2)
|
||||
(get $8 $6) ; load y
|
||||
|
||||
(load-immediate $5 12) ; offset for btn1
|
||||
(add-nat $6 $5 $2)
|
||||
(get-8 $9 $6) ; load btn1 pressed
|
||||
|
||||
(load-immediate $14 20) ; box size
|
||||
|
||||
(jump-eq-nat &draw-loop $9 $11)
|
||||
|
||||
(load-immediate $5 4) ; offset for x
|
||||
(add-nat $6 $5 $2)
|
||||
(get $7 $6) ; load x
|
||||
(load-immediate $5 8) ; offset for y
|
||||
(add-nat $6 $5 $2)
|
||||
(get $8 $6) ; load y
|
||||
(load-immediate $5 13) ; offset for btn2
|
||||
(add-nat $6 $5 $2)
|
||||
(get-8 $10 $6) ; load btn2 pressed
|
||||
|
@ -61,7 +77,6 @@
|
|||
(load-immediate $13 1)
|
||||
(push $13)
|
||||
(call &draw-outlined-swatch)
|
||||
(syscall WRITE $0 $21 $22)
|
||||
|
||||
(push $14) ; box_size (20)
|
||||
(push $13) ; box_y
|
||||
|
@ -93,14 +108,17 @@
|
|||
|
||||
(syscall WRITE $0 $21 $22)
|
||||
|
||||
(jump-eq-nat &draw-loop $9 $11)
|
||||
|
||||
(mul-nat $15 $8 $20) ; $15 = y * width
|
||||
(add-nat $15 $15 $7) ; $15 += x
|
||||
(add-nat $15 $21 $15) ; $15 = base + pixel_offset
|
||||
(add-nat $15 $15 $30)
|
||||
(load $22 &SELECTED-COLOR) ; color
|
||||
(store-8 $15 $22) ; draw color at screen [x,y]
|
||||
(load-immediate $1 5) ; size of brush
|
||||
|
||||
(push $21) ;base
|
||||
(push $20) ;width
|
||||
(push $22) ; color
|
||||
(push $7) ;x
|
||||
(push $8) ;y
|
||||
(push $1)
|
||||
(push $1)
|
||||
(call &draw-box)
|
||||
|
||||
(jump-eq-nat &draw-loop $10 $11))
|
||||
|
||||
|
@ -208,9 +226,7 @@
|
|||
(label draw-box-outer
|
||||
(add-int $6 $4 $12) ; $6 = row end = current + width
|
||||
(register-move $7 $4) ; $7 = pixel pointer
|
||||
|
||||
(memset-8 $7 $3 $12)
|
||||
|
||||
(memset-8 $7 $3 $12) ; draw row
|
||||
(add-int $4 $4 $2) ; next row (+= 640)
|
||||
(sub-int $5 $5 $1) ; decrement row count
|
||||
(jump-gt-int &draw-box-outer $5 0))
|
||||
|
@ -222,4 +238,5 @@
|
|||
(label BLACK 0)
|
||||
(label WHITE 255)
|
||||
(label DARK-GRAY 73)
|
||||
(label GRAY 146)))
|
||||
(label GRAY 146)
|
||||
(label LIGHT-GRAY 182)))
|
||||
|
|
Binary file not shown.
|
@ -36,9 +36,6 @@
|
|||
(load-immediate $5 12) ; offset for btn1
|
||||
(add-nat $6 $5 $2)
|
||||
(get-8 $9 $6) ; load btn1 pressed
|
||||
(load-immediate $5 13) ; offset for btn2
|
||||
(add-nat $6 $5 $2)
|
||||
(get-8 $10 $6) ; load btn2 pressed
|
||||
|
||||
(load-immediate $14 20) ; box size
|
||||
|
||||
|
@ -253,7 +250,7 @@
|
|||
(push $1)
|
||||
(call &draw-box)
|
||||
|
||||
(jump-eq-nat &draw-loop $10 $11))
|
||||
(jump-eq-nat &draw-loop $11 $11))
|
||||
|
||||
; Flush and halt
|
||||
(halt))
|
||||
|
|
BIN
test/paint.rom
BIN
test/paint.rom
Binary file not shown.
Loading…
Reference in New Issue