Login
Back to forumReply to this topicGo to last reply

Posted By

George
on 2011-09-11
15:13:18
 Draw a single pixel in assembler

Could you send me an example how to do this in assembler with Csabo's Plus4/IDE:

1) Graphics On
2) clear screen
3) draw a single pixel
3) check if space is pressed
4) graphics off.

Please comment the code if possible.

Posted By

Csabo
on 2011-09-11
15:28:42
 Re: Draw a single pixel in assembler

Sent by email.

Drawing a single pixel is not that hard. Two main steps: get the pointer to the pixel (it's just math), change the byte at that address by adding a bit (OR operation). In my code I cheated a bit, X can only take a value from 0-255 (not 0-319).

Let me know if something is unclear!

Posted By

George
on 2011-09-11
15:43:13
 Re: Draw a single pixel in assembler

Thanks a lot. i do not fully understand this here:

ORG $1001-2 <- this start address, but why -2?
DW $1001 <- whats this?

<-- what do you do here in this block?
DW nextln,0 ; second word is line number
DB $9E
IF start > 9999
DB "0"+start/10000
ENDIF
DB "0"+(start/1000)%10,"0"+(start/100)%10,"0"+(start/10)%10,"0"+start%10,0
nextln DB 0,0

ptr = $D0 <- you set a variable

start
SEI <- you stop interrupts here? Why?
STA $FF3F <- why this here?

Posted By

gerliczer
on 2011-09-11
16:31:03
 Re: Draw a single pixel in assembler

Hi George,

The line ORG $1001-2 will make the code compiled to address $0FFF. This is necessary, because program files start with load address. The next line DW $1001 simply defines this address, but if it is not at the correct position then the complied file will be loaded at the wrong memory area. For example if the first line would be ORG $1001, then everything that follows will be complied at two bytes offset. This would result in JMPs' and JSRs' address having two byte offsets too, so jumps would occur to wrong addresses.

The next block is the definition of one BASIC line that will start the assembly program with a SYS instruction.

The SEI is for stopping the interrupts is necessary because the default interrupt handler is in the KERNAL ROM, and the next STA $FF3F instruction will page in the underneath lying RAM, therefore an incoming interrupt without setting up a proper handler this way quite surely would crash.

Did this help?

Posted By

George
on 2011-09-11
16:36:03
 Re: Draw a single pixel in assembler

Hi gerliczer,
Yes, it helped. thank you very much. I think this init will be standard for my examples..

Another question:
This is the Code from Csabo which draws the one pixel
; draw a pixel at 160, 100 (center)
LDX #160
LDY #100
JSR drawpixel

; #################################################
drawpixel
TXA
AND #$07
STA tempx+1
;
TXA
AND #$F8
STA ptr
LDA #$00
STA ptr+1
;
TYA
AND #$07
STA tempy+1
;
TYA ; y=y/8
AND #$F8
LSR a
LSR a
LSR a
ASL a ; y=y*2
TAY
LDA ptr
CLC
ADC mul320,y
STA ptr
LDA ptr+1
ADC mul320+1,y
CLC
ADC #$20
STA ptr+1

after that i try to make a loop for a line from x=1 to 200, which does not work.
What i am doing wrong? Can i compare X or Y register direct with a value?

LDX #1
LDY #100
loop01
; loop
JSR drawpixel
INX
TXA
AND #200
BNE loop01

Posted By

gerliczer
on 2011-09-11
17:56:34
 Re: Draw a single pixel in assembler

Hi George,

I'm glad that I could help. I think I see what the problem is with your loop. Try to replace TXA and AND #200 with a single CPX #200.

And one humble request. Please do not omit the 'z' from my name.

Posted By

George
on 2012-11-23
03:29:57
 Re: Draw a single pixel in assembler

Hi gerliczer,

sorry for the name, i did not realized the z.

i tried now this:

LDX #0
LDY #100
loop01
; loop
INX
LDY #100
JSR drawpixel
CPX #$FF
BNE loop01

it draws the line until x=8 than it seems to stop.

Found it my self...
i have to store X position in a memory location. And load it again.


Update: 2012-11-23
The Draw-Pixel function above draws a pixel at position xyy in Hires-Mode (320x200).
How must the function be changed to draw a pixel in Multicolor mode (160x200)?
Couldn't find it out myself.


Posted By

bubis
on 2012-11-23
05:19:22
 Re: Draw a single pixel in assembler

If performance is not critical, you can simply use ROM routines.
Like you can use JSR $C1A5 that reads the x coordinate from $02ad-$02ae and y from $02af.
You can find plenty of examples using this ROM routine in
http://plus4world.powweb.com/software/Your_Daily_128_Byte_Intro

faster routines work like this:

XR: x coord lo
$d0: x coord hi
YR: y coord

lda row_addr_lo,y
sta $d2
clc
lda $d0
adc row_addr_hi,y
sta $d3
txa
and #$f8
tay
lda ($d2),y
ora bits,x
sta ($d2),y
rts

You have to prepare three tables for this to work:
* row_addr_lo/row_addr_hi needs to point to the first byte on the bitmap for the respective y coordinate, so it's like (bitmap_base+(y/8)*320+y&7).
* bits is a 256 bytes long periodic sequence of 128,64,32,16,8,4,2,1, 128, ....

Posted By

George
on 2012-11-23
05:21:46
 Re: Draw a single pixel in assembler

Thanks for the hint. But where are the Code-Examples to set a colored pixel?

Posted By

bubis
on 2012-11-23
05:25:49
 Re: Draw a single pixel in assembler

Check harmony.s for example, that works on mc bitmap. You have to set the color in $84 before calling $C1A5.

Posted By

George
on 2012-11-23
09:46:28
 Re: Draw a single pixel in assembler

Sorry to annoy you again, but i am a beginner and not very experienced
Please post a working Codeexample like above

Posted By

bubis
on 2012-11-30
04:19:48
 Re: Draw a single pixel in assembler

Try the below code after "GRAPHIC 4,1", it will draw a dot of color 1 at (16,32).

lda #$10
sta $02ad ;x coord low
lda #$20
sta $02af ;y coord low
lda #$00
sta $02ae ;x coord high
sta $02b0 ;y coord high
lda #$01
sta $84 ;color
jsr $c1a5

Posted By

SVS
on 2012-11-30
03:41:08
 Re: Draw a single pixel in assembler

bubis, you forgot a STA $2b0 after STA $2ae happy

Posted By

bubis
on 2012-11-30
06:40:22
 Re: Draw a single pixel in assembler

@SVS: The code works fine even without lda #$00+sta $02ae because this mem area is filled with zeros after reset. Otherwise, you are right, safer to set $2b0 as well, so I updated the code. Thanks!

Posted By

George
on 2013-03-31
10:07:11
 Re: Draw a single pixel in assembler

Hi,
I implemented the code and of course it works.
I move a little sprite around i realize filckering.
Any method to synchronize the code with the rasterbeam (V-Sync/H-Sync)?
Examples are apreciated.

Posted By

George
on 2013-03-31
10:07:14
 Re: Draw a single pixel in assembler

Hi,
I implemented the code and of course it works.
I move a little sprite around i realize filckering.
Any method to synchronize the code with the rasterbeam (V-Sync/H-Sync)?
Examples are apreciated.

Posted By

MMS
on 2013-04-01
04:39:38
 Re: Draw a single pixel in assembler

in the Publications the Raster Split has an example how to wait a specific rasterline in the Loop section.
Easy way to take care that you draw the pixel when you are out of 200 pixel high drawging area (sorry, no exact rasterline numbers here), so you draw when you are border area or out of screen.
Little more complicated if you take care that the raster is right after the drawing position, so you have a plenty of time, but need an extra register to store drawing positiom.
Some more talented programmers may give more exact instructions.

Posted By

KiCHY
on 2013-04-01
10:28:10
 Re: Draw a single pixel in assembler

The "jsr $c1a5" method works for turning on/off individual pixels on screen. Drawing a complete shape from these pixels (drawing each pixel is a complete coordinate/address calculation) costs lots of time and I'm afraid you won't eliminate the blinking completely. For shapes I strongly suggest to use some kind of software sprite routine.

Posted By

George
on 2013-04-02
07:04:36
 Re: Draw a single pixel in assembler

hi Kichy,

its a very small shape of a few pixels. I eliminated the flickering by clearing and drawing only the borders of the shape when moving it to a certain direction.

You gave an example, but i didnt get it to work, because of my lack of experience.
How do i use this routine for simple shape? (lets say a square of 4x4 pixels.

XR: x coord lo
$d0: x coord hi
YR: y coord

lda row_addr_lo,y
sta $d2
clc
lda $d0
adc row_addr_hi,y
sta $d3
txa
and #$f8
tay
lda ($d2),y
ora bits,x
sta ($d2),y
rts

You have to prepare three tables for this to work:
* row_addr_lo/row_addr_hi needs to point to the first byte on the bitmap for the respective y coordinate, so it's like (bitmap_base+(y/8)*320+y&7).
* bits is a 256 bytes long periodic sequence of 128,64,32,16,8,4,2,1, 128, ....

UPDATE:
No codewizard, who wants to help?
How do you want to keep alive the scene for the next generation,
if you don't support and document essential programming issues for the less experienced people?
Share your knowledge, with executable examples, please.

Greetings
George



Posted By

KiCHY
on 2013-04-02
16:02:48
 Re: Draw a single pixel in assembler

Hi George,

I made a small demo, you can download it:
http://wikisend.com/download/123630/DrawShape.zip

Not a speedcode, I tried to make it "tutoriallish" happy

I tried to use Plus4IDE first but it simply couldn't compile anything, got an error message... Then I checked the as65.exe and it said can't run in 64bit OS. So I tried CBM Prg Studio, I zipped its project files.

The DrawShape function uses EOR to draw the shape which means if you call it twice, the second call will remove the shape from bitmap.

I hope it helps happy

Posted By

George
on 2013-04-19
17:19:09
 Re: Draw a single pixel in assembler

Hi Kichy,

thanks for your example. A little overkill at first view for me. I will try to understand it and will come with questions.

Got it working in 2.4.0.
The source does not compile without errors.

Replace the line 136 to 147 with this here:
XCoord = $d0 ; X coordinate between 0-156
YCoord = $d1 ; Y coordinate between 0-96
SrcAddr = $d2 ; Address of 2x1char shape to be drawn (normal, or shifted versions)
SrcAddrLo = $d2
SrcAddrHi = SrcAddr+1
Dest1Addr = $d4 ; Address of left character of 2x1 shape on bitmap
Dest1AddrLo = $d4
Dest1AddrHi = Dest1Addr+1
Dest2Addr = $d6 ; Address of right character of 2x1 shape on bitmap
Dest2AddrLo = $d6
Dest2AddrHi = Dest2Addr+1
YMod8 = $d8

In Multicolor mode the shape is drawn blocky.



Back to topReply to this topic


Copyright © Plus/4 World Team, 2001-2024. Support Plus/4 World on Patreon