.include "atari.inc" .export _clrtobot, _clrtoeol, _clr_screen, _clrtoline, _cspaces, _cblank, _backspace, _cprint_pipe, _cprint_bang, _cspace, _cputc_s, _comma_space, _cprint_colon_space, _cprint_question_space, _cprint_period, _cprint_taipan_prompt .export _rvs_on, _rvs_off .import mul40 ; from cc65's runtime .importzp tmp3 ; ditto .import _revflag ; conio/revers.s .import bump_destptr ; these two are .importzp destptr ; from draw_lorcha.s .importzp sreg .import _cprintulong, _cputc, _cprint_taipan .ifdef CART_TARGET .segment "HIGHCODE" .else .code .endif ; void clr_screen(void); ; void clrtobot(void); ; void clrtoeol(void); ; void clrtoline(unsigned char line); ; this stuff doesn't disturb conio's (and the OS's) idea of the ; current cursor position. It's *way* faster than writing them in ; C in terms of cclear() (which uses one cputc() call per blank). _clr_screen: ; same as gotoxy(0,0); clrtobot(); lda #0 sta ROWCRS sta COLCRS _clrtobot: ; same as clrtoline(24); lda #24 bne _clrtoline _clrtoeol: lda ROWCRS ; fall through to _clrtoline _clrtoline: sta tmp3 ; stash our arg ;lda #0 ;sta OLDCHR ; stop conio from redrawing stuff after we clear it, ; no longer needed with our custom conio. ; setup destptr to start of current line, NOT ; current cursor position. lda ROWCRS jsr mul40 ; AX = A*40 (addr of start-of-row) clc adc SAVMSC ; add AX to screen pointer sta destptr txa adc SAVMSC+1 sta destptr+1 ; X = current row, Y = current column. Stop clearing a line when Y == 40, ; we're done when X == 24. Apologies, the names X and Y are backwards ; compared to proper Cartesian coordinates. ldx ROWCRS ldy COLCRS lda #0 clrloop: sta (destptr),y ; blank a character (A == 0, screen code for a space) iny cpy #40 bne clrloop ldy #0 inx cpx tmp3 bcs done jsr bump_destptr lda #0 tay beq clrloop done: rts _cspaces: sta tmp3 @lp: jsr _cspace dec tmp3 bne @lp rts _backspace: dec COLCRS lda #1 ; fall through to _cblank _cblank: tax lda COLCRS pha lda ROWCRS pha txa jsr _cspaces pla sta ROWCRS pla sta COLCRS rts _rvs_on: lda #$80 .byte $2c ; BIT absolute opcode _rvs_off: lda #0 sta _revflag rts ; micro-optimizations here. ; the stuff below might be a bit hard to follow, but it saves code. ; calling this: cputs("? "); ; emits code like this: ; lda #Lxxx ; jsr _cputs ; ...which is 9 bytes per call (plus 3 bytes for the "? " string itself). ; replacing each cputs("? "); with cprint_question_space() means 3 bytes ; per call (a JSR). there are 3 'some char followed by a space' routines ; here, totalling 10 bytes. the actual space is printed by code shared ; with cspace(). ; also, there are 5 'print a single character' routines. each one would ; normally be cputc('X'), which compiles to: ; lda #'X' ; jsr _cputc ; ...or 5 bytes each. we have 5 of them, so 25 bytes. using fall-thru ; and the BIT trick, they condense down to 17 bytes. ; if you're not familiar with the "BIT trick" to skip a 2-byte instruction, ; the stuff below looks like gibberish... here's a mini-tutorial: ;store1: ; lda #1 ; .byte $2c ; this is the opcode for BIT absolute ;store2: ; lda #2 ; sta $0600 ; rts ; if entered via "jsr store1", the above code fragment executes these ; instructions: ; lda #1 ; bit $02A9 ; $A9 is the LDA immediate opcode, 02 is the #2 ; sta $0600 ; rts ; if entered via "jsr store2", it's ; lda #2 ; sta $0600 ; rts ; the "bit $02a9' doesn't affect any registers other than the flags, ; and the "sta $0600 : rts" part doesn't depend on any of the flags, ; so the BIT is effectively a no-op that "masks" the 2-byte LDA #2 ; instruction "hidden" as its operand. ; ", Taipan? " ; using fall-thru here saves 3 bytes (normally the last instruction ; would be "jmp _cprint_question_space") _cprint_taipan_prompt: jsr _comma_space jsr _cprint_taipan ; fall thru ; each entry point here prints one character followed by a space ; "? " _cprint_question_space: lda #'?' .byte $2c ; ": " _cprint_colon_space: lda #':' .byte $2c ; ", " _comma_space: lda #',' jsr _cputc ; fall thru ; each entry point here prints one character _cspace: lda #' ' .byte $2c _cprint_pipe: lda #'|' .byte $2c _cputc_s: lda #'s' .byte $2c _cprint_period: lda #'.' .byte $2c _cprint_bang: lda #'!' jmp _cputc