diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/addrs.c | 67 | ||||
| -rw-r--r-- | src/addrs.h | 32 | ||||
| -rw-r--r-- | src/atari.cfg | 4 | ||||
| -rw-r--r-- | src/edbox.c | 16 | ||||
| -rw-r--r-- | src/keyclick.h | 1 | ||||
| -rw-r--r-- | src/keyclick.s | 53 | ||||
| -rw-r--r-- | src/main.c | 3 | ||||
| -rw-r--r-- | src/screen.c | 50 | ||||
| -rw-r--r-- | src/screen.h | 16 |
9 files changed, 193 insertions, 49 deletions
diff --git a/src/addrs.c b/src/addrs.c index 8c4ad1b..5154109 100644 --- a/src/addrs.c +++ b/src/addrs.c @@ -1,27 +1,56 @@ #include "addrs.h" -u8 *dlist = u8p(DLIST_ADDR); -u16 *dlist_top_lms = u16p(0xa404); -u16 *dlist_bottom_lms = u16p(0xa41e); -u8 *status_box = u8p(0xa425); /* 80 bytes */ -u8 *edit_box = u8p(0xa475); /* 160 bytes */ +u8 *dlist_top = u8p(DLIST_TOP_ADDR); +u8 *dlist_bot = u8p(DLIST_BOT_ADDR); -u8 *screen_addrs[7] = { - u8p(0xa538), - u8p(0xa8d0), - u8p(0xac68), +u16 *dlist_top_lms = u16p(0xbfa4); +u16 *dlist_bot_lms = u16p(0xbfd4); +u16 *dlist_status_lms = u16p(0xbfed); + +u8 *edit_box = u8p(0x0600); /* up to 256 bytes (page 6) */ +u8 *rx_buf = u8p(0xa000); /* 512 bytes */ +u8 *tx_buf = u8p(0xa200); /* 512 bytes */ + +/* 1000 bytes (25 40-char lines) apiece. */ +u8 *screen_top_addrs[7] = { + u8p(0x8400), + u8p(0x87e8), + u8p(0x8bd0), + u8p(0x9000), + u8p(0x93e8), + u8p(0x97d0), + u8p(0x9bb8) +}; + +/* 1000 bytes (25 40-char lines) apiece. */ +u8 *screen_bot_addrs[7] = { + u8p(0xa400), + u8p(0xa7e8), + u8p(0xabd0), u8p(0xb000), - u8p(0xb398), - u8p(0xb730), - u8p(0xbac8) + u8p(0xb3e8), + u8p(0xb7d0), + u8p(0xbbb8) }; -u8 *screen_botlines[7] = { - u8p(0xa8a8), - u8p(0xac40), - u8p(0xafd8), +/* 40 bytes (1 line), third from the bottom of each _bot_addr */ +u8 *screen_lastlines[7] = { + u8p(0xa770), + u8p(0xab58), + u8p(0xaf40), u8p(0xb370), - u8p(0xb708), - u8p(0xbaa0), - u8p(0xbe38) + u8p(0xb758), + u8p(0xbb40), + u8p(0xbf28) +}; + +/* 80 bytes (2 lines), bottom 2 of each _bot_addr */ +u8 *status_boxes[7] = { + u8p(0xa798), + u8p(0xab80), + u8p(0xaf68), + u8p(0xb398), + u8p(0xb780), + u8p(0xbb68), + u8p(0xbf50) }; diff --git a/src/addrs.h b/src/addrs.h index 6d44a68..dd9f23d 100644 --- a/src/addrs.h +++ b/src/addrs.h @@ -1,15 +1,33 @@ -#define FONT_ADDR_HI 0xa0 -#define DLIST_ADDR 0xa400 +#define FONT_ADDR_HI 0x80 +#define DLIST_TOP_ADDR 0xbfa0 +#define DLIST_BOT_ADDR 0xbfd0 #define u8 unsigned char #define u8p(x) ((unsigned char *)x) #define u16 unsigned int #define u16p(x) ((unsigned int *)x) -extern u8 *dlist; +/* dlist_bot is the main one, dlist_top is used when + scrolled back. */ +extern u8 *dlist_top, *dlist_bot; + extern u16 *dlist_top_lms; -extern u16 *dlist_bottom_lms; -extern u8 *status_box; +extern u16 *dlist_bot_lms; + +/* points to either edit_box or one of the status_boxes[] */ +extern u16 *dlist_status_lms; + +/* only one of these (not one per screen) */ extern u8 *edit_box; -extern u8 *screen_addrs[7]; -extern u8 *screen_botlines[7]; + +/* used for scrollback */ +extern u8 *screen_top_addrs[7]; + +/* normal (non-scrollback) display */ +extern u8 *screen_bot_addrs[7]; + +/* address of last line of _bot, where printing actually happens */ +extern u8 *screen_lastlines[7]; + +/* bottom 2 lines of the _bot display list for each screen */ +extern u8 *status_boxes[7]; diff --git a/src/atari.cfg b/src/atari.cfg index ea190f7..97b265e 100644 --- a/src/atari.cfg +++ b/src/atari.cfg @@ -1,5 +1,5 @@ FEATURES { - STARTADDRESS: default = $2000; + STARTADDRESS: default = $0700; } SYMBOLS { __EXEHDR__: type = import; @@ -16,7 +16,7 @@ MEMORY { # "main program" load chunk MAINHDR: file = %O, start = $0000, size = $0004; - MAIN: file = %O, define = yes, start = %S, size = $BC20 - __STACKSIZE__ - __RESERVED_MEMORY__ - %S; + MAIN: file = %O, define = yes, start = %S, size = $8000 - __STACKSIZE__ - __RESERVED_MEMORY__ - %S; TRAILER: file = %O, start = $0000, size = $0006; } SEGMENTS { diff --git a/src/edbox.c b/src/edbox.c index 9231b50..0903cb9 100644 --- a/src/edbox.c +++ b/src/edbox.c @@ -4,6 +4,7 @@ #include "addrs.h" #include "screen.h" #include "edbox.h" +#include "keyclick.h" /* TODO: tab completion */ @@ -37,7 +38,7 @@ void edbox_show(void) { scr_waitvcount(116); - *dlist_bottom_lms = addr; + *dlist_status_lms = addr; show_cursor(); } @@ -96,6 +97,7 @@ void edbox_readline(char *dest, char len) { } static void special_keystroke(char c) { + keyclick(); OS.ch = 0xff; edbox_putc(c); } @@ -178,11 +180,9 @@ void edbox_keystroke(void) { ; edbox_show(); - hide_cursor(); - OS.invflg = c = 0; + c = 0; - /* XXX: these keys don't click. */ switch(OS.ch) { case 0xa0: /* key: ctrl [ */ c = 0x7b; /* ascii: { */ @@ -197,6 +197,12 @@ void edbox_keystroke(void) { case 0x9c: /* key: ctrl ESC */ c = 0x7e; /* ascii: ~ */ break; + case 0x3c: /* caps */ + OS.shflok ^= 0x40; + keyclick(); + break; + case 0x7c: /* shift-caps */ + case 0xbc: /* ctrl-caps */ case 0x27: /* atari key */ case 0x67: /* ...w/shift */ case 0x97: /* ...w/ctrl */ @@ -207,6 +213,8 @@ void edbox_keystroke(void) { break; } + hide_cursor(); + if(c) { special_keystroke(c); } else { diff --git a/src/keyclick.h b/src/keyclick.h new file mode 100644 index 0000000..b73a212 --- /dev/null +++ b/src/keyclick.h @@ -0,0 +1 @@ +extern void keyclick(void); diff --git a/src/keyclick.s b/src/keyclick.s new file mode 100644 index 0000000..bbe613c --- /dev/null +++ b/src/keyclick.s @@ -0,0 +1,53 @@ + .include "atari.inc" + .export _keyclick + +; keyclick.s - just what you think it is. + +; How do you make it possible to disable the keyclick on the 400/800? +; Don't use the OS K: handler. + + ;.ifdef REAL_KEYCLICK + .if 1 + +; Copied from OS ROM source, 12 bytes of code. Because of the repeated +; stx WSYNC, you don't want to use this if you're using DLIs. +; Preserves A and Y, returns with X=$ff, N set, Z clear. +_keyclick: + ldx #$7f +@rc1: + stx CONSOL + stx WSYNC + dex + bpl @rc1 + rts + + .else + +; Fake keyclick. 25 bytes of code. Sounds just like the real one, but +; it won't mess up your DLIs because it's interruptible (though DLIs +; might mess it up). Loop timing assumes a GR.0 type display list +; with playfield DMA enabled and P/M DMA disabled. +; Preserves A, returns with X=$ff, Y=0, N set, Z clear. +_keyclick: +@wcount: + ldx VCOUNT ; To make the timing consistent, wait until we're sure + cpx #$10 ; that ANTIC is doing DMA. + bne @wcount + + ldx #$7f +@click: ; I tuned this by ear, then cycle-counted afterward. + stx CONSOL ; 4 + ldy #$07 ; 2 + ;lda #0 ; 2 + nop +@c1: + dey ; inner: 2 + nop ; 2 + bne @c1 ; 3 + ; 7 cycles/loop, *7 = 49, -1 for failed BNE + ; 48 + dex ; 2 + bpl @click ; 3 = 61 + rts + + .endif @@ -29,8 +29,7 @@ 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 bw=0; // # of bytes waiting. -unsigned char rx_buf[MAX_IRC_MSG_LEN]; // RX buffer. -unsigned char tx_buf[MAX_IRC_MSG_LEN]; // TX buffer. +extern char *rx_buf, *tx_buf /* 512 bytes each, see addrs.c */ unsigned int txbuflen; // TX buffer length char channel[32] = DEF_CHANNEL; diff --git a/src/screen.c b/src/screen.c index b98a26a..252d39d 100644 --- a/src/screen.c +++ b/src/screen.c @@ -25,14 +25,17 @@ void scr_waitvcount(u8 c) { } static void scr_clear(char s) { - memset(screen_addrs[s], 0, SCREEN_SIZE); + memset(screen_top_addrs[s], 0, 1000); + memset(screen_bot_addrs[s], 0, 1000); memset(scr_names[s], 0, 32); memset(scr_topics[s], 0, LINE_SIZE); } static void scr_scroll(char s) { - memmove(screen_addrs[s], screen_addrs[s] + 40, 880); - memset(screen_botlines[s], 0, 40); + memmove(screen_top_addrs[s], screen_top_addrs[s] + 40, 960); + memmove(screen_top_addrs[s] + 960, screen_bot_addrs[s], 40); + memmove(screen_bot_addrs[s], screen_bot_addrs[s] + 40, 920); + memset(screen_lastlines[s], 0, 40); } void scr_init(void) { @@ -41,7 +44,7 @@ void scr_init(void) { old_dma = OS.sdmctl; OS.sdmctl = 0; scr_waitvcount(112); /* after the last GR.0 line */ - *SDLST = DLIST_ADDR; + *SDLST = DLIST_BOT_ADDR; OS.chbas = FONT_ADDR_HI; for(i = 0; i < MAX_SCREENS; i++) { @@ -106,21 +109,36 @@ void scr_display(char s) { scr_current = s; scr_waitvcount(112); - *dlist_top_lms = (u16)screen_addrs[s]; + *dlist_bot_lms = (u16)screen_bot_addrs[s]; scr_show_status(s); } +void scr_scrollback(void) { + // OS.color2 = 0; + scr_waitvcount(112); + *dlist_top_lms = (u16)screen_top_addrs[scr_current]; + *SDLST = (u16)dlist_top; +} + +void scr_end_scrollback(void) { + // OS.color2 = 192; + scr_waitvcount(112); + *SDLST = (u16)dlist_bot; +} + void scr_show_status(char s) { int i; char *p, sc; - status_box[0] = s + 177; /* inverse number */ - status_box[1] = ':'; - strncpy(status_box + 2, scr_names[s], 32); - strncpy(status_box + 40, scr_topics[s], 40); + /* this part should be moved to _create() */ + p = status_boxes[s]; + p[0] = s + 177; /* inverse number */ + p[1] = ':'; + strncpy(p + 2, scr_names[s], 32); + strncpy(p + 40, scr_topics[s], 40); - p = status_box + 33; + p += 33; for(i = 0; i < MAX_SCREENS; i++) { switch(scr_status[i]) { case SCR_ACTIVE: @@ -134,7 +152,7 @@ void scr_show_status(char s) { } scr_waitvcount(112); - *dlist_bottom_lms = (u16)status_box; + *dlist_status_lms = (u16)status_boxes[s]; } void scr_refresh(void) { @@ -152,6 +170,14 @@ char scr_getbyname(const char *name) { return 0; } +void scr_putc_active(char c) { + scr_putc(scr_active, c); +} + +void scr_eol_active(void) { + scr_putc(scr_active, '\n'); +} + /* TODO: skip color codes (start with 0x03 or 0x04). if we're going to ever support utf-8, decode it here... also, 0x16 is supposed to be reverse video. not widely used/supported. @@ -176,7 +202,7 @@ void scr_putc(char s, char c) { xpos = 0; } - dest = screen_botlines[s] + xpos; + dest = screen_lastlines[s] + xpos; if(c & 0x80) { /* utf-8 (or maybe latin-1), we don't support it yet */ diff --git a/src/screen.h b/src/screen.h index fe8c928..bb70999 100644 --- a/src/screen.h +++ b/src/screen.h @@ -33,9 +33,9 @@ extern char scr_status[MAX_SCREENS]; void scr_init(void); /* creates a screen, if possible. we only get 7; attempts to create - more that that will return -1. on success, returns the screen - number (0-6). the name gets copied to the 1st line of the screen's - status box. + more that that will return 0 (aka the server screen). on success, + returns the screen number (2-6). the name gets copied to the 1st + line of the screen's status box. if display is true, the new screen displays. otherwise it's created "in the background". */ @@ -54,6 +54,14 @@ void scr_set_topic(char s, const char *topic); s's active flag. calls scr_show_status(). */ void scr_display(char s); +/* display the backscroll (top 25 lines) of the current screen. + note that it's a bad idea to write to the screen while it's + scrolled back! */ +void scr_scrollback(void); + +/* end scrollback mode (display the bottom 23 lines + status) */ +void scr_end_scrollback(void); + /* XXX: does this need to be public? */ void scr_show_status(char s); @@ -71,6 +79,8 @@ void scr_activate_name(const char *name); /* print one character to a screen. handles scrolling. will not print an EOL at column 0 (just ignores it). */ void scr_putc(char s, char c); +void scr_putc_active(char c); +void scr_eol_active(void); /* print text to a screen. handles scrolling. this doesn't have to be the screen being displayed, of course; |
