From 91b95b03cf8d739ed6377060a11785c2436b0540 Mon Sep 17 00:00:00 2001 From: cheapie Date: Tue, 26 Jan 2021 15:44:07 -0600 Subject: [PATCH] Add RAM, EEPROM, and GPU --- README | 11 + gpu-font.lua | 1333 +++++++++++++++++++++++++++++ gpu.lua | 431 ++++++++++ gpu.txt | 121 +++ init.lua | 2 + memory.lua | 173 ++++ textures/digistuff_eeprom_top.png | Bin 0 -> 10605 bytes textures/digistuff_gpu_top.png | Bin 0 -> 10513 bytes textures/digistuff_ram_top.png | Bin 0 -> 10570 bytes 9 files changed, 2071 insertions(+) create mode 100644 gpu-font.lua create mode 100644 gpu.lua create mode 100644 gpu.txt create mode 100644 memory.lua create mode 100644 textures/digistuff_eeprom_top.png create mode 100644 textures/digistuff_gpu_top.png create mode 100644 textures/digistuff_ram_top.png diff --git a/README b/README index 37baa7f..efd7f67 100644 --- a/README +++ b/README @@ -90,3 +90,14 @@ In addition to right-clicking the controller in use to stop using it, the follow * The player leaves the game * The player is teleported away from the controller * The controller receives the string "release" on its digilines channel + +How to use the RAM and EEPROM chips: +First, set a channel. +Messages should consist of a table, with "command" set to either "read" or "write". "address" should be set to the number (0-31) of the 512-character block to read or write, and if writing then "data" should contain the data to write. +Example (to write - reading is similar, but with no data): + {command = "write",address = 7,data = "9a91a9e451b94dc262972557ab0d406f"} + +The RAM and EEPROM chips behave identically, except that the RAM chip loses its contents when dug whereas the EEPROM does not. + +How to use the 2D graphics processor: +Please see gpu.txt for information on this part. diff --git a/gpu-font.lua b/gpu-font.lua new file mode 100644 index 0000000..7feb154 --- /dev/null +++ b/gpu-font.lua @@ -0,0 +1,1333 @@ +local chars = { + [32] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [33] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, false,false,false,false,}, + {true, false,false,false,false,}, + {true, false,false,false,false,}, + {true, false,false,false,false,}, + {true, false,false,false,false,}, + {false,false,false,false,false,}, + {true, false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [34] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, false,true, false,false,}, + {true, false,true, false,false,}, + {true, false,true, false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [35] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,true, false,true, false,}, + {false,true, false,true, false,}, + {true, true, true, true, true, }, + {false,true, false,true, false,}, + {false,true, false,true, false,}, + {true, true, true, true, true, }, + {false,true, false,true, false,}, + {false,true, false,true, false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [36] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,true, false,false,}, + {false,true, true, true, false,}, + {true, false,false,false,false,}, + {false,true, true, false,false,}, + {false,false,false,true, false,}, + {true, false,false,true, false,}, + {false,true, true, false,false,}, + {false,false,true, false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [37] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, true, true, false,false,}, + {true, false,true, false,false,}, + {true, true, false,false,true, }, + {false,false,true, true, false,}, + {false,true, false,true, true, }, + {true, false,false,true, false,}, + {false,false,false,true, true, }, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [38] = { + {false,true, true, false,false,}, + {true, false,false,false,false,}, + {false,true, true, false,true, }, + {true, false,false,true, false,}, + {false,true, true, false,true, }, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [39] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, false,false,false,false,}, + {true, false,false,false,false,}, + {true, false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [40] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,true, false,false,}, + {false,true, false,false,false,}, + {false,true, false,false,false,}, + {true, false,false,false,false,}, + {true, false,false,false,false,}, + {true, false,false,false,false,}, + {false,true, false,false,false,}, + {false,true, false,false,false,}, + {false,false,true, false,false,}, + {false,false,false,false,false,}, + }, + [41] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, false,false,false,false,}, + {false,true, false,false,false,}, + {false,true, false,false,false,}, + {false,false,true, false,false,}, + {false,false,true, false,false,}, + {false,false,true, false,false,}, + {false,true, false,false,false,}, + {false,true, false,false,false,}, + {true, false,false,false,false,}, + {false,false,false,false,false,}, + }, + [42] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,true, false,false,}, + {true, true, false,true, true, }, + {false,false,true, false,false,}, + {false,true, false,true, false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [43] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,true, false,false,}, + {false,false,true, false,false,}, + {true, true, true, true, true, }, + {false,false,true, false,false,}, + {false,false,true, false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [44] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,true, false,false,false,}, + {false,true, false,false,false,}, + {true, false,false,false,false,}, + {false,false,false,false,false,}, + }, + [45] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, true, true, true, false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [46] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, false,false,false,false,}, + {true, false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [47] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,true, }, + {false,false,false,true, false,}, + {false,false,false,true, false,}, + {false,false,true, false,false,}, + {false,false,true, false,false,}, + {false,true, false,false,false,}, + {false,true, false,false,false,}, + {true, false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [48] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,true, true, false,false,}, + {true, false,false,true, false,}, + {true, false,false,true, false,}, + {true, false,false,true, false,}, + {true, false,false,true, false,}, + {true, false,false,true, false,}, + {false,true, true, false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [49] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,true, false,false,}, + {true, true, true, false,false,}, + {false,false,true, false,false,}, + {false,false,true, false,false,}, + {false,false,true, false,false,}, + {false,false,true, false,false,}, + {true, true, true, true, false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [50] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,true, true, false,false,}, + {true, false,false,true, false,}, + {false,false,false,true, false,}, + {false,false,true, false,false,}, + {false,true, false,false,false,}, + {true, false,false,false,false,}, + {true, true, true, true, false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [51] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,true, true, false,false,}, + {true, false,false,true, false,}, + {false,false,false,true, false,}, + {false,true, true, false,false,}, + {false,false,false,true, false,}, + {true, false,false,true, false,}, + {false,true, true, false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [52] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,true, false,}, + {false,false,true, true, false,}, + {false,true, false,true, false,}, + {true, false,false,true, false,}, + {true, true, true, true, true, }, + {false,false,false,true, false,}, + {false,false,false,true, false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [53] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, true, true, true, false,}, + {true, false,false,false,false,}, + {true, false,false,false,false,}, + {true, true, true, false,false,}, + {false,false,false,true, false,}, + {false,false,false,true, false,}, + {true, true, true, false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [54] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,true, true, true, false,}, + {true, false,false,false,false,}, + {true, false,false,false,false,}, + {true, true, true, false,false,}, + {true, false,false,true, false,}, + {true, false,false,true, false,}, + {false,true, true, false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [55] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, true, true, true, false,}, + {true, false,false,true, false,}, + {false,false,false,true, false,}, + {false,false,true, false,false,}, + {false,false,true, false,false,}, + {false,true, false,false,false,}, + {false,true, false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [56] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,true, true, false,false,}, + {true, false,false,true, false,}, + {true, false,false,true, false,}, + {false,true, true, false,false,}, + {true, false,false,true, false,}, + {true, false,false,true, false,}, + {false,true, true, false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [57] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,true, true, false,false,}, + {true, false,false,true, false,}, + {true, false,false,true, false,}, + {false,true, true, true, false,}, + {false,false,false,true, false,}, + {false,false,false,true, false,}, + {true, true, true, false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [58] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,true, false,false,false,}, + {false,true, false,false,false,}, + {false,true, false,false,false,}, + {false,true, false,false,false,}, + {false,true, false,false,false,}, + {false,true, false,false,false,}, + {false,true, false,false,false,}, + {true, false,false,false,false,}, + {false,false,false,false,false,}, + }, + [59] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,true, false,false,false,}, + {false,true, false,false,false,}, + {false,false,false,false,false,}, + {false,true, false,false,false,}, + {false,true, false,false,false,}, + {true, false,false,false,false,}, + {false,false,false,false,false,}, + }, + [60] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,true, false,false,}, + {false,true, false,false,false,}, + {true, false,false,false,false,}, + {false,true, false,false,false,}, + {false,false,true, false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [61] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, true, true, true, false,}, + {false,false,false,false,false,}, + {true, true, true, true, false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [62] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, false,false,false,false,}, + {false,true, false,false,false,}, + {false,false,true, false,false,}, + {false,true, false,false,false,}, + {true, false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [63] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,true, true, false,false,}, + {true, false,false,true, false,}, + {false,false,true, false,false,}, + {false,true, false,false,false,}, + {false,false,false,false,false,}, + {false,true, false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [64] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,true, true, true, }, + {false,true, false,false,false,}, + {true, false,false,true, true, }, + {true, false,true, false,true, }, + {true, false,true, false,true, }, + {true, false,false,true, true, }, + {false,true, false,false,false,}, + {false,false,true, true, true, }, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [65] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,true, true, true, false,}, + {false,false,true, false,true, }, + {false,true, false,false,true, }, + {false,true, true, true, true, }, + {false,true, false,false,true, }, + {true, true, false,false,true, }, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [66] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, true, true, true, false,}, + {false,true, false,false,true, }, + {false,true, true, true, false,}, + {false,true, false,false,true, }, + {false,true, false,false,true, }, + {true, true, true, true, false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [67] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,true, true, false,false,}, + {true, false,false,true, false,}, + {true, false,false,false,false,}, + {true, false,false,false,false,}, + {true, false,false,true, false,}, + {false,true, true, false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [68] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, true, true, true, false,}, + {false,true, false,false,true, }, + {false,true, false,false,true, }, + {false,true, false,false,true, }, + {false,true, false,false,true, }, + {true, true, true, true, false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [69] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, true, true, true, true, }, + {false,true, false,false,true, }, + {false,true, true, true, false,}, + {false,true, false,false,false,}, + {false,true, false,false,true, }, + {true, true, true, true, true, }, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [70] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, true, true, true, true, }, + {false,true, false,false,true, }, + {false,true, true, true, false,}, + {false,true, false,true, false,}, + {false,true, false,false,false,}, + {true, true, true, false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [71] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,true, true, false,false,}, + {true, false,false,true, false,}, + {true, false,false,false,false,}, + {true, false,true, true, false,}, + {true, false,false,true, false,}, + {false,true, true, false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [72] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, true, false,false,true, }, + {false,true, false,false,true, }, + {false,true, true, true, true, }, + {false,true, false,false,true, }, + {false,true, false,false,true, }, + {true, true, false,false,true, }, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [73] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, true, true, true, true, }, + {false,false,true, false,false,}, + {false,false,true, false,false,}, + {false,false,true, false,false,}, + {false,false,true, false,false,}, + {true, true, true, true, true, }, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [74] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,true, true, true, true, }, + {false,false,false,true, false,}, + {false,false,false,true, false,}, + {true, false,false,true, false,}, + {true, false,false,true, false,}, + {false,true, true, false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [75] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, true, false,true, true, }, + {false,true, false,true, false,}, + {false,true, true, false,false,}, + {false,true, false,true, false,}, + {false,true, false,false,true, }, + {true, true, true, false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [76] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, true, true, false,false,}, + {false,true, false,false,false,}, + {false,true, false,false,false,}, + {false,true, false,false,false,}, + {false,true, false,false,true, }, + {true, true, true, true, true, }, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [77] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, false,false,false,true, }, + {true, true, false,true, true, }, + {true, false,true, false,true, }, + {true, false,true, false,true, }, + {true, false,false,false,true, }, + {true, true, false,true, true, }, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [78] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, true, false,true, true, }, + {false,true, false,false,true, }, + {false,true, true, false,true, }, + {false,true, false,true, true, }, + {false,true, false,false,true, }, + {true, true, false,false,true, }, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [79] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,true, true, false,false,}, + {true, false,false,true, false,}, + {true, false,false,true, false,}, + {true, false,false,true, false,}, + {true, false,false,true, false,}, + {false,true, true, false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [80] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, true, true, true, false,}, + {false,true, false,false,true, }, + {false,true, false,false,true, }, + {false,true, true, true, false,}, + {false,true, false,false,false,}, + {true, true, true, false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [81] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,true, true, false,false,}, + {true, false,false,true, false,}, + {true, false,false,true, false,}, + {true, false,false,true, false,}, + {true, false,false,true, false,}, + {false,true, true, false,false,}, + {false,true, true, true, false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [82] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, true, true, true, false,}, + {false,true, false,false,true, }, + {false,true, false,false,true, }, + {false,true, true, true, false,}, + {false,true, false,false,true, }, + {true, true, true, false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [83] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,true, true, true, false,}, + {true, false,false,false,false,}, + {false,true, true, false,false,}, + {false,false,false,true, false,}, + {true, false,false,true, false,}, + {true, true, true, false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [84] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, true, true, true, true, }, + {true, false,true, false,true, }, + {false,false,true, false,false,}, + {false,false,true, false,false,}, + {false,false,true, false,false,}, + {false,true, true, true, false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [85] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, true, false,false,true, }, + {false,true, false,false,true, }, + {false,true, false,false,true, }, + {false,true, false,false,true, }, + {false,true, false,false,true, }, + {false,false,true, true, false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [86] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, true, false,true, true, }, + {true, false,false,false,true, }, + {false,true, false,true, false,}, + {false,true, false,true, false,}, + {false,true, false,true, false,}, + {false,false,true, false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [87] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, true, false,true, true, }, + {true, false,false,false,true, }, + {true, false,true, false,true, }, + {true, false,true, false,true, }, + {false,true, false,true, false,}, + {false,true, false,true, false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [88] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, true, false,true, true, }, + {false,true, false,true, false,}, + {false,false,true, false,false,}, + {false,false,true, false,false,}, + {false,true, false,true, false,}, + {true, true, false,true, true, }, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [89] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, true, false,true, true, }, + {true, false,false,false,true, }, + {false,true, false,true, false,}, + {false,false,true, false,false,}, + {false,false,true, false,false,}, + {false,true, true, true, false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [90] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, true, true, true, false,}, + {true, false,false,true, false,}, + {false,false,true, false,false,}, + {false,true, false,false,false,}, + {true, false,false,true, false,}, + {true, true, true, true, false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [91] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, true, false,false,false,}, + {true, false,false,false,false,}, + {true, false,false,false,false,}, + {true, false,false,false,false,}, + {true, false,false,false,false,}, + {true, false,false,false,false,}, + {true, false,false,false,false,}, + {true, false,false,false,false,}, + {true, true, false,false,false,}, + {false,false,false,false,false,}, + }, + [92] = { + {false,false,false,false,false,}, + {true, false,false,false,false,}, + {true, false,false,false,false,}, + {false,true, false,false,false,}, + {false,true, false,false,false,}, + {false,false,true, false,false,}, + {false,false,true, false,false,}, + {false,false,false,true, false,}, + {false,false,false,true, false,}, + {false,false,false,false,true, }, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [93] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, true, false,false,false,}, + {false,true, false,false,false,}, + {false,true, false,false,false,}, + {false,true, false,false,false,}, + {false,true, false,false,false,}, + {false,true, false,false,false,}, + {false,true, false,false,false,}, + {false,true, false,false,false,}, + {true, true, false,false,false,}, + {false,false,false,false,false,}, + }, + [94] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,true, false,false,}, + {false,true, false,true, false,}, + {true, false,false,false,true, }, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [95] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, true, true, true, true, }, + {false,false,false,false,false,}, + }, + [96] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, false,false,false,false,}, + {false,true, false,false,false,}, + {false,false,true, false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [97] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,true, true, false,false,}, + {false,false,false,true, false,}, + {false,true, true, true, false,}, + {true, false,false,true, false,}, + {false,true, true, false,true, }, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [98] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, true, false,false,false,}, + {false,true, false,false,false,}, + {false,true, true, true, false,}, + {false,true, false,false,true, }, + {false,true, false,false,true, }, + {false,true, false,false,true, }, + {true, true, true, true, false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [99] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,true, true, false,false,}, + {true, false,false,true, false,}, + {true, false,false,false,false,}, + {true, false,false,true, false,}, + {false,true, true, false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [100] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,true, true, false,}, + {false,false,false,true, false,}, + {false,true, true, true, false,}, + {true, false,false,true, false,}, + {true, false,false,true, false,}, + {true, false,false,true, false,}, + {false,true, true, false,true, }, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [101] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,true, true, false,false,}, + {true, false,false,true, false,}, + {true, true, true, false,false,}, + {true, false,false,true, false,}, + {false,true, true, false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [102] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,true, true, false,}, + {false,true, false,false,false,}, + {true, true, true, true, false,}, + {false,true, false,false,false,}, + {false,true, false,false,false,}, + {false,true, false,false,false,}, + {true, true, true, true, false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [103] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,true, true, false,true, }, + {true, false,false,true, false,}, + {true, false,false,true, false,}, + {true, false,false,true, false,}, + {false,true, true, true, false,}, + {false,false,false,true, false,}, + {true, true, true, false,false,}, + {false,false,false,false,false,}, + }, + [104] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, true, false,false,false,}, + {false,true, false,false,false,}, + {false,true, true, true, false,}, + {false,true, false,false,true, }, + {false,true, false,false,true, }, + {false,true, false,false,true, }, + {true, true, true, false,true, }, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [105] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,true, false,false,}, + {false,false,false,false,false,}, + {false,true, true, false,false,}, + {false,false,true, false,false,}, + {false,false,true, false,false,}, + {false,false,true, false,false,}, + {true, true, true, true, true, }, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [106] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,true, false,false,}, + {false,false,false,false,false,}, + {true, true, true, false,false,}, + {false,false,true, false,false,}, + {false,false,true, false,false,}, + {false,false,true, false,false,}, + {false,false,true, false,false,}, + {false,false,true, false,false,}, + {true, true, false,false,false,}, + {false,false,false,false,false,}, + }, + [107] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, true, false,false,false,}, + {false,true, false,false,false,}, + {false,true, false,true, true, }, + {false,true, false,true, false,}, + {false,true, true, false,false,}, + {false,true, false,true, false,}, + {true, true, false,true, true, }, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [108] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,true, true, false,false,}, + {false,false,true, false,false,}, + {false,false,true, false,false,}, + {false,false,true, false,false,}, + {false,false,true, false,false,}, + {false,false,true, false,false,}, + {true, true, true, true, true, }, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [109] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, true, false,true, false,}, + {true, false,true, false,true, }, + {true, false,true, false,true, }, + {true, false,true, false,true, }, + {true, false,true, false,true, }, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [110] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, false,true, true, false,}, + {false,true, false,false,true, }, + {false,true, false,false,true, }, + {false,true, false,false,true, }, + {true, true, true, false,true, }, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [111] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,true, true, false,false,}, + {true, false,false,true, false,}, + {true, false,false,true, false,}, + {true, false,false,true, false,}, + {false,true, true, false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [112] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, false,true, true, false,}, + {false,true, false,false,true, }, + {false,true, false,false,true, }, + {false,true, false,false,true, }, + {false,true, true, true, false,}, + {false,true, false,false,false,}, + {true, true, true, true, false,}, + {false,false,false,false,false,}, + }, + [113] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,true, true, false,true, }, + {true, false,false,true, false,}, + {true, false,false,true, false,}, + {true, false,false,true, false,}, + {false,true, true, true, false,}, + {false,false,false,true, false,}, + {false,false,true, true, true, }, + {false,false,false,false,false,}, + }, + [114] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, false,true, true, true, }, + {false,true, false,false,false,}, + {false,true, false,false,false,}, + {false,true, false,false,false,}, + {true, true, true, true, false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [115] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,true, true, true, false,}, + {true, false,false,false,false,}, + {false,true, true, false,false,}, + {false,false,false,true, false,}, + {true, true, true, false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [116] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,true, false,false,false,}, + {false,true, false,false,false,}, + {true, true, true, true, false,}, + {false,true, false,false,false,}, + {false,true, false,false,false,}, + {false,true, false,false,true, }, + {false,false,true, true, false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [117] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, true, false,true, true, }, + {false,true, false,false,true, }, + {false,true, false,false,true, }, + {false,true, false,false,true, }, + {false,false,true, true, false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [118] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, true, false,false,true, }, + {false,true, false,false,false,}, + {false,false,true, false,true, }, + {false,false,true, false,true, }, + {false,false,false,true, false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [119] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, false,true, false,true, }, + {true, false,true, false,true, }, + {true, false,true, false,true, }, + {false,true, false,true, false,}, + {false,true, false,true, false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [120] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, true, false,true, true, }, + {false,true, false,true, false,}, + {false,false,true, false,false,}, + {false,true, false,true, false,}, + {true, true, false,true, true, }, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [121] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, true, false,true, true, }, + {false,true, false,false,true, }, + {false,true, false,false,true, }, + {false,true, false,false,true, }, + {false,false,true, true, false,}, + {false,false,true, false,false,}, + {true, true, false,false,false,}, + {false,false,false,false,false,}, + }, + [122] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, true, true, true, false,}, + {false,false,true, false,false,}, + {false,true, false,false,false,}, + {true, false,false,true, false,}, + {true, true, true, true, false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, + [123] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,true, false,false,}, + {false,true, false,false,false,}, + {false,true, false,false,false,}, + {false,true, false,false,false,}, + {true, false,false,false,false,}, + {false,true, false,false,false,}, + {false,true, false,false,false,}, + {false,true, false,false,false,}, + {false,false,true, false,false,}, + {false,false,false,false,false,}, + }, + [124] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, false,false,false,false,}, + {true, false,false,false,false,}, + {true, false,false,false,false,}, + {true, false,false,false,false,}, + {true, false,false,false,false,}, + {true, false,false,false,false,}, + {true, false,false,false,false,}, + {true, false,false,false,false,}, + {true, false,false,false,false,}, + {false,false,false,false,false,}, + }, + [125] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {true, false,false,false,false,}, + {false,true, false,false,false,}, + {false,true, false,false,false,}, + {false,true, false,false,false,}, + {false,false,true, false,false,}, + {false,true, false,false,false,}, + {false,true, false,false,false,}, + {false,true, false,false,false,}, + {true, false,false,false,false,}, + {false,false,false,false,false,}, + }, + [126] = { + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,true, false,true, false,}, + {true, false,true, false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + {false,false,false,false,false,}, + }, +} +return chars diff --git a/gpu.lua b/gpu.lua new file mode 100644 index 0000000..cf75a05 --- /dev/null +++ b/gpu.lua @@ -0,0 +1,431 @@ +local font = dofile(minetest.get_modpath("digistuff")..DIR_DELIM.."gpu-font.lua") + +local function explodebits(input) + local output = {} + for i=0,7,1 do + output[i] = input%(2^(i+1)) >= 2^i + end + return output +end + +local function implodebits(input) + local output = 0 + for i=0,7,1 do + output = output + (input[i] and 2^i or 0) + end + return output +end + +local function tohsv(r,g,b) + r = r/255 + g = g/255 + b = b/255 + max = math.max(r,g,b) + min = math.min(r,g,b) + delta = max-min + local hue = 0 + if delta > 0 then + if max == r then + hue = (g-b)/delta + hue = (hue%6)*60 + elseif max == g then + hue = (b-r)/delta + hue = 60*(hue+2) + elseif max == b then + hue = (r-g)/delta + hue = 60*(hue+4) + end + hue = hue/360 + end + local sat = 0 + if max > 0 then + sat = delta/max + end + return math.floor(hue*255),math.floor(sat*255),math.floor(max*255) +end + +local function torgb(h,s,v) + h = h/255*360 + s = s/255 + v = v/255 + local c = s*v + local x = (h/60)%2 + x = 1-math.abs(x-1) + x = x*c + local m = v-c + local r = 0 + local g = 0 + local b = 0 + if h < 60 then + r = c + g = x + elseif h < 120 then + r = x + g = c + elseif h < 180 then + g = c + b = x + elseif h < 240 then + g = x + b = c + elseif h < 300 then + r = x + b = c + else + r = c + b = x + end + r = r+m + g = g+m + b = b+m + return math.floor(r*255),math.floor(g*255),math.floor(b*255) +end + +local function bitwiseblend(srcr,dstr,srcg,dstg,srcb,dstb,mode) + local srbits = explodebits(srcr) + local sgbits = explodebits(srcg) + local sbbits = explodebits(srcb) + local drbits = explodebits(dstr) + local dgbits = explodebits(dstg) + local dbbits = explodebits(dstb) + for i=0,7,1 do + if mode == "and" then + drbits[i] = srbits[i] and drbits[i] + dgbits[i] = sgbits[i] and dgbits[i] + dbbits[i] = sbbits[i] and dbbits[i] + elseif mode == "or" then + drbits[i] = srbits[i] or drbits[i] + dgbits[i] = sgbits[i] or dgbits[i] + dbbits[i] = sbbits[i] or dbbits[i] + elseif mode == "xor" then + drbits[i] = srbits[i] ~= drbits[i] + dgbits[i] = sgbits[i] ~= dgbits[i] + dbbits[i] = sbbits[i] ~= dbbits[i] + elseif mode == "xnor" then + drbits[i] = srbits[i] == drbits[i] + dgbits[i] = sgbits[i] == dgbits[i] + dbbits[i] = sbbits[i] == dbbits[i] + elseif mode == "not" then + drbits[i] = not srbits[i] + dgbits[i] = not sgbits[i] + dbbits[i] = not sbbits[i] + elseif mode == "nand" then + drbits[i] = not (srbits[i] and drbits[i]) + dgbits[i] = not (sgbits[i] and dgbits[i]) + dbbits[i] = not (sbbits[i] and dbbits[i]) + elseif mode == "nor" then + drbits[i] = not (srbits[i] or drbits[i]) + dgbits[i] = not (sgbits[i] or dgbits[i]) + dbbits[i] = not (sbbits[i] or dbbits[i]) + end + end + return string.format("%02X%02X%02X",implodebits(drbits),implodebits(dgbits),implodebits(dbbits)) +end + +local function blend(src,dst,mode,transparent) + local srcr = tonumber(string.sub(src,1,2),16) + local srcg = tonumber(string.sub(src,3,4),16) + local srcb = tonumber(string.sub(src,5,6),16) + local dstr = tonumber(string.sub(dst,1,2),16) + local dstg = tonumber(string.sub(dst,3,4),16) + local dstb = tonumber(string.sub(dst,5,6),16) + local op = "normal" + if type(mode) == "string" then op = string.lower(mode) end + if op == "normal" then + return src + elseif op == "nop" then + return dst + elseif op == "overlay" then + return (string.upper(src) == string.upper(transparent)) and dst or src + elseif op == "add" then + local r = math.min(255,srcr+dstr) + local g = math.min(255,srcg+dstg) + local b = math.min(255,srcb+dstb) + return string.format("%02X%02X%02X",r,g,b) + elseif op == "sub" then + local r = math.max(0,dstr-srcr) + local g = math.max(0,dstg-srcg) + local b = math.max(0,dstb-srcb) + return string.format("%02X%02X%02X",r,g,b) + elseif op == "isub" then + local r = math.max(0,srcr-dstr) + local g = math.max(0,srcg-dstg) + local b = math.max(0,srcb-dstb) + return string.format("%02X%02X%02X",r,g,b) + elseif op == "average" then + local r = math.min(255,(srcr+dstr)/2) + local g = math.min(255,(srcg+dstg)/2) + local b = math.min(255,(srcb+dstb)/2) + return string.format("%02X%02X%02X",r,g,b) + elseif op == "and" or op == "or" or op == "xor" or op == "xnor" or op == "not" or op == "nand" or op == "nor" then + return bitwiseblend(srcr,dstr,srcg,dstg,srcb,dstb,op) + elseif op == "tohsv" then + return string.format("%02X%02X%02X",tohsv(srcr,srcg,srcb)) + elseif op == "torgb" then + return string.format("%02X%02X%02X",torgb(srcr,srcg,srcb)) + else + return src + end +end + +local function runcommand(pos,meta,command) + if type(command) ~= "table" then return end + if command.command == "createbuffer" then + if type(command.buffer) ~= "number" or type(command.xsize) ~= "number" or type(command.ysize) ~= "number" then return end + local bufnum = math.floor(command.buffer) + if bufnum < 0 or bufnum > 7 then return end + local xsize = math.min(64,math.floor(command.xsize)) + local ysize = math.min(64,math.floor(command.ysize)) + if xsize < 1 or ysize < 1 then return end + local fillcolor = command.fill + if type(fillcolor) ~= "string" or string.len(fillcolor) > 7 or string.len(fillcolor) < 6 then fillcolor = "000000" end + if string.sub(fillcolor,1,1) == "#" then fillcolor = string.sub(fillcolor,2,7) end + if not tonumber(fillcolor,16) then fillcolor = "000000" end + local buffer = {} + buffer.xsize = xsize + buffer.ysize = ysize + for y=1,ysize,1 do + buffer[y] = {} + for x=1,xsize,1 do + buffer[y][x] = fillcolor + end + end + meta:set_string("buffer"..bufnum,minetest.serialize(buffer)) + elseif command.command == "send" then + if type(command.buffer) ~= "number" or type(command.channel) ~= "string" then return end + local bufnum = math.floor(command.buffer) + if bufnum < 0 or bufnum > 7 then return end + local buffer = meta:get_string("buffer"..bufnum) + if string.len(buffer) == 0 then return end + buffer = minetest.deserialize(buffer) + if type(buffer) == "table" then + digiline:receptor_send(pos,digiline.rules.default,command.channel,buffer) + end + elseif command.command == "drawrect" then + if type(command.buffer) ~= "number" or type(command.x1) ~= "number" or type(command.y1) ~= "number" or type(command.x2) ~= "number" or type(command.y2) ~= "number" then return end + local bufnum = math.floor(command.buffer) + if bufnum < 0 or bufnum > 7 then return end + local x1 = math.min(64,math.floor(command.x1)) + local y1 = math.min(64,math.floor(command.y1)) + local x2 = math.min(64,math.floor(command.x2)) + local y2 = math.min(64,math.floor(command.y2)) + if x1 < 1 or y1 < 1 or x2 < 1 or y2 < 1 then return end + local buffer = meta:get_string("buffer"..bufnum) + if string.len(buffer) == 0 then return end + buffer = minetest.deserialize(buffer) + if type(buffer) ~= "table" then return end + x2 = math.min(x2,buffer.xsize) + y2 = math.min(y2,buffer.ysize) + if x1 > x2 or y1 > y2 then return end + local fillcolor = command.fill + if type(fillcolor) ~= "string" or string.len(fillcolor) > 7 or string.len(fillcolor) < 6 then fillcolor = "000000" end + if string.sub(fillcolor,1,1) == "#" then fillcolor = string.sub(fillcolor,2,7) end + if not tonumber(fillcolor,16) then fillcolor = "000000" end + local edgecolor = command.edge + if type(edgecolor) ~= "string" or string.len(edgecolor) > 7 or string.len(edgecolor) < 6 then edgecolor = fillcolor end + if string.sub(edgecolor,1,1) == "#" then edgecolor = string.sub(edgecolor,2,7) end + if not tonumber(edgecolor,16) then edgecolor = fillcolor end + for y=y1,y2,1 do + for x=x1,x2,1 do + buffer[y][x] = fillcolor + end + end + if fillcolor ~= edgecolor then + for x=x1,x2,1 do + buffer[y1][x] = edgecolor + buffer[y2][x] = edgecolor + end + for y=y1,y2,1 do + buffer[y][x1] = edgecolor + buffer[y][x2] = edgecolor + end + end + meta:set_string("buffer"..bufnum,minetest.serialize(buffer)) + elseif command.command == "drawpoint" then + if type(command.buffer) ~= "number" or type(command.x) ~= "number" or type(command.y) ~= "number" then return end + local bufnum = math.floor(command.buffer) + if bufnum < 0 or bufnum > 7 then return end + local x = math.floor(command.x) + local y = math.floor(command.y) + if x < 1 or y < 1 then return end + local buffer = meta:get_string("buffer"..bufnum) + if string.len(buffer) == 0 then return end + buffer = minetest.deserialize(buffer) + if type(buffer) ~= "table" then return end + if x > buffer.xsize or y > buffer.ysize then return end + local color = command.color + if type(color) ~= "string" or string.len(color) > 7 or string.len(color) < 6 then color = "000000" end + if string.sub(color,1,1) == "#" then color = string.sub(color,2,7) end + if not tonumber(color,16) then color = "000000" end + buffer[y][x] = color + meta:set_string("buffer"..bufnum,minetest.serialize(buffer)) + elseif command.command == "copy" then + if type(command.src) ~= "number" or type(command.dst) ~= "number" or type(command.srcx) ~= "number" or type(command.srcy) ~= "number" or type(command.dstx) ~= "number" or type(command.dsty) ~= "number" or type(command.xsize) ~= "number" or type(command.ysize) ~= "number" then return end + local src = math.floor(command.src) + if src < 0 or src > 7 then return end + local dst = math.floor(command.dst) + if dst < 0 or dst > 7 then return end + local srcx = math.floor(command.srcx) + local srcy = math.floor(command.srcy) + local dstx = math.floor(command.dstx) + local dsty = math.floor(command.dsty) + local xsize = math.floor(command.xsize) + local ysize = math.floor(command.ysize) + if srcx < 1 or srcy < 1 or dstx < 1 or dsty < 1 or xsize < 1 or ysize < 1 then return end + local sourcebuffer = meta:get_string("buffer"..src) + local destbuffer = meta:get_string("buffer"..dst) + if string.len(sourcebuffer) == 0 then return end + sourcebuffer = minetest.deserialize(sourcebuffer) + if type(sourcebuffer) ~= "table" then return end + if string.len(destbuffer) == 0 then return end + destbuffer = minetest.deserialize(destbuffer) + if type(destbuffer) ~= "table" then return end + if srcx + xsize-1 > sourcebuffer.xsize or srcy + ysize-1 > sourcebuffer.ysize then return end + if dstx + xsize-1 > destbuffer.xsize or dsty + ysize-1 > destbuffer.ysize then return end + local transparent = command.transparent + if type(transparent) ~= "string" or string.len(transparent) > 7 or string.len(transparent) < 6 then transparent = "000000" end + if string.sub(transparent,1,1) == "#" then transparent = string.sub(transparent,2,7) end + if not tonumber(transparent,16) then transparent = "000000" end + for y=0,xsize-1,1 do + for x=0,xsize-1,1 do + local srcpx = sourcebuffer[srcy+y][srcx+x] + local destpx = destbuffer[dsty+y][dstx+x] + destbuffer[dsty+y][dstx+x] = blend(srcpx,destpx,command.mode,transparent) + end + end + meta:set_string("buffer"..dst,minetest.serialize(destbuffer)) + elseif command.command == "load" then + if type(command.buffer) ~= "number" or type(command.x) ~= "number" or type(command.y) ~= "number" or type(command.data) ~= "table" then return end + local bufnum = math.floor(command.buffer) + if bufnum < 0 or bufnum > 7 then return end + local xstart = math.floor(command.x) + local ystart = math.floor(command.y) + if xstart < 1 or ystart < 1 then return end + local buffer = meta:get_string("buffer"..bufnum) + if string.len(buffer) == 0 then return end + buffer = minetest.deserialize(buffer) + if type(buffer) ~= "table" then return end + if type(command.data[1]) ~= "table" then return end + if #command.data[1] < 1 then return end + local ysize = #command.data + local xsize = #command.data[1] + if xstart+xsize > buffer.xsize or ystart+ysize > buffer.ysize then return end + for y=1,ysize,1 do + if type(command.data[y]) == "table" then + for x=1,xsize,1 do + local color = command.data[y][x] + if type(color) == "string" then + if string.len(color) == 7 then color = string.sub(color,2,7) end + if tonumber(color,16) then + buffer[ystart+y-1][xstart+x-1] = color + end + end + end + end + end + meta:set_string("buffer"..bufnum,minetest.serialize(buffer)) + elseif command.command == "text" then + if type(command.buffer) ~= "number" or type(command.x) ~= "number" or type(command.y) ~= "number" or type(command.text) ~= "string" or string.len(command.text) < 1 then return end + command.text = string.sub(command.text,1,16) + local bufnum = math.floor(command.buffer) + if bufnum < 0 or bufnum > 7 then return end + local x = math.floor(command.x) + local y = math.floor(command.y) + if x < 1 or y < 1 then return end + local buffer = meta:get_string("buffer"..bufnum) + if string.len(buffer) == 0 then return end + buffer = minetest.deserialize(buffer) + if type(buffer) ~= "table" then return end + if x > buffer.xsize or y > buffer.ysize then return end + local color = command.color + if type(color) ~= "string" or string.len(color) > 7 or string.len(color) < 6 then color = "ff6600" end + if string.sub(color,1,1) == "#" then color = string.sub(color,2,7) end + if not tonumber(color,16) then color = "ff6600" end + for i=1,string.len(command.text),1 do + local char = font[string.byte(string.sub(command.text,i,i))] + for chary=1,12,1 do + for charx=1,5,1 do + local startx = x + (i*6-6) + if char[chary][charx] and y+chary-1 <= buffer.ysize and startx+charx-1 <= buffer.xsize then + local dstpx = buffer[y+chary-1][startx+charx-1] + buffer[y+chary-1][startx+charx-1] = blend(color,dstpx,command.mode,"") + end + end + end + end + meta:set_string("buffer"..bufnum,minetest.serialize(buffer)) + end +end + +minetest.register_node("digistuff:gpu", { + description = "Digilines 2D Graphics Processor", + groups = {cracky=3}, + on_construct = function(pos) + local meta = minetest.get_meta(pos) + meta:set_string("formspec","field[channel;Channel;${channel}") + end, + tiles = { + "digistuff_gpu_top.png", + "jeija_microcontroller_bottom.png", + "jeija_microcontroller_sides.png", + "jeija_microcontroller_sides.png", + "jeija_microcontroller_sides.png", + "jeija_microcontroller_sides.png" + }, + inventory_image = "digistuff_gpu_top.png", + drawtype = "nodebox", + selection_box = { + --From luacontroller + type = "fixed", + fixed = { -8/16, -8/16, -8/16, 8/16, -5/16, 8/16 }, + }, + _digistuff_channelcopier_fieldname = "channel", + node_box = { + --From Luacontroller + type = "fixed", + fixed = { + {-8/16, -8/16, -8/16, 8/16, -7/16, 8/16}, -- Bottom slab + {-5/16, -7/16, -5/16, 5/16, -6/16, 5/16}, -- Circuit board + {-3/16, -6/16, -3/16, 3/16, -5/16, 3/16}, -- IC + } + }, + paramtype = "light", + sunlight_propagates = true, + on_receive_fields = function(pos, formname, fields, sender) + local name = sender:get_player_name() + if minetest.is_protected(pos,name) and not minetest.check_player_privs(name,{protection_bypass=true}) then + minetest.record_protection_violation(pos,name) + return + end + local meta = minetest.get_meta(pos) + if fields.channel then meta:set_string("channel",fields.channel) end + end, + digiline = + { + receptor = {}, + effector = { + action = function(pos,node,channel,msg) + local meta = minetest.get_meta(pos) + if meta:get_string("channel") ~= channel or type(msg) ~= "table" then return end + if type(msg[1]) == "table" then + for i=1,32,1 do + if type(msg[i]) == "table" then + runcommand(pos,meta,msg[i]) + end + end + else + runcommand(pos,meta,msg) + end + end + }, + }, +}) + +minetest.register_craft({ + output = "digistuff:gpu", + recipe = { + {"","default:steel_ingot",""}, + {"digilines:wire_std_00000000","mesecons_luacontroller:luacontroller0000","digilines:wire_std_00000000"}, + {"dye:red","dye:green","dye:blue"}, + } +}) diff --git a/gpu.txt b/gpu.txt new file mode 100644 index 0000000..7fccdbd --- /dev/null +++ b/gpu.txt @@ -0,0 +1,121 @@ +Digilines 2D Graphics Processor +=============================== + +Commands for this part are in the form of a table, consisting of a field called "command" with the command to be executed, and other fields supplying parameters to the command. +Example: + {command="send",buffer=0,channel="example"} + +Up to 32 commands may be sent at once by placing all of the tables into one. +Example: + { + {command="createbuffer",buffer=0,xsize=16,ysize=16,color="aaaaaa"}, + {command="send",buffer=0,channel="example"} + } + + +Command: createbuffer +--------------------- + +Creates a new buffer. Up to 8 buffers may exist at one time, and each can be up to 64x64 pixels in size. + +Parameters: +buffer [integer 0-7]: The slot number to create the new buffer in. If the slot is already occupied, the existing contents will be erased. +xsize [integer 1-64]: The width of the new buffer in pixels. +ysize [integer 1-64]: The height of the new buffer in pixels. +color [hex color, default "000000"]: A color to fill the new buffer with. + +Command: send +------------- + +Sends the contents of a buffer to a digiscreen, rgblightstone panel, or other digilines device. + +Parameters: +buffer [integer 0-7]: The buffer to send the contents of. +channel [string]: The digilines channel to send the message on. + +Command: drawrect +----------------- + +Draws a rectangle with optional border on a buffer. + +Parameters: +buffer [integer 0-7]: The buffer to draw the rectangle on. +x1 [integer 1-64]: The X position of the left side of the rectangle. +x2 [integer 1-64]: The X position of the right side of the rectangle. +y1 [integer 1-64]: The Y position of the top side of the rectangle. +y2 [integer 1-64]: The Y position of the bottom side of the rectangle. +fill [hex color, default "000000"]: The color of the rectangle. +edge [hex color, default same as fill]: The color of the outside edge of the rectangle. + +Command: drawpoint +------------------ + +Draws a point on a buffer. +This command is intended for use when writing a single pixel at a time. +For writing large blocks at one time, it is recommended to use the "load" command instead. + +Parameters: +buffer [integer 0-7]: The buffer to draw the point on. +x [integer 1-64]: The X position of the point. +y [integer 1-64]: The Y position of the point. +color [hex color, default "000000"]: The color of the point. + +Command: copy +------------- + +Perform a BitBLT operation (such as copying one buffer to another). + +Parameters: +src [integer 0-7]: The buffer to copy from. +dst [integer 0-7]: The buffer to copy to. May be the same or different from "src". +srcx [integer 1-64]: The X position of the left side of the region to copy from. +srcy [integer 1-64]: The Y position of the top side of the region to copy from. +dstx [integer 1-64]: The X position of the left side of the region to copy to. +dsty [integer 1-64]: The Y position of the top side of the region to copy to. +xsize [integer 1-64]: The width of the region to copy. +ysize [integer 1-64]: The height of the region to copy. +mode [string from list below, default "normal"]: The blend mode to use for the copy operation. +transparent [hex color, default "000000"]: The color to treat as transparency when using the "overlay" blend mode. No effect in other modes. + +Blend modes: +normal: Copy the source to the destination, overwriting the destination. +nop: Do nothing. +overlay: Same as normal, but skip pixels in the source matching the "transparent" color. +add: For each subpixel (red, green, blue) add the source values to the destination and write the sum to the destination. +sub: For each subpixel (red, green, blue) subtract the source values from the destination and write the difference to the destination. +isub: For each subpixel (red, green, blue) subtract the destination values from the source and write the difference to the destination. +average: For each subpixel (red, green, blue) calculate the average of the source and destination and write the average to the destination. +and: Perform a bitwise AND of the source and destination and write the result to the destination. +or: Perform a bitwise OR of the source and destination and write the result to the destination. +nand: Perform a bitwise NAND of the source and destination and write the result to the destination. +nor: Perform a bitwise NOR of the source and destination and write the result to the destination. +xor: Perform a bitwise XOR of the source and destination and write the result to the destination. +xnor: Perform a bitwise XNOR of the source and destination and write the result to the destination. +not: Perform a bitwise NOT of the source and write the result to the destination. +tohsv: Convert the source from the RGB color system to the HSV color system and write the result to the destination, storing hue as "red", saturation as "green", and value as "blue". +torgb: Convert the source from the HSV color system to the RGB color system, reading hue from the red channel, saturation from the green channel, and value from the blue channel, and write the result to the destination. + +Command: load +------------- + +Transfer a bitmap image into a buffer. +The width and height of the image will be automatically determined from the data given. + +Parameters: +buffer [integer 0-7]: The buffer to write the image into. +x [integer 1-64]: The X position of the left side of the image. +y [integer 1-64]: The Y position of the top side of the image. +data [2D array of hex color values, default for each is transparency]: The bitmap image to write. + +Command: text +------------- + +Draw one or more text characters on a buffer. +The font being used is 5*12 pixels in size, with one pixel spacing between characters. + +Parameters: +buffer [integer 0-7]: The buffer to draw the text on. +x [integer 1-64]: The X position of the left side of the text. +y [integer 1-64]: The Y position of the right side of the text. +color [hex color, default "ff6600"]: The color of the text. +text: The text string to draw. diff --git a/init.lua b/init.lua index 8c772fd..77d8e8a 100644 --- a/init.lua +++ b/init.lua @@ -16,6 +16,8 @@ local components = { "cardreader", "channelcopier", "controller", + "memory", + "gpu", } if minetest.get_modpath("mesecons_luacontroller") then table.insert(components,"ioexpander") end diff --git a/memory.lua b/memory.lua new file mode 100644 index 0000000..8ceada8 --- /dev/null +++ b/memory.lua @@ -0,0 +1,173 @@ +minetest.register_node("digistuff:ram", { + description = "Digilines 128Kbit SRAM", + groups = {cracky=3}, + on_construct = function(pos) + local meta = minetest.get_meta(pos) + meta:set_string("formspec","field[channel;Channel;${channel}") + for i=0,31,1 do + meta:set_string(string.format("data%02d",i),"") + end + end, + tiles = { + "digistuff_ram_top.png", + "jeija_microcontroller_bottom.png", + "jeija_microcontroller_sides.png", + "jeija_microcontroller_sides.png", + "jeija_microcontroller_sides.png", + "jeija_microcontroller_sides.png" + }, + inventory_image = "digistuff_ram_top.png", + drawtype = "nodebox", + selection_box = { + --From luacontroller + type = "fixed", + fixed = { -8/16, -8/16, -8/16, 8/16, -5/16, 8/16 }, + }, + _digistuff_channelcopier_fieldname = "channel", + node_box = { + --From Luacontroller + type = "fixed", + fixed = { + {-8/16, -8/16, -8/16, 8/16, -7/16, 8/16}, -- Bottom slab + {-5/16, -7/16, -5/16, 5/16, -6/16, 5/16}, -- Circuit board + {-3/16, -6/16, -3/16, 3/16, -5/16, 3/16}, -- IC + } + }, + paramtype = "light", + sunlight_propagates = true, + on_receive_fields = function(pos, formname, fields, sender) + local name = sender:get_player_name() + if minetest.is_protected(pos,name) and not minetest.check_player_privs(name,{protection_bypass=true}) then + minetest.record_protection_violation(pos,name) + return + end + local meta = minetest.get_meta(pos) + if fields.channel then meta:set_string("channel",fields.channel) end + end, + digiline = + { + receptor = {}, + effector = { + action = function(pos,node,channel,msg) + local meta = minetest.get_meta(pos) + if meta:get_string("channel") ~= channel or type(msg) ~= "table" then return end + if msg.command == "read" then + if type(msg.address) == "number" and msg.address >= 0 and msg.address <= 31 then + digiline:receptor_send(pos,digiline.rules.default,channel,meta:get_string(string.format("data%02i",math.floor(msg.address)))) + end + elseif msg.command == "write" then + if type(msg.address) == "number" and msg.address >= 0 and msg.address <= 31 and type(msg.data) == "string" then + meta:set_string(string.format("data%02i",math.floor(msg.address)),string.sub(msg.data,1,512)) + end + end + end + }, + }, +}) + +minetest.register_node("digistuff:eeprom", { + description = "Digilines 128Kbit EEPROM", + groups = {cracky=3}, + stack_max = 1, + after_place_node = function(pos,_,istack) + local meta = minetest.get_meta(pos) + local smeta = istack:get_meta() + for i=0,31,1 do + meta:set_string(string.format("data%02d",i),smeta:get_string(string.format("data%02d",i))) + end + meta:set_string("channel",smeta:get_string("channel")) + meta:set_string("formspec","field[channel;Channel;${channel}") + end, + on_dig = function(pos,node,player) + local name = player:get_player_name() + if minetest.is_protected(pos,name) and not minetest.check_player_privs(name,{protection_bypass=true}) then + minetest.record_protection_violation(pos,name) + return + end + local meta = minetest.get_meta(pos) + local istack = ItemStack("digistuff:eeprom") + local smeta = istack:get_meta() + for i=0,31,1 do + smeta:set_string(string.format("data%02d",i),meta:get_string(string.format("data%02d",i))) + end + smeta:set_string("channel",meta:get_string("channel")) + minetest.remove_node(pos) + smeta:set_string("description","Digilines 128KBit EEPROM (with data)") + local inv = minetest.get_inventory({type = "player",name = name,}) + inv:add_item("main",istack) + digilines.update_autoconnect(pos) + end, + tiles = { + "digistuff_eeprom_top.png", + "jeija_microcontroller_bottom.png", + "jeija_microcontroller_sides.png", + "jeija_microcontroller_sides.png", + "jeija_microcontroller_sides.png", + "jeija_microcontroller_sides.png" + }, + inventory_image = "digistuff_eeprom_top.png", + drawtype = "nodebox", + selection_box = { + --From luacontroller + type = "fixed", + fixed = { -8/16, -8/16, -8/16, 8/16, -5/16, 8/16 }, + }, + _digistuff_channelcopier_fieldname = "channel", + node_box = { + --From Luacontroller + type = "fixed", + fixed = { + {-8/16, -8/16, -8/16, 8/16, -7/16, 8/16}, -- Bottom slab + {-5/16, -7/16, -5/16, 5/16, -6/16, 5/16}, -- Circuit board + {-3/16, -6/16, -3/16, 3/16, -5/16, 3/16}, -- IC + } + }, + paramtype = "light", + sunlight_propagates = true, + on_receive_fields = function(pos, formname, fields, sender) + local name = sender:get_player_name() + if minetest.is_protected(pos,name) and not minetest.check_player_privs(name,{protection_bypass=true}) then + minetest.record_protection_violation(pos,name) + return + end + local meta = minetest.get_meta(pos) + if fields.channel then meta:set_string("channel",fields.channel) end + end, + digiline = + { + receptor = {}, + effector = { + action = function(pos,node,channel,msg) + local meta = minetest.get_meta(pos) + if meta:get_string("channel") ~= channel or type(msg) ~= "table" then return end + if msg.command == "read" then + if type(msg.address) == "number" and msg.address >= 0 and msg.address <= 31 then + digiline:receptor_send(pos,digiline.rules.default,channel,meta:get_string(string.format("data%02i",math.floor(msg.address)))) + end + elseif msg.command == "write" then + if type(msg.address) == "number" and msg.address >= 0 and msg.address <= 31 and type(msg.data) == "string" then + meta:set_string(string.format("data%02i",math.floor(msg.address)),string.sub(msg.data,1,512)) + end + end + end + }, + }, +}) + +minetest.register_craft({ + output = "digistuff:ram", + recipe = { + {"basic_materials:plastic_sheet","basic_materials:plastic_sheet","basic_materials:plastic_sheet"}, + {"mesecons_gates:nand_off","basic_materials:plastic_sheet","mesecons_gates:nand_off"}, + {"mesecons:wire_00000000_off","basic_materials:silicon","mesecons:wire_00000000_off"}, + } +}) + +minetest.register_craft({ + output = "digistuff:eeprom", + recipe = { + {"basic_materials:plastic_sheet","mesecons:wire_00000000_off","basic_materials:plastic_sheet"}, + {"digilines:wire_std_00000000","basic_materials:plastic_sheet","digilines:wire_std_00000000"}, + {"mesecons:wire_00000000_off","basic_materials:silicon","mesecons:wire_00000000_off"}, + } +}) diff --git a/textures/digistuff_eeprom_top.png b/textures/digistuff_eeprom_top.png new file mode 100644 index 0000000000000000000000000000000000000000..b80ee0b601ec9701387e63c95e70ec8853e06745 GIT binary patch literal 10605 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 WHoi~xz9y&y0IjXRKV9?Wx&HxHakTLO literal 0 HcmV?d00001 diff --git a/textures/digistuff_gpu_top.png b/textures/digistuff_gpu_top.png new file mode 100644 index 0000000000000000000000000000000000000000..2fc5a3d68fe3bcbf6f9cbf0b47a99b63c0ee5abd GIT binary patch literal 10513 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 Yr=L6DZc!%Hf=mP2ng=z~)s7zjAE4fxfdBvi literal 0 HcmV?d00001