Skip to content

Instantly share code, notes, and snippets.

@ljcucc
Last active October 3, 2022 02:22
Show Gist options
  • Save ljcucc/ac855678107676310d96a132f0fdb130 to your computer and use it in GitHub Desktop.
Save ljcucc/ac855678107676310d96a132f0fdb130 to your computer and use it in GitHub Desktop.
uxn
import "dart:typed_data";
var program = Uint8List.fromList(<int>[
0xa0, 0x01, 0x38, 0x80, 0x10, 0x37, 0xa0, 0x01,
0x15, 0xa0, 0x06, 0x29, 0x2e, 0xa0, 0x01, 0x35,
0xa0, 0x06, 0x29, 0x2e, 0x00, 0x56, 0x61, 0x72,
0x76, 0x61, 0x72, 0x61, 0x27, 0x73, 0x20, 0x55,
0x6e, 0x69, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x20,
0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20,
0x31, 0x2e, 0x30, 0x0a, 0x00, 0x3e, 0x20, 0x00,
0x80, 0x12, 0x16, 0x06, 0xa0, 0x02, 0x1a, 0x2e,
0x80, 0x0a, 0x09, 0x80, 0x33, 0x0d, 0xa0, 0x02,
0xbf, 0x2e, 0xa0, 0xff, 0x02, 0x17, 0xa0, 0x01,
0xac, 0x80, 0x00, 0x37, 0xa0, 0x01, 0x7a, 0xa0,
0x04, 0xa4, 0x2e, 0x80, 0x2c, 0xa0, 0x04, 0xac,
0x2e, 0xa0, 0x01, 0xe1, 0x2e, 0xa0, 0x00, 0x00,
0xa0, 0x01, 0x00, 0xa0, 0x05, 0x98, 0x2e, 0x80,
0x00, 0xa0, 0xff, 0xff, 0x15, 0xa0, 0x67, 0x39,
0x2c, 0x00, 0xa0, 0x01, 0xa6, 0xa0, 0x06, 0x29,
0x2e, 0xa0, 0xff, 0xff, 0x14, 0x80, 0x00, 0x80,
0x00, 0x07, 0xa0, 0xff, 0x00, 0x38, 0x14, 0xa0,
0x05, 0xf7, 0x2e, 0xa0, 0x20, 0x18, 0x17, 0x01,
0x8a, 0x80, 0xeb, 0x0d, 0x22, 0xa0, 0x0a, 0x18,
0x17, 0xa0, 0x00, 0x02, 0x17, 0x00, 0x57, 0x53,
0x54, 0x3a, 0x20, 0x00, 0xa0, 0x06, 0xaf, 0xa0,
0x06, 0x29, 0x2e, 0xa0, 0x06, 0xe4, 0xa0, 0x06,
0x29, 0x2e, 0xa0, 0x28, 0x18, 0x17, 0x80, 0x00,
0xa0, 0xff, 0xfe, 0x14, 0x80, 0x10, 0x3f, 0xa0,
0x01, 0xd9, 0x38, 0x34, 0xa0, 0x06, 0x29, 0x2e,
0xa0, 0x29, 0x18, 0x17, 0xa0, 0x00, 0x02, 0x17,
0x00, 0x06, 0xe9, 0x06, 0xf1, 0x06, 0xfb, 0x07,
0x04, 0x80, 0x96, 0x30, 0xa0, 0x00, 0x04, 0x28,
0x80, 0x28, 0x0d, 0xa0, 0x02, 0x14, 0xa0, 0x06,
0x29, 0x2e, 0xa0, 0x67, 0x39, 0x26, 0x80, 0x96,
0x30, 0x38, 0xa0, 0x00, 0x04, 0x39, 0x24, 0x94,
0xa0, 0x05, 0xf7, 0x2e, 0xa0, 0x20, 0x18, 0x17,
0x21, 0xaa, 0x80, 0xf2, 0x0d, 0x22, 0x22, 0xa0,
0x0a, 0x18, 0x17, 0x6c, 0x41, 0x53, 0x4d, 0x3a,
0x20, 0x00, 0x80, 0x28, 0x88, 0x03, 0x80, 0x23,
0x0d, 0x80, 0x29, 0x88, 0x03, 0x80, 0x1c, 0x0d,
0x80, 0x00, 0x80, 0x15, 0x0d, 0x80, 0x20, 0x8a,
0x03, 0x80, 0x17, 0x0d, 0xa0, 0x00, 0x00, 0x26,
0x80, 0x17, 0x0e, 0xa0, 0x00, 0x30, 0xa0, 0x05,
0x98, 0x2e, 0x02, 0x6c, 0x80, 0x29, 0x19, 0x80,
0xdf, 0x13, 0x6c, 0xa0, 0x00, 0x00, 0xa0, 0x05,
0xbb, 0x2c, 0xa0, 0x05, 0xa8, 0x2e, 0x1d, 0x80,
0x01, 0x0d, 0x6c, 0xa0, 0x07, 0x39, 0xa0, 0x07,
0x12, 0x94, 0xa0, 0x00, 0x00, 0x14, 0x08, 0x80,
0x33, 0x0d, 0x21, 0x21, 0x21, 0xaa, 0x80, 0xf0,
0x0d, 0x22, 0x22, 0xa0, 0x00, 0x00, 0x26, 0xa0,
0x04, 0xbf, 0x2e, 0x80, 0x28, 0x0d, 0x26, 0xa0,
0x05, 0xa8, 0x2e, 0xa0, 0x00, 0x04, 0x28, 0x80,
0x24, 0x0d, 0x26, 0xa0, 0x05, 0xa8, 0x2e, 0xa0,
0x00, 0x02, 0x28, 0x80, 0x20, 0x0d, 0xa0, 0x06,
0xab, 0xa0, 0x06, 0x10, 0x2c, 0x23, 0xa0, 0x00,
0x00, 0x21, 0x24, 0x21, 0x34, 0x2c, 0xa0, 0x04,
0xc9, 0x2e, 0xa0, 0x04, 0xac, 0x2c, 0xa0, 0x05,
0x35, 0x2e, 0xa0, 0x04, 0xa8, 0x2c, 0xa0, 0x05,
0x35, 0x2e, 0x03, 0xa0, 0x04, 0xac, 0x2c, 0x80,
0x92, 0x30, 0x1d, 0x80, 0x01, 0x0d, 0x6c, 0xa0,
0x37, 0x39, 0x26, 0x80, 0x0f, 0x0e, 0x21, 0x21,
0xa0, 0x05, 0xaf, 0x2e, 0x21, 0xa1, 0x21, 0x14,
0x80, 0xef, 0x0d, 0x22, 0x6c, 0xaf, 0x21, 0x21,
0xa1, 0x80, 0x6e, 0x0e, 0x26, 0xa0, 0xff, 0xff,
0x28, 0x80, 0x1e, 0x0d, 0x34, 0x2f, 0x94, 0x80,
0x2e, 0x08, 0x80, 0x21, 0x0d, 0x94, 0x80, 0x2c,
0x08, 0x80, 0x20, 0x0d, 0x94, 0x80, 0x3b, 0x08,
0x80, 0x40, 0x0d, 0x94, 0x80, 0x3a, 0x08, 0x80,
0x3e, 0x0d, 0x22, 0x6f, 0x21, 0x21, 0x62, 0xa0,
0x06, 0xa7, 0xa0, 0x06, 0x10, 0x2c, 0x6f, 0x03,
0x6f, 0x80, 0x1f, 0x0c, 0x6f, 0xef, 0x34, 0x39,
0xa0, 0x00, 0x02, 0x39, 0x26, 0xa0, 0x00, 0x80,
0x38, 0x02, 0x80, 0x00, 0x08, 0x80, 0x09, 0x0d,
0x27, 0x21, 0xa0, 0x06, 0xa3, 0xa0, 0x06, 0x10,
0x2e, 0x03, 0x6f, 0x34, 0xa0, 0x67, 0x39, 0x38,
0x15, 0x22, 0x6c, 0x6f, 0x6f, 0x80, 0x02, 0x0c,
0x6f, 0x6f, 0x34, 0xa0, 0x67, 0x39, 0x38, 0x35,
0x22, 0x6c, 0x2f, 0xa0, 0x07, 0x39, 0xa1, 0x21,
0xef, 0xa0, 0x05, 0xd5, 0x2e, 0x80, 0x13, 0x0d,
0x21, 0x21, 0xa0, 0x05, 0xaf, 0x2e, 0x21, 0xa1,
0x21, 0x14, 0x80, 0xe9, 0x0d, 0x22, 0x62, 0xa0,
0xff, 0xff, 0x6c, 0x62, 0x6c, 0x26, 0xa0, 0x05,
0xa8, 0x2e, 0xa0, 0x00, 0x04, 0x28, 0x80, 0x13,
0x0d, 0x26, 0xa0, 0x05, 0xa8, 0x2e, 0xa0, 0x00,
0x02, 0x28, 0x80, 0x0f, 0x0d, 0xa0, 0x06, 0x9b,
0xa0, 0x06, 0x10, 0x2c, 0xa0, 0x05, 0x35, 0x2e,
0xa0, 0x04, 0xa4, 0x2c, 0xa0, 0x05, 0x35, 0x2e,
0x03, 0xa0, 0x04, 0x9e, 0x2c, 0x26, 0xa0, 0x03,
0x52, 0x2e, 0xa0, 0xff, 0xff, 0x28, 0x80, 0x08,
0x0d, 0x26, 0xa0, 0x06, 0x9f, 0xa0, 0x06, 0x10,
0x2e, 0x80, 0x94, 0x30, 0xa0, 0x07, 0x39, 0x80,
0x90, 0x30, 0xaf, 0x38, 0x35, 0x61, 0x61, 0x26,
0xa0, 0x07, 0x39, 0xef, 0x38, 0xa0, 0x05, 0xc5,
0x2e, 0xa0, 0x05, 0xa8, 0x2e, 0x2f, 0x78, 0x61,
0x6f, 0x80, 0x90, 0x31, 0x6c, 0xa0, 0x00, 0x30,
0xaf, 0xa0, 0x00, 0x30, 0xa0, 0x05, 0x98, 0x2e,
0x26, 0x6f, 0xa0, 0x05, 0xc5, 0x2c, 0xa0, 0x05,
0x35, 0x2e, 0x80, 0x94, 0x31, 0x6c, 0xa0, 0x05,
0x35, 0x2e, 0x80, 0x94, 0x30, 0x38, 0x80, 0x94,
0x31, 0x6c, 0x80, 0xd8, 0x0e, 0x80, 0x9d, 0x0c,
0x80, 0x3e, 0x0e, 0x80, 0x97, 0x0c, 0x80, 0x94,
0x30, 0x21, 0x80, 0x55, 0x0e, 0x80, 0xff, 0xa0,
0x04, 0x9e, 0x2c, 0x80, 0x94, 0x30, 0x21, 0x80,
0x48, 0x0e, 0xa0, 0xff, 0xff, 0xa0, 0x04, 0xa4,
0x2c, 0x80, 0x94, 0x30, 0x80, 0x3b, 0x0e, 0xa0,
0xff, 0xff, 0xa0, 0x04, 0xa8, 0x2c, 0x14, 0xa0,
0x04, 0xac, 0x2c, 0x94, 0xa0, 0x04, 0xac, 0x2e,
0x21, 0x94, 0x80, 0xf6, 0x0d, 0x22, 0x6c, 0x22,
0x6c, 0xa0, 0x00, 0x60, 0xaf, 0xa0, 0x00, 0x30,
0xa0, 0x05, 0x98, 0x2e, 0xa0, 0x00, 0x30, 0xef,
0xa0, 0x05, 0xc5, 0x2e, 0x80, 0x2f, 0xef, 0xa0,
0x05, 0xbb, 0x2e, 0xef, 0xa0, 0x05, 0xc0, 0x2e,
0x6f, 0x6c, 0xa0, 0x37, 0x39, 0x80, 0x92, 0x30,
0x38, 0xaf, 0x35, 0x61, 0x61, 0x26, 0xa0, 0x00,
0x01, 0x39, 0x14, 0xef, 0x15, 0x61, 0x94, 0x80,
0x26, 0x09, 0x80, 0x04, 0x0d, 0x21, 0x80, 0xc0,
0x0e, 0x26, 0xef, 0xa0, 0x05, 0xc5, 0x2e, 0xa0,
0x05, 0xa8, 0x2e, 0x6f, 0x38, 0xa0, 0x37, 0x39,
0x39, 0x21, 0x80, 0x92, 0x31, 0x6c, 0x80, 0x80,
0x04, 0x80, 0x04, 0x0c, 0xa0, 0xa0, 0x04, 0x0e,
0x04, 0x80, 0x00, 0x0e, 0xa0, 0x67, 0x39, 0x80,
0x94, 0x30, 0xaf, 0x38, 0x15, 0x61, 0xef, 0x80,
0x94, 0x31, 0x6f, 0x80, 0x96, 0x31, 0x6c, 0x26,
0xa0, 0x06, 0x94, 0x80, 0x5d, 0x0e, 0x80, 0x31,
0x0d, 0x2f, 0xa0, 0x20, 0x00, 0x80, 0x00, 0x07,
0x80, 0x03, 0x1a, 0xa0, 0x06, 0x34, 0x38, 0xef,
0x80, 0x48, 0x0e, 0x80, 0x0a, 0x0d, 0x01, 0x8a,
0x80, 0xea, 0x0d, 0x22, 0x62, 0x80, 0x00, 0x6c,
0x03, 0x06, 0x80, 0x00, 0x08, 0x80, 0x70, 0x1f,
0x18, 0x6f, 0x21, 0x21, 0x21, 0x80, 0x06, 0x0e,
0x18, 0x6c, 0x22, 0x80, 0x01, 0x6c, 0xc0, 0x00,
0x94, 0x80, 0x32, 0x08, 0x80, 0x50, 0x1f, 0x0f,
0x58, 0x94, 0x80, 0x72, 0x08, 0x80, 0x60, 0x1f,
0x0f, 0x58, 0x94, 0x80, 0x6b, 0x08, 0x80, 0x70,
0x1f, 0x0f, 0x58, 0x21, 0x94, 0x80, 0xe0, 0x0d,
0x22, 0x4f, 0x6c, 0xb4, 0x2f, 0x21, 0x21, 0x24,
0xb4, 0x2f, 0x21, 0x21, 0x68, 0x14, 0x0f, 0x14,
0x0f, 0x48, 0x5c, 0x4f, 0x6c, 0x26, 0x80, 0x24,
0x0e, 0x80, 0x0b, 0x0d, 0xa0, 0x06, 0x97, 0xa0,
0x06, 0x10, 0x2e, 0xa0, 0x00, 0x00, 0x6c, 0xe0,
0x00, 0x00, 0xc0, 0x40, 0x7f, 0xc0, 0x00, 0x94,
0x80, 0x21, 0x0e, 0x0f, 0x78, 0x21, 0x94, 0x80,
0xf0, 0x0d, 0x22, 0x6f, 0x6c, 0x94, 0x80, 0x13,
0x0e, 0x80, 0xff, 0x09, 0x80, 0x04, 0x0d, 0x22,
0x80, 0x00, 0x6c, 0x21, 0x94, 0x80, 0xed, 0x0d,
0x22, 0x80, 0x01, 0x6c, 0x06, 0x80, 0x2f, 0x0a,
0x07, 0x80, 0x3a, 0x0b, 0x1c, 0x80, 0x10, 0x0d,
0x06, 0x80, 0x60, 0x0a, 0x07, 0x80, 0x67, 0x0b,
0x1c, 0x80, 0x08, 0x0d, 0x02, 0x80, 0xff, 0x6c,
0x80, 0x30, 0x19, 0x6c, 0x80, 0x57, 0x19, 0x6c,
0x27, 0x38, 0x24, 0xaf, 0x80, 0x00, 0x6f, 0x15,
0x21, 0xaa, 0x80, 0xf6, 0x0d, 0x22, 0x22, 0x6c,
0x26, 0x80, 0x03, 0x0e, 0x24, 0x39, 0x6c, 0x94,
0x80, 0x00, 0x09, 0x0c, 0x6c, 0x21, 0x94, 0x80,
0xfb, 0x0d, 0x6c, 0x80, 0xf1, 0x0e, 0x15, 0x6c,
0x26, 0x80, 0xe4, 0x0e, 0x38, 0x2f, 0x94, 0xef,
0x15, 0x61, 0x21, 0x94, 0x80, 0xf7, 0x0d, 0x22,
0x80, 0x00, 0x6f, 0x15, 0x6c, 0x2f, 0x94, 0xd4,
0x4f, 0x09, 0x80, 0x11, 0x0d, 0x94, 0xd4, 0x4f,
0x1d, 0x80, 0x05, 0x0d, 0x22, 0x62, 0x80, 0x01,
0x6c, 0x21, 0x61, 0x80, 0xe8, 0x0c, 0x22, 0x62,
0x80, 0x00, 0x6c, 0x04, 0x80, 0x00, 0x0e, 0x06,
0x80, 0x04, 0x1f, 0x80, 0x00, 0x0e, 0x80, 0x0f,
0x1c, 0x06, 0x80, 0x09, 0x0a, 0x80, 0x27, 0x1a,
0x18, 0x80, 0x30, 0x18, 0x80, 0x18, 0x17, 0x6c,
0xa0, 0x06, 0x25, 0x80, 0x13, 0x0e, 0x80, 0x10,
0x0e, 0xa0, 0x20, 0x18, 0x17, 0x80, 0x09, 0x0e,
0xa0, 0x0a, 0x18, 0x17, 0x6c, 0x2d, 0x2d, 0x20,
0x00, 0x94, 0x80, 0x18, 0x17, 0x21, 0x94, 0x80,
0xf7, 0x0d, 0x22, 0x6c, 0x4c, 0x49, 0x54, 0x49,
0x4e, 0x43, 0x50, 0x4f, 0x50, 0x4e, 0x49, 0x50,
0x53, 0x57, 0x50, 0x52, 0x4f, 0x54, 0x44, 0x55,
0x50, 0x4f, 0x56, 0x52, 0x45, 0x51, 0x55, 0x4e,
0x45, 0x51, 0x47, 0x54, 0x48, 0x4c, 0x54, 0x48,
0x4a, 0x4d, 0x50, 0x4a, 0x43, 0x4e, 0x4a, 0x53,
0x52, 0x53, 0x54, 0x48, 0x4c, 0x44, 0x5a, 0x53,
0x54, 0x5a, 0x4c, 0x44, 0x52, 0x53, 0x54, 0x52,
0x4c, 0x44, 0x41, 0x53, 0x54, 0x41, 0x44, 0x45,
0x49, 0x44, 0x45, 0x4f, 0x41, 0x44, 0x44, 0x53,
0x55, 0x42, 0x4d, 0x55, 0x4c, 0x44, 0x49, 0x56,
0x41, 0x4e, 0x44, 0x4f, 0x52, 0x41, 0x45, 0x4f,
0x52, 0x53, 0x46, 0x54, 0x42, 0x52, 0x4b, 0x68,
0x65, 0x78, 0x00, 0x6c, 0x69, 0x74, 0x00, 0x64,
0x75, 0x70, 0x00, 0x66, 0x61, 0x72, 0x00, 0x72,
0x65, 0x66, 0x00, 0x6b, 0x65, 0x79, 0x00, 0x45,
0x72, 0x72, 0x6f, 0x72, 0x20, 0x00, 0x4e, 0x75,
0x6d, 0x62, 0x65, 0x72, 0x00, 0x44, 0x75, 0x70,
0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x00, 0x4f,
0x75, 0x74, 0x2d, 0x6f, 0x66, 0x2d, 0x72, 0x61,
0x6e, 0x67, 0x65, 0x00, 0x52, 0x65, 0x66, 0x65,
0x72, 0x65, 0x6e, 0x63, 0x65, 0x00, 0x54, 0x6f,
0x6b, 0x65, 0x6e, 0x00, 0x45, 0x76, 0x61, 0x6c,
0x00, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e,
0x00, 0x55, 0x6e, 0x64, 0x65, 0x72, 0x66, 0x6c,
0x6f, 0x77, 0x00, 0x4f, 0x76, 0x65, 0x72, 0x66,
0x6c, 0x6f, 0x77, 0x00, 0x5a, 0x65, 0x72, 0x6f,
0x2d, 0x44, 0x69, 0x76, 0x69, 0x73, 0x69, 0x6f,
0x6e, 0x00, 0x7c, 0x03, 0xee, 0x24, 0x03, 0xf6,
0x40, 0x04, 0x02, 0x26, 0x04, 0x08, 0x2e, 0x04,
0x0e, 0x2c, 0x04, 0x0e, 0x3b, 0x04, 0x1b, 0x3a,
0x04, 0x29, 0x27, 0x04, 0x36, 0x22, 0x04, 0x3b,
0x5b, 0x04, 0x47, 0x5d, 0x04, 0x47, 0x23, 0x03,
0x75, 0x00, 0x00
]);
// var program = Uint8List.fromList(<int>[0x80, 0x41, 0x80, 0x18, 0x17]);
void main() async {
var emulator = Emu();
Stream<int> placeholder() async* {
yield 0;
}
;
Stream<int> stream =
emulator.uxn?.load(program).eval(0x0100) ?? placeholder();
run(stream);
}
Future<void> run(Stream<int> stream) async {
await for (final value in stream) {
// await Future.delayed(const Duration(milliseconds: 1000), () => "2");
}
}
class Stack {
Uxn u;
int addr, pk = 0;
Stack(this.u, this.addr);
int get(int index) {
return u.ram[this.addr + 0xff];
}
int ptr() {
return get(0xff);
}
int inc() {
// print("++stack inc");
return u.ram[this.addr + 0xff]++;
}
int dec() {
// print("--stack inc");
return u.rk != 0 ? --pk : --u.ram[addr + 0xff];
}
pop8() {
// print(" stack pop8");
// u.debugMem();
return ptr() == 0x00 ? u.halt(1) : u.ram[addr + dec()];
}
push8(int val) {
if (ptr() == 0xff) return u.halt(2);
// print(" stack push8");
// u.debugMem();
u.ram[addr + inc()] = val;
}
pop16() {
// print("> stack pop16");
// u.debugMem();
return pop8() + (pop8() << 8);
}
push16(int val) {
// print("> stack push16");
// u.debugMem();
push8(val >> 0x08);
push8(val & 0xff);
}
}
class Console {
Emu emu;
String buff = "";
Console(this.emu);
send(int val) {
if (val == 0x0a){
print(buff);
buff = "";
}else{
//print(val);
buff += (String.fromCharCode(val));
}
}
}
class Emu {
Uxn? uxn;
Console? stdio;
Emu() {
uxn = Uxn(this);
stdio = Console(this);
}
int dei(int port) {
return uxn?.getdev(port) ?? 0;
}
deo(int port, int val) {
uxn?.setdev(port, val);
switch (port) {
case 0x10:
case 0x11:
print("Set console vector");
break;
case 0x00:
case 0x01:
print("Set system vector");
break;
case 0x02:
uxn?.wst?.addr = val != 0 ? val * 0x100 : 0x10000;
break;
case 0x18:
//print(String.fromCharCode(val));
stdio?.send(val);
break;
case 0x0f:
print("Program ended.");
break;
default:
print("Unknown deo");
print(port);
print(val);
break;
}
}
}
class Uxn {
Uint8List ram = Uint8List(0x13000);
Stack? wst, rst, src, dst;
int dev = 0x12000;
Emu emu;
int r2 = 0, rr = 0, rk = 0;
Uxn(this.emu) {
wst = Stack(this, 0x10000);
rst = Stack(this, 0x11000);
}
int getdev(int port) => ram[dev + port];
setdev(int port, int val) => ram[dev + port] = val;
int pop() {
return r2 != 0 ? src?.pop16() : src?.pop8();
}
push8(int x) {
src?.push8(x);
}
push16(int x) {
src?.push16(x);
}
push(int val) {
if (r2 != 0)
push16(val);
else
push8(val);
}
int peek8(int addr) {
return ram[addr];
}
int peek16(int addr) {
return (ram[addr] << 8) + ram[addr + 1];
}
int peek(int addr) {
return r2 != 0 ? peek16(addr) : ram[addr];
}
poke8(int addr, int val) {
ram[addr] = val;
}
poke(int addr, int val) {
if (r2 != 0) {
ram[addr] = val >> 8;
ram[addr + 1] = val;
} else
ram[addr] = val;
}
int devr(int port) {
return r2 != 0 ? (emu.dei(port) << 8) + emu.dei(port + 1) : emu.dei(port);
}
devw(int port, val) {
if (r2 != 0) {
emu.deo(port, val >> 8);
emu.deo(port + 1, val & 0xff);
} else {
// print("DEO");
// print(port.toRadixString(16));
// print(val.toRadixString(16));
emu.deo(port, val);
}
}
int jump(int addr,int pc) {
// print("jump: ${addr.toRadixString(16)}, ${pc.toRadixString(16)}");
return r2 != 0 ? addr : pc + rel(addr);
}
int pc = 0;
Stream<int> eval(int ipc) async* {
pc = ipc;
print("start eval");
int a = 0, b = 0, c = 0, instr = 0;
while ((instr = ram[pc++]) != 0) {
// print("[ CYCLE START ] ${(pc-1).toRadixString(16)} ${instr.toRadixString(16)}");
// emu.onStep(pc, instr);
r2 = instr & 0x20;
rr = instr & 0x40;
rk = instr & 0x80;
if (rk != 0) {
wst?.pk = wst?.ptr() ?? 0;
rst?.pk = rst?.ptr() ?? 0;
}
if (rr != 0) {
// print("rst, wst switch ${(pc-1).toRadixString(16)}");
src = rst;
dst = wst;
} else {
src = wst;
dst = rst;
}
// print(
// ">>exec command [${(pc-1).toRadixString(16)}] ${(instr).toRadixString(16)} , type: ${(instr & 0x1f).toRadixString(16)}");
// yield 0;
switch (instr & 0x1f) {
// Stack
case 0x00:
// print(">>>LIT ${r2.toRadixString(16)}");
/* LIT */ push(peek(pc));
pc += (r2 != 0? 1: 0) + 1;
break;
case 0x01:
// print(">>>INC");
/* INC */ push(pop() + 1);
break;
case 0x02:
/* POP */ pop();
break;
case 0x03:
/* NIP */ a = pop();
pop();
push(a);
break;
case 0x04:
/* SWP */ a = pop();
b = pop();
push(a);
push(b);
break;
case 0x05:
/* ROT */ a = pop();
b = pop();
c = pop();
push(b);
push(a);
push(c);
break;
case 0x06:
/* DUP */ a = pop();
push(a);
push(a);
break;
case 0x07:
/* OVR */ a = pop();
b = pop();
push(b);
push(a);
push(b);
break;
// Logic
case 0x08:
/* EQU */ a = pop();
b = pop();
push8(b == a ? 1 : 0);
break;
case 0x09:
/* NEQ */ a = pop();
b = pop();
push8(b != a ? 1 : 0);
break;
case 0x0a:
/* GTH */ a = pop();
b = pop();
push8(b > a ? 1 : 0);
break;
case 0x0b:
/* LTH */ a = pop();
b = pop();
push8(b < a ? 1 : 0);
break;
case 0x0c:
/* JMP */ pc = jump(pop(), pc);
break;
case 0x0d:
// print(">>JCN");
/* JCN */ a = pop();
if (src?.pop8() != 0) pc = jump(a, pc);
// print("<<JCN");
break;
case 0x0e:
/* JSR */ dst?.push16(pc);
pc = jump(pop(), pc);
break;
case 0x0f:
/* STH */ if (r2 != 0) {
dst?.push16(src?.pop16());
} else {
dst?.push8(src?.pop8());
}
break;
// Memory
case 0x10:
/* LDZ */ push(peek(src?.pop8()));
break;
case 0x11:
/* STZ */ poke(src?.pop8(), pop());
break;
case 0x12:
/* LDR */ push(peek(pc + rel(src?.pop8())));
break;
case 0x13:
/* STR */ poke(pc + rel(src?.pop8()), pop());
break;
case 0x14:
/* LDA */ push(peek(src?.pop16()));
break;
case 0x15:
/* STA */ poke(src?.pop16(), pop());
break;
case 0x16:
/* DEI */ push(devr(src?.pop8()));
break;
case 0x17:
/* DEO */ devw(src?.pop8(), pop());
break;
// Arithmetic
case 0x18:
/* ADD */ a = pop();
b = pop();
push(b + a);
break;
case 0x19:
/* SUB */ a = pop();
b = pop();
push(b - a);
break;
case 0x1a:
/* MUL */ a = pop();
b = pop();
push(b * a);
break;
case 0x1b:
/* DIV */ a = pop();
b = pop();
// if (a == 0) return halt(3);
if (a == 0) halt(3);
push((b / a).round());
break;
case 0x1c:
/* AND */ a = pop();
b = pop();
push(b & a);
break;
case 0x1d:
/* ORA */ a = pop();
b = pop();
push(b | a);
break;
case 0x1e:
/* EOR */ a = pop();
b = pop();
push(b ^ a);
break;
case 0x1f:
/* SFT */ a = src?.pop8();
b = pop();
push(b >> (a & 0x0f) << ((a & 0xf0) >> 4));
break;
}
yield 0;
//debugMem();
// print("[ CYCLE DONE ]");
}
print(emu.stdio?.buff);
}
Uxn load(Uint8List program) {
for (var i = 0; i < program.length; i++) {
ram[0x100 + i] = program[i];
}
return this;
}
final errors = ["underflow", "overflow", "division by zero"];
halt(int err) {
// var vec = peek16()
print(
"Error ${(rr != 0 ? " Return-stack " : " Working-stack ")} ${errors[err]} at ${pc.toRadixString(16)} , command ${ram[pc - 1].toRadixString(16)}");
print(program[pc].toRadixString(16));
pc = 0x0000;
debugMem();
throw "halt";
// throw "Error " + (rr != 0 ? " Return-stack " : " Working-stack ") + errors[err];
}
debugMem() {
var result = "";
print("return stack: ");
for (int i = 0; i < 0x100; i++) {
if(ram[0x11000 + i] == 0){
result += ".";
continue;
}
result += (ram[0x11000 + i].toRadixString(16) + ", ");
}
print(result);
result = "";
print("working stack: ");
for (int i = 0; i < 0x100; i++) {
if(ram[0x11000 + i] == 0){
result += ".";
continue;
}
result += (ram[0x10000 + i].toRadixString(16) + ", ");
}
print(result);
print("");
}
int rel(val) {
return (val > 0x80 ? val - 256 : val);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment