#include "vend.h"
void delay(u16 ms) {
- /* delay routine written in assembly so we know what we're really getting.
- * each inner loop should take ~1 ms to execute.
- * 15 cycles * (1/4.9152Mhz) * 327 = 0.997 ms + a little bit on the fringes.
- *
- * XXX - how do we know gcc isn't optimising this? it seems to optimise after
- * parsing C -> asm, but before asm -> machine code.
- */
- //asm volatile ("pshx\npsha\npshb\n"); /* save registers */
asm volatile ("ldx %0\n" :: "m" (ms) : "x");
asm volatile (
"delay_loop:\n"
- //" ldd #327\n" /* 3 */
" ldd #150\n" /* 3 */
"delay_inner_loop:\n" /* 15 cycles each */
" cpd #0x0000\n" /* 5 */
" beq delay_out\n" /* 3 */
" bra delay_loop\n" /* 3 */
"delay_out:\n" ::: "x", "d");
- /*" pulb\n"
- " pula\n"
- " pulx\n");*/
}
u8 my_strlen(char* s) {
return hexconv_buf;
}
+bool ishex(char b) {
+ if (b >= '0' && b <= '9') return 1;
+ if (b >= 'a' && b <= 'f') return 1;
+ if (b >= 'A' && b <= 'F') return 1;
+ return 0;
+}
+
* and snacks.
*/
-#define VERSION_STRING "R 20040622"
+#define VERSION_STRING "V 20040624"
#include "display_basic.h"
#include "keypad.h"
return 0;
}
+bool check_badpoke() {
+ if (cant_poke()) {
+ send_string("099 Can't poke without flipping DIP SW 3." CRLF);
+ return 1;
+ }
+ return 0;
+}
+
void unknown_command() {
send_string("012 Unknown command. Type HELP for help." CRLF);
}
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(
"Valid commands are:" CRLF
" ABOUT ROM information" CRLF
- " PING pongs" CRLF
+ " B[S][nn] beep [synchronously] for a duration nn (optional)" CRLF
+ " C[S][nn] silence [synchronously] for a duration nn (optional)" CRLF
+ " Dxxxxxxxxxx show a message on the display" CRLF
" ECHO {ON|OFF} turn echo on or off" CRLF
- " Vnn vend an item" CRLF
- " VALL vend all items" CRLF
- " DXXXXXXXXXX show a message on the display" CRLF
- " B[nn] beep for a duration nn (optional)" CRLF
- " S[...] query all internal switch states" CRLF
- " H[...] this help screen" CRLF
" GETROM download the ROM source code using xmodem" CRLF
- "Comments start with a #" CRLF
+ " H[...] this help screen" CRLF
+ "*JUMPxxxx jumps to a subroute at location xxxx" CRLF
+ "*PEEKxxxx returns the value of the byte at location xxxx" CRLF
+ "*POKExxxxyy sets the value of location xxxx to yy" CRLF
+ " PING pongs" CRLF
+ " S[...] query all internal switch states" CRLF
+ "+Vnn vend an item" CRLF
+ "+VALL vend all items" CRLF
+ "*Wxxxxxxxxxxxx set a new password for authenticated vends. xxx=16 chars" CRLF
+ "" CRLF
+ "Very few functions are available when the machine is in standalone " CRLF
+ "mode (DIP SW 1 is set)" CRLF
+ "+ denotes that this item requires authentication if DIP SW 2 is set" CRLF
+ "* denotes that DIP SW 3 must be set to use these" CRLF
+ "Commands starting with # are ignored (comments)" CRLF
);
}
unknown_command();
}
-//SHA1_CTX ctx;
-//u8 sha1_digest[SHA1_SIGNATURE_SIZE];
-
int main() {
u8 i;
for (i = 0; i < 11; i++)
send_string("5N4X0RZ R US" CRLF);
mic_challenge = 0;
- mic_set_secret("ABCDEFGH12345678");
last_standalone = is_standalone();
if (last_standalone)
case '#':
send_string(CRLF);
break;
- case 'E':
- set_echo();
- break;
- case 'H':
- help();
- break;
- case 'V':
- dispense_something();
- break;
- case 'D':
- write_to_display();
+ case 'A':
+ about();
break;
case 'B':
do_chime();
case 'C':
do_silence();
break;
- case 'P':
- ping_pong();
+ case 'D':
+ write_to_display();
break;
- case 'A':
- about();
+ case 'E':
+ set_echo();
break;
- case 'S':
- print_switches(1);
+ case 'G':
+ getrom();
+ break;
+ case 'H':
+ help();
break;
case 'M':
moo();
break;
+ case 'P':
+ if (sci_rx_buf[1] == 'I')
+ ping_pong();
+ else if (sci_rx_buf[1] == 'O')
+ poke();
+ else if (sci_rx_buf[1] == 'E')
+ peek();
+ break;
+ case 'J':
+ jump();
+ break;
case 'Q':
quit();
break;
- case 'G':
- getrom();
+ case 'S':
+ print_switches(1);
+ break;
+ case 'V':
+ dispense_something();
+ break;
+ case 'W':
+ do_set_password();
break;
default:
// shurg