Jump to content
IGNORED

BASIC graphics subroutines in assembler


Recommended Posts

I found a book with BASIC graphics subroutines in assembler but I'm unable to get the "GRAFIC" subroutine to work. I'm at loss why exactly. The book is Assembly Language Programming For the Atari Computers. I'm using WUDSN, MADS, and Altirra. Below are the subroutines. I'm calling it just by loading a value into accumulator and then jsr grafic, which results in just a blue screen when i run it. No change in graphics mode.

 

The last row was originally: NAME .BYTE "S:",$9B . Perhaps that has got something to do with it? Any help would be much appreciated.

; ******************************
; CIO equates
; ******************************
ICHID =    $0340
ICDNO =    $0341
ICCOM =    $0342
ICSTA =    $0343
ICBAL =    $0344
ICBAH =    $0345
ICPTL =    $0346
ICPTH =    $0347
ICBLL =    $0348
ICBLH =    $0349
ICAX1 =    $034A
ICAX2 =    $034B
CIOV  =    $E456
; ******************************
; Other equates needed
; ******************************
COLOR0 =   $02C4
COLCRS =   $55
ROWCRS =   $54
ATACHR =   $02FB
STORE1 =   $CC
STOCOL =   $CD
       *=  $600
; ******************************
; The SETCOLOR routine
; ******************************
; Before calling this routine,
; the registers should be set
; just like the BASIC SETCOLOR:
; SETCOLOR color,hue,luminance
;    stored respectively in
;   X reg.,accumulator,Y reg.
SETCOL
       ASL         ; Need to multiply
       ASL         ; hue by 16, and
       ASL         ; add it to lumimance.
       ASL         ; Now hue is * 16
       STA STORE1    ; temporarily
       TYA           ; So we can add
       CLC           ; Before adding
       ADC STORE1    ; Now have sum
       STA COLOR0,X  ; Actual SETCOLOR
       RTS           ; All done
; ******************************
; The COLOR command
; ******************************
; For these routines, we will
; simply store the current COLOR
; in STOCOL, so the COLOR
; command simply requires that
; the accumulator hold the value
; "n" in the command COLOR n
COLOR
       STA STOCOL    ; That's it!
       RTS           ; All done
; ******************************
; The GRAPHICS command
; ******************************
; The "n" parameter of
; a GRAPHICS n command will be
; passed to this routine in the
; accumulator
GRAFIC
       PHA           ; Store on stack
       LDX #$60      ; IOCB6 for screen
       LDA #$C       ; CLOSE command
       STA ICCOM,X   ; in command byte
       JSR CIOV      ; Do the CLOSE
       LDX #$60      ; The screen again
       LDA #3        ; OPEN command
       STA ICCOM,X   ; in command byte
       LDA #NAME&255 ; Name is "S:"
       STA ICBAL,X   ; Low byte
       LDA #NAME/256 ; High byte
       STA ICBAH,X
       PLA           ; Get GRAPHICS n
       STA ICAX2,X   ; Graphics mode
       AND #$F0      ; Get high 4 bits
       EOR #$10      ; Flip high bit
       ORA #$C       ; Read or write
       STA ICAX1,X   ; n+16, n+32 etc.
       JSR CIOV      ; Setup GRAPHICS n
       RTS           ; All done
; ******************************
; The POSITION command
; ******************************
; Identical to the BASIC
; POSITION X,Y command.
; Since X may be greater than
; 255 in GRAPHICS 8, we need to
; use the accumulator for the
; high byte of X.
POSITN
       STX COLCRS    ; Low byte of X
       STA COLCRS+1  ; High byte of X
       STY ROWCRS    ; Y position
       RTS           ; All done
; ******************************
; The PLOT command
; ******************************
; We'll use the X,Y, and A just
; like in the POSITION command.
PLOT
       JSR POSITN    ; To store info
       LDX #$60      ; For the screen
       LDA #$B       ; Put record
       STA ICCOM,X   ; Command byte
       LDA #0        ; Special case of
       STA ICBLL,X   ;  I/O using the
       STA ICBLH,X   ;  accumulator
       LDA STOCOL    ; Get COLOR to use
       JSR CIOV      ; Plot the point
       RTS           ; All done
; ******************************
; The DRAWTO command
; ******************************
; We'll use the X,Y, and A just
; like in the POSITION command
DRAWTO
       JSR POSITN    ; To store info
       LDA STOCOL    ; Get COLOR
       STA ATACHR    ; Keep CIO happy
       LDX #$60      ; The screen again
       LDA #$11      ; For DRAWTO
       STA ICCOM,X   ; Command byte
       LDA #$C       ; As in XIO
       STA ICAX1,X   ; Auxiliary 1
       LDA #0        ; Clear
       STA ICAX2,X   ; Auxiliary 2
       JSR CIOV      ; Draw the line
       RTS           ; All done
; ******************************
; The FILL command
; ******************************
; We'll use the X,Y, and A just
; like in the POSITION command.
; This is similar to DRAWTO
FILL
       JSR POSITN    ; To store info
       LDA STOCOL    ; Get COLOR
       STA ATACHR    ; Keep CIO happy
       LDX #$60      ; The screen again
       LDA #$12      ; For FILL
       STA ICCOM,X   ; Command byte
       LDA #$C       ; As in XIO
       STA ICAX1,X   ; Auxiliary 1
       LDA #0        ; Clear
       STA ICAX2,X   ; Auxiliary 2
       JSR CIOV      ; FILL the area
       RTS           ; All done
; ******************************
; The LOCATE command
; ******************************
; We'll use the X,Y, and A just
; like in the POSITION command
; and the accumulator will
; contain the LOCATEd color
LOCATE
       JSR POSITN    ; To store info
       LDX #$60      ; The screen again
       LDA #7        ; Get record
       STA ICCOM,X   ; Command byte
       LDA #0        ; Special case of
       STA ICBLL,X   ; data transfer
       STA ICBLH,X   ; in accumulator
       JSR CIOV      ; Do the LOCATE
       RTS           ; All done
; ******************************
; The screen's name
; ******************************
NAME   dta d "S:",$9B
Link to comment
Share on other sites

That last line should be OK - for the CIO Open command you just need the device prefix and Return $9B code as a minimum.

 

By the looks these routines are just building blocks and you need to call them with appropriate parameters.

Like the GRAFIC sub - it expects A to contain the graphcis mode so you'd want to make sure to call it as such (try 15 as a test to get Gr. 15)

 

Also note - if you use fullscreen graphics modes (no text window), this can have implications if you're using Basic or in fact probably most other language processor environments. Once the program finishes there will be output to device #0 E: which will override the graphics mode that's been setup and open a new text screen.

The GRAFIC sub appears to process the mode the same way Basic does, ie +16 requests no text window.

 

A good way to deal with this is don't let the program just end, do something like a line that waits for key input of just does a GOTO itself and use Break to end the program.

Edited by Rybags
  • Like 1
Link to comment
Share on other sites

Thank you for your input Rybags. I am actually calling them with appropriate parameters. This snippet only includes the subroutines. My test program actually only sets a value for A and calls for GRAFIC subroutine and then loops infinitely. I did check that it actually goes through the routine.

 

I have seen two very similar versions of these same subroutines and I have been unable to set graphics mode with either of them for some reason. I'm sure there's a better way to do all this, I'm just curious why it wouldn't work. The fact that these books sometimes have typos in code snippets doesn't really help my paranoia :) .

Edited by whisperer_in_darkness
Link to comment
Share on other sites

I suspect there might be problems in the source code.

 

Look specifically at instructions where they're trying to use the high or low portion of a 16-bit value.

The old way with Atari's AsmEd was like:

 

LDA #LABEL&255

or

LDA #LABEL/256

 

With the more modern assemblers, even Mac-65 the preferred method is:

 

LDA #<LABEL

or

LDA #>LABEL

 

 

Also it's worthwhile using debug in the emuator to scroll through the code when it's loaded into Ram - check that what was assembled matches what it should actually be. Not much effort for short routines like these.

Link to comment
Share on other sites

I think I got it. I installed another assembler where the correct syntax is:

NAME   .BYTE "S:",$9B

And the code definitely works! I then had a look at MADS documentation and there are in fact two DTA string data types:

 

c ATASCII string, delimited by '' or ""; * at the end encodes inverse
video, e.g. dta c'abecadlo'*
d INTERNAL string, delimited by '' or ""; * at the end encodes inverse
video, e.g. dta d'abecadlo'*

Looks like it needs to be ATASCII string like this:

dta c "S:",$9B

I'm not exactly sure when to use internal and when ATASCII but I guess I'll have to look it up.

Edited by whisperer_in_darkness
Link to comment
Share on other sites

Internal = screen codes, generally you only use that if storing characters directly to screen memory or indexing into a character set e.g. redefining.

 

Internal codes are different so that Gr. 1 and 2 which only have 64 characters could have alpha and numeric within the same charset.

  • Like 3
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...