From f4021c437bf3944d88241a791bae888f5af2b4de Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Sat, 26 Jan 2019 22:24:50 +0000 Subject: [PATCH] atarist: filling in the blanks Still a work in progress with much to complete --- Kernel/platform-atarist/config.h | 7 +- Kernel/platform-atarist/devtty.c | 374 ++++++++++++++++++++--------- Kernel/platform-atarist/devtty.h | 10 +- Kernel/platform-atarist/kernel.def | 6 +- Kernel/platform-atarist/main.c | 20 +- Kernel/platform-atarist/p68000.S | 325 ++++++++++++++++++++++--- 6 files changed, 582 insertions(+), 160 deletions(-) diff --git a/Kernel/platform-atarist/config.h b/Kernel/platform-atarist/config.h index 11cb001e..cfec7bac 100644 --- a/Kernel/platform-atarist/config.h +++ b/Kernel/platform-atarist/config.h @@ -34,9 +34,10 @@ #define CMDLINE NULL /* Location of root dev name */ /* Device parameters */ -#define NUM_DEV_TTY 2 -#define NDEVS 2 /* Devices 0..NDEVS-1 are capable of being mounted */ - /* (add new mountable devices to beginning area.) */ +#define NUM_DEV_TTY 3 + #define TTYDEV BOOT_TTY /* Device used by kernel for messages, panics */ #define NBUFS 10 /* Number of block buffers */ #define NMOUNTS 4 /* Number of mounts at a time */ + +/* TODO tty scan rows/cols etc */ diff --git a/Kernel/platform-atarist/devtty.c b/Kernel/platform-atarist/devtty.c index 15f986ef..fb0f4315 100644 --- a/Kernel/platform-atarist/devtty.c +++ b/Kernel/platform-atarist/devtty.c @@ -7,12 +7,22 @@ #include #include -#undef DEBUG /* UNdefine to delete debug code sequences */ +/* + * We have three serial links on the Atari ST. The MFP provides the serial + * port (tty2 for now), and a pair of ACIA chips provide keyboard/mouse/js + * and midi. We expose the midi as a tty but not the keyboard port. + */ +#define IKBD_STATUS 0xFFFC00 +#define IKBD_DATA 0xFFFC02 +#define MIDI_STATUS 0xFFFC04 +#define MIDI_DATA 0xFFFC06 + +#define MFP_TSR 0xFFFA2D +#define MFP_DATA 0xFFFA2F +#define MFP_TCDCR 0xFFFA1D +#define MFP_TDDR 0xFFFA25 -uint8_t *uart_data = (uint8_t *)0xFF04; /* ACIA data */ -uint8_t *uart_status = (uint8_t *)0xFF05; /* ACIA status */ -uint8_t *uart_command = (uint8_t *)0xFF06; /* ACIA command */ -uint8_t *uart_control = (uint8_t *)0xFF07; /* ACIA control */ +#undef DEBUG /* UNdefine to delete debug code sequences */ static tcflag_t console_mask[4] = { _ISYS, @@ -33,22 +43,24 @@ static tcflag_t uart_mask[4] = { tcflag_t *termios_mask[NUM_DEV_TTY + 1] = { NULL, console_mask, - console_mask, - uart_mask + uart_mask, + console_mask }; static unsigned char tbuf1[TTYSIZ]; static unsigned char tbuf2[TTYSIZ]; +static unsigned char tbuf3[TTYSIZ]; struct s_queue ttyinq[NUM_DEV_TTY + 1] = { /* ttyinq[0] is never used */ {NULL, NULL, NULL, 0, 0, 0}, {tbuf1, tbuf1, tbuf1, TTYSIZ, 0, TTYSIZ / 2}, - {tbuf2, tbuf2, tbuf2, TTYSIZ, 0, TTYSIZ / 2} + {tbuf2, tbuf2, tbuf2, TTYSIZ, 0, TTYSIZ / 2}, + {tbuf3, tbuf3, tbuf3, TTYSIZ, 0, TTYSIZ / 2} }; uint8_t vtattr_cap; -/* tty1 is the screen tty2 is the serial port */ +/* tty1 is the screen tty2 is the serial port tty3 is MIDI */ /* Output for the system console (kprintf etc) */ void kputchar(char c) @@ -63,26 +75,62 @@ ttyready_t tty_writeready(uint8_t minor) uint8_t c; if (minor == 1) return TTY_READY_NOW; - c = *uart_status; - return (c & 16) ? TTY_READY_NOW : TTY_READY_SOON; /* TX DATA empty */ + if (minor == 2) { + /* Double check which way around */ + c = *(volatile uint8_t *)MFP_TSR; + return (c & 0x80) ? TTY_READY_NOW : TTY_READY_SOON; + } + c = *(volatile uint8_t *)MIDI_STATUS; + if (c & 0x02) + return TTY_READY_NOW; + return TTY_READY_SOON; } -/* For DragonPlus we should perhaps support both monitors 8) */ - void tty_putc(uint8_t minor, unsigned char c) { if (minor == 1) { vtoutput(&c, 1); - } else - *uart_data = c; /* Data */ + } else if (minor == 2) + *(volatile uint8_t *)MFP_DATA = c; + else + *(volatile uint8_t *)MIDI_DATA = c; } +static const uint16_t mfp_baud[] = { + 0x0104, /* B0 */ + 0x0260, /* B50 */ + 0x0240, /* B75 */ + 0x01AF, /* B110 */ + 0x018F, /* B134 */ + 0x0180, /* B150 */ + 0x0140, /* B300 */ + 0x0120, /* B600 */ + 0x0110, /* B1200 */ + 0x0108, /* B2400 */ + 0x0104, /* B4800 */ + 0x0102, /* B9600 */ + 0x0101 /* B19200 */ + /* Hardware cannot support 38400 or higher */ +}; + void tty_setup(uint8_t minor, uint8_t flags) { + if (minor == 1) + return; + /* Mostly TOOD */ + if (minor == 3) { + return; + } if (minor == 2) { - /* FIXME: do proper mode setting */ - *uart_command = 0x01; /* DTR high, IRQ enabled, TX irq disabled 8N1 */ - *uart_control = 0x1E; /* 9600 baud */ + uint8_t speed = ttydata[2].termios.c_cflag & CBAUD; + if (speed > B19200) { + speed = B19200; + ttydata[2].termios.c_cflag &= ~CBAUD; + ttydata[2].termios.c_cflag |= B19200; + } + *(volatile uint8_t *)MFP_TCDCR &= 0xF0; + *(volatile uint8_t *)MFP_TDDR = mfp_baud[speed]; + *(volatile uint8_t *)MFP_TCDCR |= mfp_baud[speed] >> 8; } } @@ -101,127 +149,219 @@ void tty_data_consumed(uint8_t minor) { } -void tty_interrupt(void) +void ser_cts(void) { - uint8_t r = *uart_status; - if (r & 0x8) { - r = *uart_data; - tty_inproc(2,r); - } } +void ser_dcd(void) +{ +} + +void ser_ri(void) +{ +} struct vt_repeat keyrepeat; -uint8_t keymap[8]; -static uint8_t keyin[8]; -static uint8_t keybyte, keybit; -static uint8_t newkey; +uint8_t keymap[16]; +static uint8_t lastkey; static int keysdown = 0; -static uint8_t shiftmask[8] = { - 0, 0x40, 0, 0, 0, 0, 0, 0x40 -}; -static uint8_t rbit[8] = { - 0xFE, - 0xFD, - 0xFB, - 0xF7, - 0xEF, - 0xDF, - 0xBF, - 0x7F, -}; +uint8_t keyboard[1][128] = { { + 0, KEY_ESC, + '1','2','3','4','5','6','7','8','9', + '-','=', KEY_BS, KEY_TAB, + 'q','w','e','r','t','y','u','i','o','p', + '[',']',KEY_ENTER, + 0, 'a','s','d','f','g','h','j','k','l',':',';', + 0,'\\','z','x','c','v','b','n','m','.',',','/',0, + 0,0,' ',0, /* caps lock */ + KEY_F1,KEY_F2,KEY_F3,KEY_F4,KEY_F5,KEY_F6,KEY_F7,KEY_F8,KEY_F9,KEY_F10, + 0,0, + KEY_HOME,KEY_UP,0,'-',KEY_LEFT,0,KEY_RIGHT,'+',0,KEY_DOWN, + 0, KEY_INSERT,KEY_DEL, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,/* ISO ?? */ + KEY_UNDO, KEY_HELP, + '(','/','*',')', /* FIXME */ + '7','8','9', + '4','5','6', + '1','2','3', + '0','.', KEY_ENTER, +} }; -/* Row inputs: multiplexed with the joystick */ -static volatile uint8_t *pia_row = (uint8_t *)0xFF00; -/* Columns for scanning: multiplexed with the printer port */ -static volatile uint8_t *pia_col = (uint8_t *)0xFF02; -/* Control */ -static volatile uint8_t *pia_ctrl = (uint8_t *)0xFF03; - -static void keyproc(void) -{ - int i; - uint8_t key; - - for (i = 0; i < 8; i++) { - /* We do the scan in software on the Dragon */ - *pia_col = rbit[i]; - keyin[i] = ~*pia_row; - key = keyin[i] ^ keymap[i]; - if (key) { - int n; - int m = 1; - for (n = 0; n < 7; n++) { - if ((key & m) && (keymap[i] & m)) { - if (!(shiftmask[i] & m)) - keysdown--; - } - if ((key & m) && !(keymap[i] & m)) { - if (!(shiftmask[i] & m)) { - keysdown++; - newkey = 1; - keybyte = i; - keybit = n; - } - } - m += m; - } - } - keymap[i] = keyin[i]; +/* TODO */ +uint8_t shiftkeyboard[1][128] = { { + 0, KEY_ESC, + '1','2','3','4','5','6','7','8','9', + '-','=', KEY_BS, KEY_TAB, + 'q','w','e','r','t','y','u','i','o','p', + '[',']',KEY_ENTER, + 0, 'a','s','d','f','g','h','j','k','l',':',';', + 0,'\\','z','x','c','v','b','n','m','.',',','/',0, + 0,0,' ',0/* caps lock */, + KEY_F1,KEY_F2,KEY_F3,KEY_F4,KEY_F5,KEY_F6,KEY_F7,KEY_F8,KEY_F9,KEY_F10, + 0,0, + KEY_HOME,KEY_UP,0,'-',KEY_LEFT,0,KEY_RIGHT,'+',0,KEY_DOWN, + 0, KEY_INSERT,KEY_DEL, + 0,0,0,0,0,0,0,0,0,0,0,0, + 0,/* ISO ?? */ + KEY_UNDO, KEY_HELP, + '(','/','*',')', /* FIXME */ + '7','8','9', + '4','5','6', + '1','2','3', + '0','.', KEY_ENTER, +} }; + +static void keydecode(void) +{ + uint8_t c = lastkey; + + if (c == 0 || !keysdown) + return; + /* FIXME: wire up input layer */ + if ((keymap[5] & 0x02) || (keymap[6] & 0x40)) /* shifts */ + c = shiftkeyboard[0][c]; + else if (keymap[7] & 0x02) { /* Caps lock */ + if (c >= 'a' && c <= 'z') + c -= 32; } + if (keymap[2] & 0x10) /* Control */ + c &= 31; + else + c = keyboard[0][c]; + /* What should we do with alt (0x38) */ + /* FIXME: unicode */ + vt_inproc(1, c); } -uint8_t keyboard[8][7] = { - { '0', '8', '@', 'h', 'p', 'x', 10 }, - { '1', '9', 'a', 'i', 'q', 'y', 0 /* clear - used as ctrl*/ }, - { '2', ':', 'b', 'j', 'r', 'z', 27 /* break (used for esc) */ }, - { '3', ';', 'c', 'k', 's', '^' /* up */, 0 /* NC */ }, - { '4', ',', 'd', 'l', 't', '|' /* down */, 0 /* NC */ }, - { '5', '-', 'e', 'm', 'u', 8 /* left */, 0 /* NC */ }, - { '6', '.', 'f', 'n', 'v', '\t' /* right */, 0 /* NC */ }, - { '7', '/', 'g', 'o', 'w', ' ', 0 /* shift */ }, -}; +/* It's not really a grid but we need to expose it as that */ +/* FIXME: direct 37/5e/5f/59-59 to mouse */ -uint8_t shiftkeyboard[8][7] = { - { '_', '(', '\\', 'H', 'P', 'X', 10 }, - { '!', ')', 'A', 'I', 'Q', 'Y', 0 /* clear */ }, - { '"', '*', 'B', 'J', 'R', 'Z', 3 /* break */ }, - { '#', '+', 'C', 'K', 'S', '[' /* up */, 0 /* NC */ }, - { '$', '<', 'D', 'L', 'T', ']' /* down */, 0 /* NC */ }, - { '%', '=', 'E', 'M', 'U', '{' /* left */, 0 /* NC */ }, - { '&', '>', 'F', 'N', 'V', '}' /* right */, 0 /* NC */ }, - { '\'', '?', 'G', 'O', 'W', ' ', 0 /* shift */ }, +static void keybop(uint8_t c) +{ + uint8_t i = c >> 3; + uint8_t b = c & 7; + uint8_t nonshift = 1; + + if (c == 0x2A || c ==0x36 || c == 0x14 || c== 0x38 || c == 0x3A) + nonshift = 0; + + if (c & 0x80) { + keymap[i] &= ~ (1 << b); + keysdown -= nonshift; + if (c == (lastkey | 0x8)) + lastkey = 0; + return; + } + keymap[i] |= (1 << b); + lastkey = c; + keysdown += nonshift; + /* FIXME: autorepeat */ + if (keysdown && lastkey && keysdown < 3) + keydecode(); +} + +static uint8_t ikbd_buf[8]; +static uint8_t ikbd_ct; +static uint8_t ikbd_len = 1; +static uint8_t ikbd_busy; + +static const uint8_t msg_len[10] = { + 8, 6, 3, 3, 3, 3, 7, 3, 2, 2 }; -static void keydecode(void) +static void ikbd_message(void) { - uint8_t c; - - if (keymap[7] & 64) /* shift */ - c = shiftkeyboard[keybyte][keybit]; - else - c = keyboard[keybyte][keybit]; - if (keymap[1] & 64) { /* control */ - if (c > 31 && c < 127) - c &= 31; + uint8_t c = ikbd_buf[0]; + if (ikbd_ct == 1) { + if (c < 0xF6) { + ikbd_ct = 0; + ikbd_len = 1; + keybop(c); + } else + ikbd_len = msg_len[c - 0xF6]; + return; + } + /* A message completed */ + ikbd_ct = 0; + ikbd_len = 1; + switch(c) { + case 0xF6: /* Query reply */ + ikbd_busy = 0; + wakeup(&ikbd_busy); + return; + case 0xF7: /* Abs mouse */ + return; + case 0xF8: /* Rel mouse (used) */ + case 0xF9: + case 0xFA: + case 0xFB: + return; + case 0xFC: /* rtc */ + ikbd_busy = 0; + wakeup(&ikbd_busy); + /* + memcpy(ikbd_rtc, ikbd_buf + 1, 6); + ikbd_rtc_ready = 1; + wakeup(&ikbd_rtc_ready); */ + return; + case 0xFD: /* sticks both */ + case 0xFE: /* stick 0 */ + case 0xFF: /* stick 1 */ + return; } - tty_inproc(1, c); } -void platform_interrupt(void) +static void acia_key_event(uint8_t c) { - uint8_t i = *pia_ctrl; - if (i & 0x80) { - *pia_col; - newkey = 0; - keyproc(); - if (keysdown < 3 && newkey) - keydecode(); - timer_interrupt(); + ikbd_buf[ikbd_ct++] = c; + if (ikbd_ct == ikbd_len) + ikbd_message(); +} + +/* Someting happened on one of our ACIA chips - or both. We poll them on + the transmit side for now */ +void acia_interrupt(void) +{ + uint8_t st = *(volatile uint8_t *)IKBD_STATUS; + if (st & 0x80) + acia_key_event(*(volatile uint8_t *)IKBD_DATA); + st = *(uint8_t *)MIDI_STATUS; + if (st & 0x80) + tty_inproc(3, *(volatile uint8_t *)MIDI_DATA); +} + +/* + * Send a message to the keyboard controller + * + * FIXME: timeouts + */ +void ikbd_send(uint8_t *msg, uint8_t len) +{ + irqflags_t irq = di(); + while(1) { + if (ikbd_busy == 0) { + ikbd_busy = 1; + while(len) { + while(*(volatile uint8_t *)IKBD_STATUS & 2); + *(volatile uint8_t *)IKBD_DATA = *msg++; + } + irqrestore(irq); + return; + } + psleep_nosig(&ikbd_busy); + di(); } } /* This is used by the vt asm code, but needs to live at the top of the kernel */ uint16_t cursorpos; + + +/* + * Graphics and vblank + */ + +uint32_t vblankct; diff --git a/Kernel/platform-atarist/devtty.h b/Kernel/platform-atarist/devtty.h index 14c28c31..86d98072 100644 --- a/Kernel/platform-atarist/devtty.h +++ b/Kernel/platform-atarist/devtty.h @@ -1,10 +1,10 @@ #ifndef __DEVTTY_DOT_H__ #define __DEVTTY_DOT_H__ -#define KEY_ROWS 8 -#define KEY_COLS 7 -extern uint8_t keymap[8]; -extern uint8_t keyboard[8][7]; -extern uint8_t shiftkeyboard[8][7]; +#define KEY_ROWS 1 +#define KEY_COLS 128 +extern uint8_t keymap[16]; +extern uint8_t keyboard[1][128]; +extern uint8_t shiftkeyboard[1][128]; #endif diff --git a/Kernel/platform-atarist/kernel.def b/Kernel/platform-atarist/kernel.def index 3f24f44c..42ab1a4b 100644 --- a/Kernel/platform-atarist/kernel.def +++ b/Kernel/platform-atarist/kernel.def @@ -1,4 +1,2 @@ -; UZI mnemonics for memory addresses etc - -U_DATA equ 0x7D00 ; (this is struct u_data from kernel.h) -U_DATA__TOTALSIZE equ 0x300 ; 256+256+256 bytes. +#define DI_MASK $700 /* or bits for DI */ +#define EI_MASK $300 /* or bits for EI : block hblank */ diff --git a/Kernel/platform-atarist/main.c b/Kernel/platform-atarist/main.c index 878c73ba..7fe922d9 100644 --- a/Kernel/platform-atarist/main.c +++ b/Kernel/platform-atarist/main.c @@ -26,6 +26,7 @@ void memzero(void *p, usize_t len) void platform_copyright(void) { + } void do_beep(void) @@ -38,17 +39,32 @@ void map_init(void) u_block uarea_block[PTABSIZE]; -void *screenbase; +uint8_t hzticks; +uint32_t memtop; +uint16_t fdseek; +uint16_t cputype; +uint32_t screenbase; + void pagemap_init(void) { + hzticks = *(uint16_t *)0x448 ? 60 : 50; + memtop = *(uint32_t *)0x42E; + fdseek = *(uint16_t *)0x440; + cputype = *(uint16_t *)0x59E; + + kprintf("System Memory: %dK\n", memtop >> 10); + if (hzticks == 60) + kputs("NTSC System\n"); + if (cputype) + kputs("Not a 68000\n"); /* FIXME: 512K hackish setup to get going */ /* Linker provided end of kernel */ extern uint8_t _end; uint32_t e = (uint32_t)&_end; kprintf("Kernel end %p\n", e); /* Allocate the rest of memory to the userspace */ - kmemaddblk((void *)e, 0x78000 - e); + kmemaddblk((void *)e, screenbase - e); } /* Udata and kernel stacks */ diff --git a/Kernel/platform-atarist/p68000.S b/Kernel/platform-atarist/p68000.S index 511d14da..dbea7b18 100644 --- a/Kernel/platform-atarist/p68000.S +++ b/Kernel/platform-atarist/p68000.S @@ -26,21 +26,75 @@ init_early: rts init_hardware: - ; set system RAM size - move.l $42E,d0 ; TOS phystop - lsr.l #8,d0 ; into KBytes - lsr.l #2,d0 - move.w d0,ramsize - sub.w #64,d0 ; Guess for kernel - move.w d0,procmem ; guesses for now - bsr install_vectors - rts + ; + ; We use the ROM to do the initial set up. We must do this + ; before we steal all the vectors + ; + move.w #4,-(sp) + trap #14 + and #3,d0 + move.b d0,videomode + move.b #50,videorows ; 640x400 is special + move.b #49,videobot + cmpb #2,d0 + beq mode_ok ; different monitor so leave it alone + move.b #25,videorows ; 640x200 mode + move.b #24,videobot + + ; Set our palette + pea palette + move.w #6,-(sp) + trap #14 + addq #6,sp + + move.b #1,d0 +mode_ok: + move.w d0,-(sp) ; Stack resolution wanted + + move.w $42E,d0 ; Top of RAM + sub.l #32000,d0 ; Frame buffer space + move.l d0,screenbase ; Save our video base + + move.l d0,-(sp) ; physical base + move.l d0,-(sp) ; logicalbase + move.w #5,-(sp) ; setScreen + trap #14 + lea 12(sp),sp + + ; set system RAM size + move.l $42E,d0 ; TOS phystop + lsr.l #8,d0 ; into KBytes + lsr.l #2,d0 + move.w d0,ramsize + sub.w #64,d0 ; Guess for kernel + sub.w #32,d0 ; Video memory + move.w d0,procmem ; guesses for now + bsr install_vectors + move.w #0,a0 + move.l #int2,$68(a0) ; hblank autvector + move.l #int4,$70(a0) ; vblank autovector + move.l #int_mfp1,$104(a0) ; DCD + move.l #int_mfp2,$108(a0) ; CTS + move.l #int_mfp5,$114(a0) ; 200Hz + move.l #int_mfp6,$118(a0) ; IKBD/Midi + move.l #int_mfp9,$124(a0) ; Tx Error + move.l #int_mfp10,$128(a0) ; Tx Done + move.l #int_mfp11,$12c(a0) ; RX Error + move.l #int_mfp12,$130(a0) ; RX Data + move.l #int_mfp14,$138(a0) ; RI + rts +palette: + word $0000 ; black + word $0F00 ; red + word $00F0 ; green + word $0FFF ; white + ; We let the others go to trash ; Nothing to do in 68000 - all set up once at boot ; program_vectors: - rts + rts ; ; All mapped all the time @@ -50,49 +104,262 @@ map_process: map_kernel: map_restore: map_save: - rts + rts + +; +; Interrupt vectors +; + +; Hblank +int2: + ori.w #0300,sr ; Fix up if something messes with sr + rte +; Vblank +; Trigger a wakeup if anyone is waiting on blanking events +; +int4: + add.w #1,vblankct + tst.b vblankw + beq int4_out + movem.l a0/a1/d0/d1,-(sp) + pea vblankct + bsr wakeup + addq #4,sp + movem.l (sp)+,a0/a1/d0/d1 +int4_out: + rte +; +; The level 6 handlers are autovectored +; +int_mfp1: ; DCD on the serial + movem.l a0/a1/d0/d1,-(sp) + bsr ser_dcd + movem.l (sp)+,a0/a1/d0/d1 + rte +int_mfp2: ; CTS on the seriall + movem.l a0/a1/d0/d1,-(sp) + bsr ser_cts + movem.l (sp)+,a0/a1/d0/d1 + rte +int_mfp5: ; 200Hz timer + movem.l a0/a1/d0/d1,-(sp) + bsr timer_interrupt + movem.l (sp)+,a0/a1/d0/d1 + rte +int_mfp6: ; ACIA interrupts + movem.l a0/a1/d0/d1,-(sp) + bsr acia_interrupt + movem.l (sp)+,a0/a1/d0/d1 + rte +int_mfp9: ; MFP serial transmit error + ; FIXME what do we need to do to clear down ? + rte +int_mfp10: ; MFP tx complete + ; FIXME: blocked for now using polling + rte +int_mfp11: ; MFP rx error + ; FIXME: how to clear + rte +int_mfp12: ; MFP receive + movem.l a0/a1/d0/d1,-(sp) + move.b $FFFA2D,d0 + move.l d0,-(sp) + pea.l 2 + bsr tty_inproc + addq #8,sp + movem.l (sp)+,a0/a1/d0/d1 + rte +int_mfp14: ; MFP ring indicate + movem.l a0/a1/d0/d1,-(sp) + bsr ser_ri + movem.l (sp)+,a0/a1/d0/d1 + rte ; outchar: Wait for UART TX idle, then print the char in d0 outchar: - move.w d0,-(sp) + move.w d0,-(sp) outcharw: - move.b $FFFFFA13,d0 - btst #2,d0 - beq outcharw - move.w (sp)+,d0 - move.b d0,$FFFFFA2D + move.b $FFFA13,d0 + btst #2,d0 + beq outcharw + move.w (sp)+,d0 + move.b d0,$FFFA2D + rts + +; +; There are 3 possible modes that we care about +; We number then by planes-1 so the mode is our counter for dbra +; 0 640x400x1 planar +; 1 320x200x4 planar +; 3 640x200x2 planar +; +vaddr: + ; X in D1 Y in D0 + ; returns address in A1, mode in D1 + + mulu.w vwidth,d0 + mulu.w vshift,d2 + move.b d1,d3 + and.w #1,d3 + and.w #$fffe,d1 + lsl.w d2,d1 + add.w d1,d0 + add.w d3,d0 + move.l screenbase,a0 + add.w d0,a0 + move.w videomode,d2 + move.w vlen,d3 ; bytes per scan line minus + ; those we write rts +aligned: +; +; FIXME: check how gcc pushes uint8_t's in this case and set offsets +; properly +; plot_char: - ; y, x, c - move.l screenbase,a0 ; Screen base from TOS move.w 4(sp),d0 - mulu.w #640,d0 ; Always under 64K - adda.l d0,a0 - adda.w 6(sp),a0 ; do is now our offset + move.w 6(sp),d1 + move.l d2,-(sp) + move.l d3,-(sp) + +plot_char_1: + ; Save Regs - move.w 8(sp),d0 ; character + bsr vaddr + + move.w 16(sp),d0 ; character lsl.w #3,d0 ; into font position lea fontdata_8x8,a1 ; font adda.w d0,a1 - moveq #7,d1 + moveq #7,d0 +; +; Really we need to expand this per mode and to do colour +; plotit: - move.b (a1)+,(a0) - add.l #80,a0 - dbra d1,plotit + move.w d2,d1 ; count by mode +plotrow: + move.b (a1),(a0) + add.w #2,a0 + dbra d1,plotrow + add.w d3,a0 ; line length for mode + dbra d0,plotit + ; Restore regs + move.l (sp)+,d3 + move.l (sp)+,d2 rts -scroll_down: +; +; 640x400 is our special case - the bytes per line is half the other +; modes +; scroll_up: + move.l screenbase,a0 + move.w #640,d0 + move.w #32000-640-1,d1 + tst.w videomode + beq hires + move.w #1280,d0 + move.w #32000-1280-1,d1 +hires: + move.l a0,a1 + add.w d0,a1 +scrollu: move.l (a1)+,(a0)+ + dbra d1,scrollu + rts + +scroll_down: + move.l screenbase+32000,a0 + move.w #640,d0 + move.w #32000-640-1,d1 + tst.w videomode + beq hiresd + move.w #1280,d0 + move.w #32000-1280-1,d1 +hiresd: + move.l a0,a1 + sub.w d0,a1 +scrolld: move.l -(a1),-(a0) + dbra d1,scrolld + rts + clear_lines: + move.l 4(sp),d0 + move.l d2,-(sp) + move.l d3,-(sp) + move.w #0,a1 + bsr vaddr + ; d2 is mode count, d3 is extra words/line, a0 is address + move.l 6(sp),d0 + bra wipen +wipe: + move.w d2,d1 +wipe1: clr.w (a0)+ + dbra d2,wipe1 + add.w d3,a0 +wipen: + dbra d0,wipe + move.l (sp)+,d3 + move.l (sp)+,d2 + rts + clear_across: + rts + cursor_on: -cursor_off: + move.w 4(sp),d0 ; check stacking + move.w 6(sp),d1 + move.l d2,-(sp) + move.l d3,-(sp) + bsr vaddr + moveq #7,d0 + lea.l cursordata,a1 + movem.l a0/d2/d3,(a1) +; +; Really we need to expand this per mode and to do colour +; +xorit: + move.w d2,d1 ; count by mode +xorrow: + eor.b #255,(a0) + add.w #2,a0 + dbra d1,xorrow + add.w d3,a0 ; line length for mode + dbra d0,xorit + move.l (sp)+,d3 + move.l (sp)+,d2 + rts cursor_disable: +cursor_off: + move.l d2,-(sp) + move.l d3,-(sp) + lea.l cursordata,a1 + movem.l (a1),a0/d2/d3 + bra xorit + vtattr_notify: rts .section data kernel_flag: byte 1 + +cursordata: word 0 + word 0 + word 0 + word 0 +videorows: + byte 0 +videobot: + byte 0 +vwidth: + byte 640 +vshift: + byte 0 +vlen: + byte 638 +videomode: + byte 1 +vblankw: + byte 1 -- 2.34.1