.include "atari.inc" .include "conio/mul40.s" .export _clrtobot, _clrtoeol, _clr_screen, _clrtoline, _cspaces, _cblank, _cblankto, _backspace, _cprint_pipe, _cprint_bang, _cspace, _cputc_s, _comma_space, _cprint_colon_space, _cprint_question_space, _cprint_period, _cprint_taipan_prompt, _plus_or_space, _gotox0y22, _gotox0y3, _gotox0y, _gotox0y3_clrtoeol,_cputc0, _set_orders, _pluralize, _print_combat_msg .export _rvs_on, _rvs_off .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, _timed_getch, _orders .import _turbo .import _print_msg .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 ; we'd have had to do this if ROWCRS weren't zero-page. .byte $2c ; see bit trick explanation below, if you don't recognize this. _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 _cblankto: sec sbc COLCRS beq done bcs _cblank 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 _cputc0: lda #'0' .byte $2c _cprint_pipe: lda #'|' .byte $2c _cputc_s: lda #'s' .byte $2c _cprint_period: lda #'.' .byte $2c _cprint_bang: lda #'!' jmp _cputc ; extern void plus_or_space(unsigned char b); _plus_or_space: tax beq @spc lda #'+' + 128 ; inverse plus .byte $2c @spc: lda #' ' ldx #39 stx COLCRS ldx #15 stx ROWCRS jmp _cputc ; extern void gotox0y22(void); _gotox0y22: lda #22 .byte $2c ; extern void gotox0y3(void); _gotox0y3: lda #3 ; extern void gotox0y(char y); _gotox0y: sta ROWCRS lda #0 sta COLCRS rts ; extern void gotox0y3_clrtoeol(void); _gotox0y3_clrtoeol: jsr _gotox0y3 jmp _clrtoeol ; extern void print_combat_msg(const char *); _print_combat_msg: pha jsr _gotox0y3 pla jsr _print_msg jmp _clrtoeol ; extern void __fastcall__ pluralize(int num); _pluralize: cmp #1 bne _cputc_s txa bne _cputc_s rts ; extern void set_orders(void); _set_orders: lda _turbo ; in turbo fight mode? beq @sowait ; no, so wait like usual lda CH ; turbo = yes, did user hit a key? cmp #$ff bne @sowait ; yes, wait like usual rts @sowait: lda #0 sta _turbo jsr _timed_getch cmp #$60 ; capital letter? bcs @sonoturbo ; nope, disable turbo @soturbo: ora #$20 ; convert to lowercase sta _turbo ; enable turbo ;;; sta COLOR4 ; for debugging @sonoturbo: ldx #3 @solp: cmp orders_tbl-1,x beq @returnx dex bne @solp stx _turbo ; invalid order, disable turbo rts @returnx: stx _orders rts .rodata orders_tbl: .byte "frt"