uxn

Varvara Ordinator, written in ANSI C(SDL2)
git clone https://git.eamoncaddigan.net/uxn.git
Log | Files | Refs | README | LICENSE

system.c (3364B)


      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 
      4 #include "../uxn.h"
      5 
      6 #include "system.h"
      7 
      8 /*
      9 Copyright (c) 2022-2025 Devine Lu Linvega, Andrew Alderwick
     10 
     11 Permission to use, copy, modify, and distribute this software for any
     12 purpose with or without fee is hereby granted, provided that the above
     13 copyright notice and this permission notice appear in all copies.
     14 
     15 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     16 WITH REGARD TO THIS SOFTWARE.
     17 */
     18 
     19 char *boot_path;
     20 
     21 static void
     22 system_print(Stack *s)
     23 {
     24 	Uint8 i;
     25 	for(i = s->ptr - 8; i != (Uint8)(s->ptr); i++)
     26 		fprintf(stderr, "%02x%c", s->dat[i], i == 0xff ? '|' : ' ');
     27 	fprintf(stderr, "< \n");
     28 }
     29 
     30 int
     31 system_error(char *msg, const char *err)
     32 {
     33 	fprintf(stderr, "%s: %s\n", msg, err), fflush(stderr);
     34 	return 0;
     35 }
     36 
     37 static int
     38 system_load(Uint8 *ram, char *rom_path)
     39 {
     40 	FILE *f = fopen(rom_path, "rb");
     41 	if(f) {
     42 		int i = 0, l = fread(ram, 0x10000 - PAGE_PROGRAM, 1, f);
     43 		while(l && ++i < RAM_PAGES)
     44 			l = fread(ram + 0x10000 * i - PAGE_PROGRAM, 0x10000, 1, f);
     45 		fclose(f);
     46 	}
     47 	return !!f;
     48 }
     49 
     50 void
     51 system_reboot(int soft)
     52 {
     53 	int i;
     54 	for(i = soft ? 0x100 : 0; i < 0x10000; i++) uxn.ram[i] = 0;
     55 	for(i = 0x0; i < 0x100; i++) uxn.dev[i] = 0;
     56 	uxn.wst.ptr = uxn.rst.ptr = 0;
     57 	if(system_load(&uxn.ram[PAGE_PROGRAM], boot_path))
     58 		uxn_eval(PAGE_PROGRAM);
     59 }
     60 
     61 int
     62 system_boot(Uint8 *ram, char *rom_path)
     63 {
     64 	uxn.ram = ram, boot_path = rom_path;
     65 	return system_load(uxn.ram + PAGE_PROGRAM, rom_path);
     66 }
     67 
     68 /* IO */
     69 
     70 Uint8
     71 system_dei(Uint8 addr)
     72 {
     73 	switch(addr) {
     74 	case 0x4: return uxn.wst.ptr;
     75 	case 0x5: return uxn.rst.ptr;
     76 	default: return uxn.dev[addr];
     77 	}
     78 }
     79 
     80 void
     81 system_deo(Uint8 port)
     82 {
     83 	switch(port) {
     84 	case 0x3: {
     85 		Uint16 addr = PEEK2(uxn.dev + 2);
     86 		if(uxn.ram[addr] == 0x0) {
     87 			Uint16 i, value = uxn.ram[addr + 7], length = PEEK2(uxn.ram + addr + 1);
     88 			unsigned int dst_page = PEEK2(uxn.ram + addr + 3), dst_addr = PEEK2(uxn.ram + addr + 5);
     89 			unsigned int dst = dst_page * 0x10000;
     90 			if(dst_page < RAM_PAGES)
     91 				for(i = 0; i < length; i++)
     92 					uxn.ram[dst + (Uint16)(dst_addr + i)] = value;
     93 		} else if(uxn.ram[addr] == 0x1) {
     94 			Uint16 i, length = PEEK2(uxn.ram + addr + 1);
     95 			unsigned int a_page = PEEK2(uxn.ram + addr + 3), a_addr = PEEK2(uxn.ram + addr + 5);
     96 			unsigned int b_page = PEEK2(uxn.ram + addr + 7), b_addr = PEEK2(uxn.ram + addr + 9);
     97 			unsigned int src = a_page * 0x10000, dst = b_page * 0x10000;
     98 			if(a_page < RAM_PAGES && b_page < RAM_PAGES)
     99 				for(i = 0; i < length; i++)
    100 					uxn.ram[dst + (Uint16)(b_addr + i)] = uxn.ram[src + (Uint16)(a_addr + i)];
    101 		} else if(uxn.ram[addr] == 0x2) {
    102 			Uint16 i, length = PEEK2(uxn.ram + addr + 1);
    103 			unsigned int a_page = PEEK2(uxn.ram + addr + 3), a_addr = PEEK2(uxn.ram + addr + 5);
    104 			unsigned int b_page = PEEK2(uxn.ram + addr + 7), b_addr = PEEK2(uxn.ram + addr + 9);
    105 			unsigned int src = a_page * 0x10000, dst = b_page * 0x10000;
    106 			if(a_page < RAM_PAGES && b_page < RAM_PAGES)
    107 				for(i = length - 1; i != 0xffff; i--)
    108 					uxn.ram[dst + (Uint16)(b_addr + i)] = uxn.ram[src + (Uint16)(a_addr + i)];
    109 		} else
    110 			fprintf(stderr, "Unknown Expansion Command 0x%02x\n", uxn.ram[addr]);
    111 		break;
    112 	}
    113 	case 0x4:
    114 		uxn.wst.ptr = uxn.dev[4];
    115 		break;
    116 	case 0x5:
    117 		uxn.rst.ptr = uxn.dev[5];
    118 		break;
    119 	case 0xe:
    120 		fprintf(stderr, "WST "), system_print(&uxn.wst);
    121 		fprintf(stderr, "RST "), system_print(&uxn.rst);
    122 		break;
    123 	}
    124 }