diff options
-rw-r--r-- | Makefile | 5 | ||||
-rw-r--r-- | dla.s | 75 | ||||
-rw-r--r-- | io.s | 147 | ||||
-rw-r--r-- | printint.s | 37 |
4 files changed, 130 insertions, 134 deletions
@@ -4,7 +4,7 @@ PERL = perl all: dla.xex -dla.xex: dla.s io.s dlatbl.s xex.inc +dla.xex: dla.s io.s dlatbl.s xex.inc printint.s $(CL65) $(CL65FLAGS) -l dla.list -Ln dla.labels -t none -o dla.xex dla.s dlatbl.s: mkdlatbl.pl @@ -15,3 +15,6 @@ clean: test: all atari800 -turbo dla.xex + +%.xex: %.s + $(CL65) $(CL65FLAGS) -t none -o $@ $< @@ -49,9 +49,13 @@ xex_org loadaddr .include "io.s" ; printchrx and getchrx + .include "printint.s" ; init stuff gets done once, at startup init: + lda #0 + sta seedtype + sta LMARGN lda SDMCTL sta old_dma lda SDLSTL @@ -59,6 +63,12 @@ init: lda SDLSTH sta old_dl+1 + ; set default particles (if user just hits return) + lda #<DEFAULTPART + sta maxparticles + lda #>DEFAULTPART + sta maxparticles+1 + ; "New" option jumps here, restore GR.0 screen getargs: lda #$90 @@ -74,22 +84,19 @@ getargs: lda old_dma sta SDMCTL - ; set default particles (if user just hits return) - lda #<DEFAULTPART - sta maxparticles - lda #>DEFAULTPART - sta maxparticles+1 - ; print banner and prompt. -printmsg: - ldx #0 -pmloop: - lda msg,x - beq pmdone - jsr printchrx - inx - bne pmloop -pmdone: +printbanner: + lda #<banner + ldx #>banner + jsr printmsg + + lda maxparticles + ldx maxparticles+1 + jsr printdecw + + lda #<prompt + ldx #>prompt + jsr printmsg ; use CIO to read input, so user can use backspace/etc. jsr readline @@ -100,13 +107,13 @@ pmdone: lda #0 sta CIX jsr AFP ; ASCII to floating point, result in FR0 - bcs printmsg ; C set means error + bcs printbanner ; C set means error jsr FPI ; convert FR0 to integer (result in FR0) - bcs printmsg + bcs printbanner lda FR0 tax ora FR0+1 ; we don't accept 0 for an answer! - beq printmsg + beq printbanner lda FR0+1 stx maxparticles sta maxparticles+1 @@ -114,21 +121,21 @@ pmdone: usedefault: ; print seed type prompt - ldx #0 -pm2loop: - lda msg2,x - beq pm2done - jsr printchrx + lda #<seedprompt + ldx #>seedprompt + jsr printmsg + ldx seedtype inx - bne pm2loop -pm2done: + txa + jsr printdecb + lda #<seedprompt2 + ldx #>seedprompt2 + jsr printmsg readgen: jsr getchrx cmp #$9b - bne noteol - lda #$31 -noteol: + beq generate cmp #$31 bcc readgen cmp #$35 @@ -700,13 +707,17 @@ readline: ;;;;; end of executable code, data tables from here on out. ; prompts -msg: +banner: .byte $7d, "Diffusion Limited Aggregate",$9b .byte "Urchlay's ASM version 0.0.7",$9b,$9b .byte "Particle count range: 1 to 65535",$9b - .byte "How many particles [",.sprintf("%d", DEFAULTPART),"]? ",$0 -msg2: - .byte $9b,"Seed Type: ",$9b,"1=Dot 2=Plus 3=4Dots 4=Line [1]? ",$0 + .byte "How many particles [",$0 +prompt: + .byte "]? ",$0 +seedprompt: + .byte $9b,"Seed Type: ",$9b,"1=Dot 2=Plus 3=4Dots 4=Line [",$0 +seedprompt2: + .byte "]? ",$0 ; screen codes for menu menumsg: @@ -1,104 +1,3 @@ - ; 20220930 bkw, aka Urchlay on libera IRC, aka urchlay@slackware.uk: - - ; Example code for calling CIO through the back door, like BASIC does. - ; Provided under the terms of the WTFPL: Do WTF you want to with this. - - ; Verbose documentation here. To skip to the actual code, search for - ; three ; characters. - - ; There's a lot of old code that calls the OS ROM's print-character - ; and read-character addresses directly. These were never published - ; by Atari as part of their API... and in fact they changed between - ; the 400/800 and XL/XE, which is a major reason why certain software - ; is "OS B only" or "XL only". People coming from other platforms such - ; at the C=64 or Apple II were used to their ROMs having fixed - ; addresses to JSR to, for print-character and read-character, and - ; so they used $F6A4 to print and $F6E2 to read... which were - ; never guaranteed by Atari not to change. And they did change, - ; in the XL OS. - - ; The pedantically correct way to print a character is to set up - ; a 1-byte buffer for IOCB #0, and call CIOV with ICCOM set to - ; $09 (aka 'put record'). Even Atari decided this was too much - ; work, so they also provided a handy "put-one-byte" vector in - ; EDITRV, which gets copied to ICPTL/H when the OS opens the E: - ; device... BASIC uses this to print characters, and you can, too. It - ; works on any revision of the Atari OS, because it's part of the - ; OS specification: if it *didn't* work on some OS version, neither - ; would Atari BASIC, which would count as a show-stopper! - - ; Atari didn't provide a similar slot in the IOCB for the - ; get-one-byte vector... and generally, if you're interested in - ; reading input one character at a time, you don't want IOCB #0 (E:) - ; anyway. You want the K: device (which returns immediately after - ; each keypress, rather than waiting for a whole line of input). The - ; correct way to read from the keyboard is to open an IOCB (other - ; than #0) to the K: device, set up that IOCB, including a 1-byte - ; buffer, and call CIOV with ICCOM set to $05 (aka get-record). But - ; it turns out that the K: device has a get-one-byte routine that (a) - ; can be found in a published location (KEYBDV table) that doesn't - ; change with ROM revision, and (b) works without even having an IOCB - ; open for K:. - - ; The vectors are stored as "address minus one", because they're - ; intended to be called via the RTS instruction (probably Atari did - ; this because the JSR instruction doesn't have an indexed mode like - ; JMP does). Read on, to see how to call them. The calling sequence - ; isn't as convenient as the illegal entry points (or the Commodore's - ; Kernal, which does publish print-acumulator and get-1-byte - ; vectors), but it's a lot less code than the 'proper' IOCB setup - ; would be. And if you copy/paste from this file, you just call these - ; subroutines in your code (as convenient as the Commodore). - - ; You are welcome to copy the code in this file into your own - ; project. It's unencumbered: I release it under the WTFPL. I would - ; just say it's public domain, but I have been told by people who - ; ought to know that some countries don't actually recognize public - ; domain in their law. WTFPL explicitly says you can do whatever you - ; want with this. - - ; Examples: - - ; You could make your own "memo pad mode" with this: - ; - ; main: - ; jsr getchr - ; jsr printchr - ; jmp main - - ; Print a null-terminated string, up to 256 bytes long: - ; - ; ldx #0 - ; msgloop: - ; lda message,x - ; beq msgdone - ; jsr printchrx - ; inx - ; bne msgloop - ; msgdone: - ; rts ; or whatever other code goes here... - ; - ; message: .byte "Hello, World!",$9b,$00 - - ; Environment: - - ; The code depends on a few symbols (equates) being defined. How you - ; do this depends on the assembler you're using. - - ; .include "atari.inc" ; for ca65 - ; .include "sysequ.m65" ; for atasm - ; include atari8.h ; dasm, if it actually had this file :( - - ; If your assembler doesn't have a file of Atari symbols, use: - ; ICPTL = $0346 - ; ICPTH = $0347 - ; KEYBDV = $E420 - ; EDITRV = $E400 ; only if you change getchr to use this. - ; ...of course your assembler might want EQU or .EQU instead of = signs. - - ; .org <wherever> ; your assembler may want org without the dot, or *= - - ;;; Start of actual code. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Subroutine: printchr @@ -159,6 +58,28 @@ getchr: ; remember that they call printchr and getchr, so you have to copy ; those also. + ; Subroutine: Print A register in hex. + ; Preserves X (but not A or Y). +printhex: + pha ; stash argument + lsr ; shift right 4 times, + lsr ; to get the first hex digit + lsr ; (aka nybble) into the bottom + lsr ; 4 bit positions. + jsr printxdig ; print the top nybble. + pla ; restore original value... + and #$0f ; mask off high nybble + ; fall through to print the 2nd digit. + + ; Subroutine: Print a nybble (A=0 to $0f) in hex. +printxdig: + ora #$30 ; 0-9 now ASCII... + cmp #$3a ; do we have A-F? + bcc xok ; if not, don't adjust it + adc #$26 ; A-F now ASCII: $3a + $26 + 1 (carry always set) = $61 (a) +xok: + ; fall through to print the digit. + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Subroutine: printchrx ; @@ -201,3 +122,27 @@ getchrx: tax ; from stack. tya ; restore return value to A. rts ; regular RTS. + + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; Subroutine: printmsg + ; + ; Print the null-terminated message pointed to by A (low) and X (high). + ; Limited to <= 256 character messages. + ; + ; Trashes all registers, plus uses FR0 for temp storage. + ; Calls printchr. + ; +printmsg: + sta FR0 + stx FR0+1 + lda #0 + sta FR0+2 +pmloop: + ldy FR0+2 + lda (FR0),y + beq pmdone + jsr printchr + inc FR0+2 + bne pmloop +pmdone: + rts diff --git a/printint.s b/printint.s new file mode 100644 index 0000000..6d65f93 --- /dev/null +++ b/printint.s @@ -0,0 +1,37 @@ + +; use FP math pack to print 8- or 16-bit integers in decimal. + +;;; Subroutine: printdecb +;;; Print byte in accumulator, in decimal +;;; Trashes all regs/flags +printdecb: + ldx #0 + ; fall thru to printdecw + +;;; Subroutine: printdecw +;;; Print word in A/X, in decimal (X is high byte) +;;; Trashes all regs/flags +; one annoyance here: we need (zp),y addressing because FASC actually +; updates INBUFF to point to the first non-zero ASCII digit (this is +; how we skip leading zeroes), but we don't have a "printchry" that +; preserves Y, so we end up using X for a counter and copying it to Y +; every loop iteration... +; also, why did I pick A/X instead of X/Y like FLD(0|1)R uses? in case +; someone ever wants to call this from C code in cc65... +printdecw: + sta FR0 + stx FR0+1 + jsr IFP + jsr FASC + ldx #0 +pwloop: + txa + tay + lda (INBUFF),y + php + and #$7f + jsr printchrx + inx + plp + bpl pwloop + rts |