+void do_silence() {
+ if (check_standalone()) return;
+ if (sci_rx_buf[1] == '\0')
+ unchime_start();
+ else if (sci_rx_buf[1] == 'S') { /* synchronous beep */
+ if (sci_rx_buf[2] == '\0')
+ unchime_start();
+ else if (sci_rx_buf[3] != '\0' && sci_rx_buf[4] == '\0')
+ unchime_for(hex2u8(sci_rx_buf[2], sci_rx_buf[3]));
+ else {
+ send_string("511 Unknown silence duration." CRLF);
+ return;
+ }
+ while (unchime_count); /* spin */
+ send_string("501 Silenced." CRLF);
+ return;
+ } else if (sci_rx_buf[2] != '\0' && sci_rx_buf[3] == '\0')
+ unchime_for(hex2u8(sci_rx_buf[1], sci_rx_buf[2]));
+ else {
+ send_string("511 Unknown silence duration." CRLF);
+ return;
+ }
+ send_string("501 Silence started." CRLF);
+ return;
+}
+
+void print_switches(u8 prompted) {
+ if (prompted)
+ send_string("600 ");
+ else
+ send_string("610 ");
+ send_string(u82hex(misc_input));
+ send_string(" ");
+ send_string(u82hex(switch_input));
+ send_string(CRLF);
+}
+
+void ping_pong() {
+ /* make sure it's really a ping */
+ if (!my_strncmp("ING", (char*)sci_rx_buf+1, 3)) {
+ unknown_command();
+ return;
+ }
+ /* respond with ack & pong */
+ send_string("000 PONG!" CRLF);
+}
+
+u16 hex2addr(char* addrptr) {
+ u16 v;
+ v = hex2u8(addrptr[0], addrptr[1]) << 8;
+ v |= hex2u8(addrptr[2], addrptr[3]);
+ return v;
+}
+
+void peek() {
+ if (!my_strncmp("EEK", (char*)sci_rx_buf+1, 3)) {
+ unknown_command();
+ return;
+ }
+ if (check_badpoke()) return;
+ if (ishex(sci_rx_buf[4]) && ishex(sci_rx_buf[5]) && ishex(sci_rx_buf[6]) &&
+ ishex(sci_rx_buf[7]) && sci_rx_buf[8] == '\0') {
+ u16 v = hex2addr((char*)(sci_rx_buf+4));
+ v = *((u8*)v);
+ send_string("090 ");
+ send_string(u82hex(v));
+ send_string(CRLF);
+ return;
+ }
+ send_string("091 Invalid location given." CRLF);
+}
+
+void poke() {
+ if (!my_strncmp("OKE", (char*)sci_rx_buf+1, 3)) {
+ unknown_command();
+ return;
+ }
+ if (check_badpoke()) return;
+ if (ishex(sci_rx_buf[4]) && ishex(sci_rx_buf[5]) && ishex(sci_rx_buf[6]) &&
+ ishex(sci_rx_buf[7]) && ishex(sci_rx_buf[8]) && ishex(sci_rx_buf[9])
+ && sci_rx_buf[10] == '\0') {
+ u16 v;
+ v = hex2addr((char*)(sci_rx_buf+4));
+ *(u8*)v = hex2u8(sci_rx_buf[8], sci_rx_buf[9]);
+ send_string("080 Written." CRLF);
+ return;
+ }
+ send_string("081 Invalid location or byte given." CRLF);
+}
+
+void jump() {
+ if (!my_strncmp("UMP", (char*)sci_rx_buf+1, 3)) {
+ unknown_command();
+ return;
+ }
+ if (check_badpoke()) return;
+ if (ishex(sci_rx_buf[4]) && ishex(sci_rx_buf[5]) && ishex(sci_rx_buf[6]) &&
+ ishex(sci_rx_buf[7]) && sci_rx_buf[8] == '\0') {
+ u16 v = hex2addr((char*)(sci_rx_buf+4));
+ send_string("070 Jumping now." CRLF);
+ asm volatile ("jsr %0" : : "m"(*(u16*)v) : "d");
+ send_string("071 And back." CRLF);
+ return;
+ }
+ send_string("079 Invalid location given." CRLF);
+}
+
+void do_set_password() {
+ u8 i;
+ bool good = 1;
+ if (check_badpoke()) return;
+ for (i=1; i < 17; i++) {
+ if (sci_rx_buf[i] == '\0') {
+ good = 0;
+ break;
+ }
+ }
+ if (good && sci_rx_buf[17] != '\0') good = 0;
+ if (!good) {
+ send_string("061 Password must be exactly 16 characters." CRLF);
+ return;
+ }
+
+ mic_set_secret((char*)(sci_rx_buf+1));
+ send_string("060 Password has been set." CRLF);
+}
+
+void send_prompt() {
+ if (must_verify()) {
+ send_string(u82hex(mic_challenge >> 8));
+ send_string(u82hex(mic_challenge & 0xff));
+ }
+ send_string(is_standalone()?"% ":"# ");
+}
+
+void about() {
+ if (!my_strncmp("BOUT", (char*)sci_rx_buf+1, 4)) {
+ unknown_command();
+ return;
+ }
+ send_string(
+ CRLF
+ " Revision: " VERSION_STRING " Built: " DATEBUILT_STRING CRLF "" CRLF CRLF
+ " This snack machine was brought to you by " CRLF
+ " Bernard Blackham" CRLF
+ " Harry McNally" CRLF
+ " Mark Tearle" CRLF
+ " Michal Gornisiewicz" CRLF
+ " Nick Bannon" CRLF
+ " and others." CRLF
+ "" CRLF
+ " Another UCC project in action. http://www.ucc.asn.au/" CRLF
+ );
+}