diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/bell.s | 45 | ||||
| -rw-r--r-- | src/cmd.c | 112 | ||||
| -rw-r--r-- | src/irc.c | 191 | ||||
| -rw-r--r-- | src/irc.h | 5 | ||||
| -rw-r--r-- | src/main.c | 4 |
5 files changed, 332 insertions, 25 deletions
diff --git a/src/bell.s b/src/bell.s new file mode 100644 index 0000000..6a27503 --- /dev/null +++ b/src/bell.s @@ -0,0 +1,45 @@ + + .include "atari.inc" + + .import _bell_type + .export _bell + +DISTVOL = $a8 +PITCH = $40 +JIFFIES = $03 + +_bell: + lda #<bell_callback + sta CDTMA2 + lda #>bell_callback + sta CDTMA2+1 + lda _bell_type + beq done + lda #JIFFIES + sta CDTMV2 + lda _bell_type + and #1 + beq check_flash + lda #DISTVOL + sta AUDC1 + lda #PITCH + sta AUDF1 +check_flash: + lda _bell_type + and #2 + beq done + lda #$08 + sta COLOR4 + lda #JIFFIES + sta CDTMV2 +done: + rts + +bell_callback: + lda #0 + sta AUDC1 + sta AUDF1 + sta COLOR4 + lda #JIFFIES + sta CDTMV2 + rts @@ -12,13 +12,17 @@ char *command, *arg1, *arg2, *arg3; static char *target; +static void do_away(void); +static void do_bell(void); static void do_color(void); +static void do_ctcp(void); static void do_info(void); static void do_j(void); static void do_j1(void); static void do_list(void); static void do_me(void); static void do_msg(void); +static void do_names(void); static void do_part(void); static void do_ping(void); static void do_query(void); @@ -37,7 +41,10 @@ typedef struct { OP DEOP VOICE DEVOICE KICK BAN KB IGNORE UNIGNORE MODE */ cmd_t command_defs[] = { + { "AWAY", do_away, 1 }, + { "BELL", do_bell, 1 }, { "COLOR", do_color, 1 }, + { "CTCP", do_ctcp, 1 }, { "INFO", do_info, 0 }, { "J", do_j, 1 }, { "J1", do_j1, 1 }, @@ -47,6 +54,7 @@ cmd_t command_defs[] = { { "M", do_msg, 1 }, { "ME", do_me, 1 }, { "MSG", do_msg, 1 }, + { "NAMES", do_names, 0 }, { "PART", do_part, 0 }, { "PING", do_ping, 0 }, { "Q", do_query, 1 }, @@ -96,7 +104,7 @@ static void err_marker(void) { static void err_arg_req(void) { err_marker(); scr_print_current(cmd_def->cmd); - scr_print_current(" requires an argument\n"); + scr_print_current(": missing argument\n"); } static void err_no_scr_target(void) { @@ -104,12 +112,6 @@ static void err_no_scr_target(void) { scr_print_current("No channel/nick for screen\n"); } -static void err_target_req(void) { - err_marker(); - scr_print_current(cmd_def->cmd); - scr_print_current(" requires target channel/nick\n"); -} - /* arg points to something like: "part #channel I'm outta here\0" after nextarg(), arg points to "part\0" only, and ret points @@ -162,7 +164,7 @@ static void do_part(void) { } if(!target) { - err_target_req(); + err_no_scr_target(); return; } @@ -181,7 +183,7 @@ static void do_topic(void) { } if(!target) { - err_target_req(); + err_no_scr_target(); return; } @@ -191,6 +193,22 @@ static void do_topic(void) { txbuf_send(); } +static void do_names(void) { + if(arg1[0] == '#') { + target = arg1; + arg2 = nextarg(arg1); + } else { + arg2 = arg1; + } + + if(!target) { + err_no_scr_target(); + return; + } + txbuf_set_str2("NAMES ", target); + txbuf_send(); +} + static void do_server_info(void) { txbuf_send_str("INFO"); } @@ -199,27 +217,70 @@ static void do_server_ping(void) { txbuf_send_str("PING 0xdeadbeef"); } -static void do_ctcp_ping(void) { +/* arg1 = nick + arg2 = CTCP type + arg3 = optional data */ +static void send_ctcp(void) { txbuf_set_str3("PRIVMSG ", arg1, " :\x01"); - txbuf_append_str("PING 0xdeadbeef\x01"); + txbuf_append_str(arg2); + if(arg3) + txbuf_append_str2(" ", arg3); + txbuf_append_str("\x01"); txbuf_send(); } +long read_rtclok(void) { + long r; + + r = ((long)OS.rtclok[0] << 16); + r |= (OS.rtclok[1] << 8); + r |= OS.rtclok[2]; + + return r; +} + +static void rtclok_to_numbuf(void) { + long r; + r = read_rtclok(); + ltoa(r, numbuf, 10); +} + +static void do_ctcp_ping(void) { + arg2 = "PING"; + rtclok_to_numbuf(); + arg3 = numbuf; + send_ctcp(); +} + static void do_ctcp_info(void) { - txbuf_set_str3("PRIVMSG ", arg1, " :\x01"); - txbuf_append_str("CLIENTINFO\x01"); - txbuf_send(); + arg2 = "CLIENTINFO"; + arg3 = 0; + send_ctcp(); } static void do_ctcp_ver(void) { - txbuf_set_str3("PRIVMSG ", arg1, " :\x01"); - txbuf_append_str("VERSION\x01"); - txbuf_send(); + arg2 = "VERSION"; + arg3 = 0; + send_ctcp(); +} + +static void do_ctcp(void) { + if(!arg1) { + err_arg_req(); + return; + } + arg2 = nextarg(arg1); + if(!arg2) { + err_arg_req(); + return; + } + arg3 = nextarg(arg2); + send_ctcp(); } static void do_me(void) { if(!target) { - err_target_req(); + err_no_scr_target(); return; } @@ -272,6 +333,10 @@ static void do_color(void) { } static void do_query(void) { + /* don't create a query if we already got one! */ + if(scr_getbyname(arg1)) + return; + if(scr_create(arg1, 1) == 0xff) { err_marker(); scr_print_current("Can't create query, all screens in use\n"); @@ -300,6 +365,17 @@ static void do_msg(void) { } } +static void do_away(void) { + OS.atract = 0x80; + irc_away = 1; + txbuf_set_str2("AWAY :", arg1); + txbuf_send(); +} + +static void do_bell(void) { + bell_type = *arg1 - '0'; +} + static int cmd_local(void) { arg1 = nextarg(command); @@ -15,15 +15,23 @@ #define MAX_MSG 512 +extern void __fastcall__ bell(void); /* see src/bell.s */ + char *msg_src, *msg_cmd, *msg_dest, *msg_text; char *msg_args[MAX_MSG_ARGS]; int msg_argcount; +char irc_away = 0; +char bell_type = 3; + static char msgbuf[MAX_MSG] = { 0 }; static char *msg; /* with source removed */ static int msgbuf_len = 0, msg_len = 0; static char regged = 0, hilite = 0; +static char scr_prev = SCR_PRIV; + +char numbuf[10]; /* static void join_channel(void) { @@ -56,6 +64,7 @@ static void hilite_bold(void) { } static void do_chan_nick(void) { + if(hilite) bell(); hilite_bold(); scr_print_active("<"); hilite_bold(); @@ -75,6 +84,107 @@ static void do_priv_nick(void) { scr_print_active("*"); scr_print_active(msg_src); scr_print_active("* "); + bell(); +} + +static void print_ping_time(char *p) { + static long now, pingtime; + static int sec, frac; + + now = read_rtclok(); + pingtime = atol(p); + + /* correct for rtclock rollover (every 77 hours) */ + if(now < pingtime) now |= 0x01000000L; + + pingtime = now - pingtime; + + sec = pingtime / hz; + frac = pingtime % hz; + frac *= 1000; + frac /= (hz * 10); + + scr_print_active("*** "); + scr_print_active(msg_src); + scr_print_active(" ping time: "); + itoa(sec, numbuf, 10); + scr_print_active(numbuf); + scr_print_active("."); + itoa(frac, numbuf, 10); + scr_print_active(numbuf); + scr_print_active(" sec"); + + /* for debugging: + scr_print_active(" "); + ltoa(pingtime, numbuf, 10); + scr_print_active(numbuf); + */ +} + +/* FIXME: this isn't very fast */ +static void do_ctcp(int is_notice) { + static char *p, *ctcp_type, *resp; + + resp = 0; + ctcp_type = ++msg_text; /* skip leading ^A */ + + if( (p = strchr(msg_text, '\x01')) ) { + /* kill trailing ^A */ + *p = 0; + } + + if( (p = strchr(msg_text, ' ')) ) { + *p++ = 0; + } + + if(is_notice) { + /* NOTICEs are responses */ + if(p && streq_i(ctcp_type, "PING")) { + print_ping_time(p); + } else { + scr_print_active("*** CTCP "); + scr_print_active(ctcp_type); + scr_print_active(" response from "); + scr_print_active(msg_src); + if(p) { + scr_print_active(": "); + scr_print_active(p); + } + } + scr_eol_active(); + } else { + /* this is a PRIVMSG (aka a request) */ + if(streq_i(ctcp_type, "ACTION")) { + scr_print_active("* "); + scr_print_active(msg_src); + scr_print_active(" "); + scr_print_active(p); + scr_eol_active(); + return; + } + + scr_print_active("*** CTCP "); + scr_print_active(ctcp_type); + scr_print_active(" request from "); + scr_print_active(msg_src); + scr_eol_active(); + + if(streq_i(ctcp_type, "PING")) { + resp = p; + } else if(streq_i(ctcp_type, "CLIENTINFO")) { + resp = "PING VERSION CLIENTINFO"; + } else if(streq_i(ctcp_type, "VERSION")) { + resp = "FujiNetChat pre-alpha on an Atari 8-bit"; + } else { + /* unknown CTCP type, ignore */ + return; + } + + txbuf_set_str3("NOTICE ", msg_src, " :\x01"); + txbuf_append_str3(ctcp_type, " ", resp); + txbuf_append_str("\x01"); + txbuf_send(); + } } static void do_privmsg(void) { @@ -84,6 +194,11 @@ static void do_privmsg(void) { else hilite = 0; + if(*msg_text == '\x01') { + do_ctcp(0); + return; + } + if(*msg_dest == '#') do_chan_nick(); else @@ -93,6 +208,15 @@ static void do_privmsg(void) { scr_eol_active(); } +static void do_notice(void) { + if(*msg_text == '\x01') { + do_ctcp(1); + } else { + scr_print_active("NOTICE "); + do_privmsg(); + } +} + static void do_join(void) { if(streq_i(usernick, msg_src)) { scr_print_active("You have "); @@ -321,6 +445,8 @@ static void dispatch_msg(void) { if(streq_i(msg_cmd, "PRIVMSG")) { do_privmsg(); + } else if(streq_i(msg_cmd, "NOTICE")) { + do_notice(); } else if(streq_i(msg_cmd, "JOIN")) { do_join(); } else if(streq_i(msg_cmd, "NICK")) { @@ -459,10 +585,9 @@ static void irc_split_Lines(void) { /* TODO: there needs to be a scr_printnum() */ void print_errnum(void) { extern unsigned char err; - char tmp[10]; scr_print_current("Error #"); - itoa(err, tmp, 10); - scr_print_current(tmp); + itoa(err, numbuf, 10); + scr_print_current(numbuf); scr_print_current(", press any key...\n"); } @@ -472,11 +597,13 @@ int irc_read(void) { err = nstatus(url); if(err != 1) { + regged = 0; if(err == 136) { scr_print_current("Disconnected, press any key...\n"); } else { print_errnum(); } + bell(); cgetc(); scr_display(0); return 0; @@ -529,23 +656,71 @@ static void scrollback() { scr_end_scrollback(); } +static void hunt_screen(signed char dir) { + signed char s = scr_current; + + do { + s += dir; + if(s < 0) + s = MAX_SCREENS - 1; + s %= MAX_SCREENS; + } while(scr_status[s] == SCR_UNUSED); + + scr_display(s); +} + +void switch_to_active() { + char i; + + for(i = 0; i < MAX_SCREENS; i++) { + if(scr_status[i] == SCR_ACTIVE) { + scr_prev = scr_current; + scr_display(i); + return; + } + } +} + static void start_keystroke(void) { char i, s; i = cgetc(); if(i >= '1' && i <= '7') { s = i - '1'; - if(scr_status[s] != SCR_UNUSED) - scr_display(s); + if(s != scr_current) { + if(scr_status[s] != SCR_UNUSED) { + scr_prev = scr_current; + scr_display(s); + } + } } else if(i == CH_CURS_UP || i == '-') { scrollback(); - } else if(i == 0x1b) { /* escape */ + } else if(i == CH_ESC) { + scr_prev = SCR_PRIV; scr_destroy(scr_current); + } else if(i == CH_CURS_LEFT || i == '+') { + scr_prev = scr_current; + hunt_screen(-1); + } else if(i == CH_CURS_RIGHT || i == '*') { + scr_prev = scr_current; + hunt_screen(1); + } else if(i == CH_TAB) { + i = scr_current; + scr_display(scr_prev); + scr_prev = i; + } else if(i == 'a' || i == 'A') { + switch_to_active(); + } else if(i == 's' || i == 'S') { + edbox_hide(); } } static void keystroke(void) { if(OS.ch == 0xff) return; + if(irc_away) { + txbuf_send_str("AWAY"); + irc_away = 0; + } if(GTIA_READ.consol == 6) { /* start pressed */ start_keystroke(); } else { @@ -556,6 +731,10 @@ static void keystroke(void) { /* only exits on error (e.g. connection closed, which might be via /QUIT). */ void irc_loop(void) { while(1) { + if(!irc_away && (OS.atract & 0x80)) { + irc_away = 1; + txbuf_send_str("AWAY :ATRACT mode"); + } if(!irc_read()) return; keystroke(); } @@ -11,6 +11,7 @@ extern char *rx_buf; extern unsigned short rxbuflen; extern unsigned char err; extern unsigned char trip; +extern char hz; extern unsigned int txbuflen; extern char *tx_buf; @@ -41,9 +42,12 @@ void print_error(unsigned char err); /**** irc.c */ #define MAX_MSG_ARGS 8 +extern char numbuf[10]; extern char *msg_src, *msg_cmd, *msg_dest, *msg_text; extern char *msg_args[MAX_MSG_ARGS]; extern int msg_argcount; +extern char irc_away; +extern char bell_type; /* call this once, right after TCP connection is established. */ void irc_register(void); @@ -57,3 +61,4 @@ void print_errnum(void); /**** cmd.c */ void cmd_command(char *cmd); void cmd_execute(void); +long read_rtclok(void); /* irc.c needs this one so it's not static */ @@ -23,13 +23,13 @@ char url[256] = DEF_URL; // URL char usernick[32] = DEF_NICK; -char tmp[8]; // temporary # to string unsigned char err; // error code of last operation. unsigned char trip=0; // if trip=1, fujinet is asking us for attention. bool old_enabled=false; // were interrupts enabled for old vector void* old_vprced; // old PROCEED vector, restored on exit. unsigned short rxbuflen; unsigned int txbuflen; // TX buffer length +char hz; /* 50 for PAL, 60 for NSTC */ /* TODO: user modes (default +iw), fg/bg color... */ @@ -142,6 +142,8 @@ int main(void) { OS.color2 = 0xc0; /* darkest green background */ OS.color1 = 0x0c; /* bright text */ + hz = (GTIA_READ.pal & 0x0e) ? 60 : 50; + scr_init(); while(1) { |
