News:

Printed Amstrad Addict magazine announced, check it out here!

Main Menu
avatar_endangermice

CPC Coordinates System

Started by endangermice, 18:36, 03 July 12

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

endangermice

Since getting my 6128 back up and running, I decided to revisit my Z80 days and have managed to write a sprite routine (which has reminded of the nightmare design of the CPC colour encoding and screen address system). It's very basic at the moment but can draw some nice large shapes etc.


The bit that has me stumped is the SCR DOT POSITION firmware call &BC1D. According to the guide you enter the X coord into HL and the Y into DE. After execution HL will contain the memory address of the location of that pixel. However this doesn't seem to be what I'm experiencing. If I use 0,0 as the coordinates, rather than getting &C000 as I would expect, I seem to be getting the bottom of the screen &FF80. I thought the coordinates were simply inverted but then discovered that the screen appears to be 400 pixels high rather than 200.


I'm working in mode 0.


I think I'm missing some additional info about the way the CPC screen is structured. Can anyone enlighten me further...?


Cheers,


Damien
For all the latest Starquake remake news check out my website - www.endangermice.co.uk

TFM

Try to start with 1,1 in stead of 0,0

Further it probably depends if you scrolled the screen or not.

I'm not using firmware, but you should be able to easily check these two possibilities.
TFM of FutureSoft
Also visit the CPC and Plus users favorite OS: FutureOS - The Revolution on CPC6128 and 6128Plus

fano

#2
This is perfectly normal , (0,0) is at the left/bottom corner of the screen for the system.#C000 should be at something like (0,398) or (0,399)
The real organisation of the memory screen is not very complicated when you understood how CRTC work.I already posted something about it here but i can explain more if you need.
"NOP" is the perfect program : short , fast and (known) bug free

Follow Easter Egg products on Facebook !

endangermice

#3
Fano that's fantastic - thank you for this, it looks like it works in exactly the same way as the basic plot routine. The screen memory layout is fine once you get used to it but just makes the screen drawing routines a bit more of a challenge compared to other systems. It's taken me two days and about five rewrites until I produced a sprite routine that works - I could have stolen one but would rather learn by doing it all from scratch!


Along the way I've written a little utility on the PC that will convert a 16 colour bitmap to a series of Defb strings it also maps the colours to the nearest cpc colour and produces a palette that you can load straight into the CPC too. It's a bit rough around the edges right now but if anyone's interested ill make it available.
For all the latest Starquake remake news check out my website - www.endangermice.co.uk

arnoldemu

Great to hear your enjoying writing a sprite routine.
Are you planning a game in the future?
Always good to see new cpc games and new cpc programmers.
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

endangermice

Possibly - though I already have a remake using XNA that I really must finish first. I'm currently re-familiarising myself with Z80 and specifically the CPCs data layout etc. All of this will be going up on my blog which I'm hoping to launch soon, workload and real-life permitting!
For all the latest Starquake remake news check out my website - www.endangermice.co.uk

endangermice

I've been experimenting more tonight and I'm still not getting this coordinate system. When I'm drawing my sprite now, I can't increment it any less than a whole character row or column - I thought writing to the screen directly would allow me to move it in much smaller increments. I'm clearly missing something very important here but I am at a loss as to what this is - is there something special I have to do to move a sprite by a smaller amount - it seems that even SCR DOT POSITION only wants to give me addresses for character positions not pixel positioning and the Co-ordinate system seems completely screwed...?


I can post my code if it helps...?
For all the latest Starquake remake news check out my website - www.endangermice.co.uk

Executioner

SCR_DOT_POSITION takes the reversed co-ordinate system the same as the BASIC MOVE, DRAW, PLOT etc use. It's co-ordinates are always 640x400 regardless of the screen mode, and it returns a bit mask for the selected pixel. There are some fast pixel plotting routines and similar address routines here on the Wiki in the Programming section.

arnoldemu

#8
Quote from: endangermice on 00:43, 05 July 12
I've been experimenting more tonight and I'm still not getting this coordinate system. When I'm drawing my sprite now, I can't increment it any less than a whole character row or column - I thought writing to the screen directly would allow me to move it in much smaller increments. I'm clearly missing something very important here but I am at a loss as to what this is - is there something special I have to do to move a sprite by a smaller amount - it seems that even SCR DOT POSITION only wants to give me addresses for character positions not pixel positioning and the Co-ordinate system seems completely screwed...?


I can post my code if it helps...?
the smallest movement by writing single bytes in mode 0 is 2 pixels, 4 in mode 1 and 8 in mode 2.
To move smaller amounts there are 2 choices. Store 2 images in mode 0 (4 in mode 1 etc), each offset by 1 pixel.
OR, use a lookup table to convert from unshifted to shifted, and then combine them together with and and or.
it's extra work.

Did you look at my programming examples I posted concerning sprites and exactly this?
it really will help you.

I have replied in the topic so you can look through it "asm source code".
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

endangermice

That's great Executioner, thank you so much for your very helpful response! I have taken the excellent fast plot routine and have employed it to calculate my screen addresses, much more logical than the firmware routine (which is also incorrectly explained in a book I've been using!) and I suspect a lot lot faster.

I think I now have a pretty much working sprite routine. Needs some more testing, but looking very promising so far! It's almost certainly terrible compared to the attempts by others on here, but hey it's a start!

ArnoldEmu - I did take a look at your thread and it has helped a great deal. I'm still very new to all of this and there is a lot to take in. Right now I'm happy with moving 2 pixels on the horizontal plane - I can understand the concepts behind making it work for a 1 pixel move but need to get a bit more experience first before I delve in, but thank you for the pointers!


Anyway in case anyone is interested here's the code I came up with - feel free to scrutinise, I know it could be a whole lot better, but not too bad for a first attempt!



; Better Sprite Routine
org &4000


; set screen mode and clear the screen
ld a, 0
call &BC0E
call &BC14


; Draw the sprite
ld hl, TestData
ld de, 0
ld bc, 100
call DrawSprite


; Done
ret


DrawSprite
   ; Setup Variables
   ; Entry hl points to the shape to be drawn
   ; DE is the X-Coordinate
   ; BC is the Y-Coordinate


   ; Get Screen address for sprite
   push hl
   push bc ; Push BC onto the stack
   
   ; Get the line to draw from - uses mod of 8 to get the offset
   ld a, c ; Load the Y-Coord into accumilator
   and %00000111 ; Perform modulus of 8 (binary eight)
   ld c, a ; Load the result back into c
   ld b, 0 ; clear high order byte b
    ld (SpriteLineCounter), bc ; Set sprite line counter to the offset


   pop hl   ; pop it off into hl


   call GetCoords ; get the screen address
   ld (SpriteDrawAddress), hl
   pop hl


   ld bc, 0 ; Set the counter to 0


SpriteDrawLoop:


   ; should we jump out of the loop?
   push hl ; move hl temporarily
   ld hl, (SpriteHeight)
   and a;
   sbc hl, bc
   pop hl ; get it back (will be pointing at the sprite data) - have to do it here in case we jump to exit, won't affect the zero flag anyway
   jr z, SpriteFinished


   push bc ; store BC since we're about to use it!


   ; Load in data
   push hl ; need hl again
   ld hl, (SpriteDrawAddress) ; load sprite screen address into hl
   ld d, h ; Start position (extrapolate using firmware routine) BC1D?
   ld e, l


   pop hl ; pop the sprite data address back into hl


   ld bc, (SpriteWidth) ; Width
   ldir ; copy this line to the screen


   push hl


   ld hl, (SpriteDrawAddress) ; load sprite screen address into hl
   ld de, (SpriteLineCounter)


   push hl


   ld hl, 7 ; Have we drawn all lines?
   and a
   sbc hl, de
   pop hl


   jr z, MoveNextColumn ; yes goto next column   
   jr nz, MoveNextLine ; no goto next line


StoreSpriteValues
   ld (SpriteLineCounter), de
   ld (SpriteDrawAddress), hl


   pop hl ; Get sprite data address back into hl


   ; Get BC back
   pop bc
   inc bc


   jr SpriteDrawLoop


SpriteFinished
   ret


MoveNextLine
   ld bc, &800 ; Move to the next line - offset of &800
   ; remove an offset here...?
   add hl, bc
   inc de ; increment the sprite line counter
   jr StoreSpriteValues


MoveNextColumn
   ld bc, &3800
   sbc hl, bc
   ld bc, &50
   add hl, bc
   ld de, 0 ; reset the sprite line counter
   jr StoreSpriteValues


CMASK   EQU &B338      ;Adress for colormask
            ;664/6128 &B6A3
                 
GetCoords   
   LD A, L         ;A = Lowbyte Y
   AND %00000111      ;isolate Bit 0..2
   LD H, A         ;= y MOD 8 to H
   XOR L         ;A = Bit 3..7 of Y
   LD L, A         ;= (Y\*8 to L
   LD C, A         ;store in C
   LD B, &60      ;B = &C0\2 = Highbyte Screenstart\2
     
   ADD HL, HL      ;HL * 2
   ADD HL, HL      ;HL * 4
   ADD HL, BC      ;+ BC = Startaddress
   ADD HL, HL      ;of the raster line
     
   SRL E         ;calculate X\2, because 2 pixel per byte, Carry is X MOD 2
     
   LD C, %10101010           ;Bitmask for MODE 0
   JR NC, NSHIFT      ;-> = 0, no shift
SHIFT   
   LD C, %01010101           ;other bitmask for right pixel
     
NSHIFT   
   ADD HL, DE      ;+ HL = Screenaddress
        LD A, (CMASK)      ;get color mask
   XOR (HL)      ;XOR screenbyte
   AND C         ;AND bitmask
   XOR (HL)      ;XOR screenbyte
   LD (HL), A      ;new screenbyte
   RET   


SpriteWidth dw 0032
SpriteHeight dw 0064
SpriteLineCounter dw 0000
SpriteDrawAddress dw &C100


TestData
;defb 32, 64
defb &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &40, &80, &00, &00, &00, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &40, &0c, &48, &00, &00, &00, &0c, &48, &80, &00, &00, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &0c, &0c, &0c, &80, &00, &04, &0c, &0c, &c0, &00, &00, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &04, &0c, &0c, &0c, &48, &00, &40, &0c, &0c, &c0, &00, &00, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &84, &0c, &0c, &0c, &48, &00, &00, &0c, &0c, &c0, &00, &00, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &84, &0c, &0c, &0c, &0c, &80, &00, &40, &0c, &c0, &00, &00, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &04, &0c, &48, &0c, &0c, &80, &00, &00, &84, &c0, &00, &00, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &c0, &c0, &84, &0c, &48, &00, &00, &84, &c0, &00, &00, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &40, &0c, &48, &80, &00, &0c, &80, &00, &00, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &cc, &cc, &cc, &cc, &c8, &0c, &0c, &80, &00, &0c, &80, &00, &00, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &cc, &98, &30, &30, &64, &cc, &cc, &0c, &0c, &80, &40, &0c, &80, &00, &00, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &44, &30, &30, &30, &30, &30, &30, &64, &84, &0c, &48, &00, &c0, &80, &00, &00, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &00, &00, &00, &00, &44, &cc, &cc, &30, &30, &30, &30, &30, &64, &84, &0c, &48, &44, &88, &00, &00, &00, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &00, &00, &00, &04, &0c, &0c, &4c, &cc, &30, &30, &30, &30, &30, &8c, &0c, &48, &44, &cc, &00, &00, &00, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &00, &00, &44, &0c, &0c, &0c, &0c, &4c, &cc, &30, &30, &30, &30, &c8, &0c, &0c, &c4, &cc, &88, &00, &00, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &00, &00, &0c, &0c, &0c, &0c, &0c, &0c, &cc, &98, &30, &30, &30, &cc, &0c, &0c, &80, &cc, &cc, &00, &00, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &00, &00, &0c, &cc, &0c, &0c, &0c, &0c, &cc, &cc, &30, &30, &30, &64, &84, &0c, &80, &cc, &cc, &88, &00, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &00, &04, &08, &00, &04, &0c, &0c, &0c, &4c, &cc, &98, &30, &30, &64, &c8, &0c, &80, &cc, &cc, &cc, &00, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &00, &8c, &08, &00, &04, &0c, &0c, &0c, &4c, &cc, &cc, &98, &30, &30, &cc, &c0, &80, &cc, &cc, &cc, &88, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &00, &8c, &08, &00, &04, &0c, &0c, &0c, &4c, &cc, &cc, &cc, &30, &30, &cc, &40, &80, &cc, &cc, &cc, &88, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &44, &8c, &0c, &cc, &0c, &0c, &0c, &0c, &4c, &cc, &cc, &cc, &98, &30, &cc, &88, &44, &cc, &cc, &cc, &cc, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &cc, &8c, &0c, &0c, &0c, &0c, &0c, &0c, &4c, &cc, &cc, &cc, &98, &30, &64, &cc, &cc, &cc, &cc, &cc, &cc, &88, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &cc, &8c, &0c, &0c, &0c, &0c, &0c, &0c, &4c, &cc, &cc, &cc, &cc, &30, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &88, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &cc, &8c, &0c, &0c, &0c, &0c, &0c, &0c, &4c, &cc, &cc, &cc, &cc, &30, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &88, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &44, &64, &cc, &0c, &0c, &0c, &0c, &0c, &0c, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &44, &30, &cc, &0c, &0c, &0c, &0c, &0c, &4c, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &10, &30, &cc, &cc, &0c, &0c, &0c, &0c, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &10, &30, &64, &cc, &cc, &0c, &0c, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &88, &00, &00, &00, &00
defb &00, &00, &00, &00, &98, &30, &30, &cc, &cc, &88, &44, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &88, &00, &00, &00, &00
defb &00, &00, &00, &00, &98, &30, &30, &30, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &88, &00, &00, &00, &00
defb &00, &00, &00, &00, &98, &30, &30, &30, &64, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &88, &00, &00, &00, &00
defb &00, &00, &00, &00, &98, &30, &30, &30, &30, &64, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &88, &00, &00, &00, &00
defb &00, &00, &00, &00, &98, &30, &30, &30, &30, &30, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &88, &00, &00, &00, &00
defb &00, &00, &00, &00, &10, &30, &30, &30, &30, &30, &30, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &88, &00, &00, &00, &00
defb &00, &00, &00, &00, &44, &30, &30, &30, &30, &30, &30, &64, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &44, &30, &30, &30, &30, &30, &30, &30, &30, &64, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &44, &30, &30, &30, &30, &30, &30, &30, &30, &64, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &44, &98, &30, &30, &30, &30, &30, &30, &30, &cc, &cc, &c8, &0c, &48, &80, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &98, &30, &30, &30, &30, &30, &30, &cc, &cc, &cc, &8c, &0c, &0c, &0c, &c0, &cc, &cc, &cc, &cc, &cc, &cc, &88, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &cc, &30, &30, &30, &30, &64, &cc, &cc, &cc, &cc, &c8, &0c, &0c, &0c, &0c, &48, &44, &cc, &cc, &cc, &cc, &88, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &44, &98, &30, &30, &64, &cc, &cc, &cc, &cc, &cc, &cc, &84, &0c, &0c, &0c, &0c, &48, &cc, &cc, &cc, &cc, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &44, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &40, &0c, &0c, &0c, &0c, &0c, &80, &cc, &cc, &cc, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &80, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &88, &84, &0c, &0c, &0c, &0c, &48, &44, &cc, &88, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &48, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &40, &0c, &0c, &0c, &0c, &0c, &80, &cc, &00, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &c0, &44, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &88, &c0, &0c, &0c, &0c, &0c, &48, &80, &00, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &40, &80, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &c8, &0c, &0c, &0c, &0c, &0c, &08, &00, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &40, &80, &44, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &84, &0c, &0c, &0c, &0c, &0c, &80, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &00, &c0, &00, &44, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &84, &0c, &0c, &0c, &0c, &0c, &0c, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &00, &40, &c0, &00, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &8c, &0c, &0c, &0c, &0c, &0c, &0c, &0c, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &00, &00, &c0, &80, &00, &cc, &cc, &cc, &cc, &cc, &cc, &cc, &8c, &0c, &0c, &0c, &0c, &0c, &0c, &0c, &c0, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &00, &00, &40, &c0, &00, &00, &cc, &cc, &cc, &cc, &cc, &8c, &0c, &0c, &0c, &0c, &0c, &0c, &0c, &48, &80, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &00, &00, &00, &40, &c0, &00, &00, &44, &cc, &cc, &cc, &0c, &0c, &0c, &0c, &0c, &0c, &0c, &0c, &48, &80, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &00, &00, &00, &00, &c0, &c0, &00, &00, &00, &44, &04, &0c, &0c, &0c, &0c, &0c, &0c, &0c, &0c, &c0, &00, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &c0, &c0, &80, &00, &40, &0c, &0c, &0c, &0c, &0c, &0c, &0c, &0c, &c0, &00, &00, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &40, &c0, &c0, &c0, &84, &0c, &0c, &0c, &0c, &0c, &0c, &0c, &c0, &80, &00, &00, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &c0, &c0, &84, &0c, &0c, &0c, &0c, &0c, &0c, &c0, &80, &00, &00, &00, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &0c, &0c, &0c, &0c, &0c, &48, &c0, &80, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &84, &0c, &0c, &84, &c0, &c0, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &40, &c0, &c0, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00
defb &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00, &00






For all the latest Starquake remake news check out my website - www.endangermice.co.uk

Executioner

Quote from: endangermice on 09:37, 05 July 12

   LD C, %10101010           ;Bitmask for MODE 0
   JR NC, NSHIFT      ;-> = 0, no shift
SHIFT   
   LD C, %01010101           ;other bitmask for right pixel
     
NSHIFT   
   ADD HL, DE      ;+ HL = Screenaddress
        LD A, (CMASK)      ;get color mask
   XOR (HL)      ;XOR screenbyte
   AND C         ;AND bitmask
   XOR (HL)      ;XOR screenbyte
   LD (HL), A      ;new screenbyte


This last bit of the original plot routine actually works out the pixel mask and plots the pixel on the screen. It can simply be replaced with ADD HL,DE then the RET if it's just being used to calculate the screen address.

Cheers,
Richard

endangermice

Ah I see, I'll take a look at this later and remove the surpless code! I've been reading your tips on sprite drawing and will be optimising this routine to remove the pushes etc.so it executes faster - this first stab is really a simple routine so I can see more clearly what's going on and understand exactly how everything is working - I'm quite keen to use EXX allowing me to use the additional registers but I know the OS uses these too so really need to understand the implications of this....


I'm now trying to figure out the best approach that will allow me to do pixel perfect horizontal movement on a Mode 0 screen. By far the easiest way is to just store each image twice but in each case, offset by a pixel. I could then switch between the shapes by performing a modulus of two on the XCoord. However, having thought about it I'd rather try and do this is code i.e rather than have two copies to the shape - shift the pixel data somehow before drawing it. Are the any examples on how to to do this - due to the colour encoding and the fact that a sprite will sit over several horizontal screen addresses a simple bit shift won't do it!


Finally - how are you guys calculating the execution performance of your code? Is it just a case of going through each instruction, calculating the execution cycles and then adding all os this together or is thee a less manual approach....?


Thanks for all the help Richard - its really appreciated - I'm learning a lot and it's much appreciated to have people like you around on the forum - I'm also finding WinAPEs built in assembler an absolute godsend - a million miles away from having Maxam on disk which was my setup back in the 80s!


Cheers,


Damien
For all the latest Starquake remake news check out my website - www.endangermice.co.uk

TFM

Well, Maxam in ROM is way better ;-) To load from disc (again and again) can be a real pain...
TFM of FutureSoft
Also visit the CPC and Plus users favorite OS: FutureOS - The Revolution on CPC6128 and 6128Plus

endangermice

Yeah tell me about it! Unfortunately back then I was rather poor so could only afford the disc version - sob :(. Still it makes me massively appreciate the benefits of developing on an emulator then writing to a disc ready for the CPC. I suppose a really cool project would be to write an assembler that would assemble then copy the code directly into the CPCs memory via the expansion port giving you the WInAPE experience on real hardware!
For all the latest Starquake remake news check out my website - www.endangermice.co.uk

TFM

Aehm... That's what my Maxam does. It writes code in the RAM of the CPC ;-)
TFM of FutureSoft
Also visit the CPC and Plus users favorite OS: FutureOS - The Revolution on CPC6128 and 6128Plus

endangermice

Now that is very cool! Any details....?
For all the latest Starquake remake news check out my website - www.endangermice.co.uk

fano

Quote from: endangermice on 00:07, 09 July 12I suppose a really cool project would be to write an assembler that would assemble then copy the code directly into the CPCs memory via the expansion port giving you the WInAPE experience on real hardware!
You can assemble the code in memory in winape, save snapshot and inject it via cpcbooster.
"NOP" is the perfect program : short , fast and (known) bug free

Follow Easter Egg products on Facebook !

endangermice

Sounds great, I'll have to check it out. Right now I write the discs from WinApe using CPCDiscXP then load them into the CPC via the external 3.5" drive. My code is so small right now that it's not exactly a hardship and I do all of the testing in WinAPE anyway but a direct connection would be very cool!
For all the latest Starquake remake news check out my website - www.endangermice.co.uk

fano

#18
You can find more infos about it here and still find one here (the last one ?)
You need to own a romboard (like a megaflash for example) or a modified CPC+ cartrige (i use that solution) to be able to use snapshot tools.
Without that you can still do cool things like disc transfert or music playback from PC with arkos tracker like this :


Musique sur Amstrad CPC via CPCbooster+
"NOP" is the perfect program : short , fast and (known) bug free

Follow Easter Egg products on Facebook !

Prodatron

Quote from: endangermice on 09:00, 08 July 12
Finally - how are you guys calculating the execution performance of your code? Is it just a case of going through each instruction, calculating the execution cycles and then adding all os this together or is thee a less manual approach....?
I use these three ways of checking the execution performance:
- for inner-loops and other not too large things, which needs to be optimized as much as possible, I am writing the execution cycles behind each instruction and add them. This is a good way to compare different approuches and to optimize each single instruction. After some experiences it's quite easy to keep the execution times in mind and write them down, as it's quite logical.
- for larger routines I sometimes use the "old school" rasterline methode: Use e.g. 3 HALT instruction after each framefly, set INK 0 to red, execute your routine, then set INK 0 to black, and repeat everything. Then you will see a red area on your screen which shows you, how many rasterlines (each is 64 microseconds) are spent for your routine
- the modern way: Use WinApe, set a breakpoint at the beginning and at the end of your routine. When the first breakpoint is reached, reset the Timer (upper right side of the debugger window below the registers) to 0, then continue execution. When the second breakpoint is reached, read the Timer, it shows the exact execution time.

Quote from: endangermice on 09:00, 08 July 12
I'm also finding WinAPEs built in assembler an absolute godsend - a million miles away from having Maxam on disk which was my setup back in the 80s!
That's true! :) Using WinApe speeds up developing of Z80 projects a million times. So you can concentrate 100% on programming and debugging, which is just great! Currently I think there is no better way.

CU,
Prodatron

GRAPHICAL Z80 MULTITASKING OPERATING SYSTEM

endangermice

#20
Ah, I didn't know about the timer in WinAPE, that will very useful - thanks for the tip, it's definitely the best development environment I've come across for the CPC - all credit to Richard for some fine work!


This leads me onto another question... How are you tracking the position of the scanline? If for example I want to do all of my processing etc. during the frame flyback, how do I ensure this happens? Is the frame flyback reset each time the mode is set or the screen is cleared? Waiting for a frame flyback by calling the firmware routine &BD19 seems to slow my code down significantly presumably because its constantly being made to wait?


I suspect the best way is to time your code so it syncs itself i.e. executes quickly enough to have drawn during flyback - but I'm not too sure how I know that a flyback is about to occurred?


I see when I break program execution in WinAPE that it appears to draw the position of the beam on the screen at that point (the horizontal and vertical lines) is that correct?

Sorry for all the questions, but the answers are holping me to learn a great deal - much better than the old days of writing to AA and waiting a month for a reply ;) .
For all the latest Starquake remake news check out my website - www.endangermice.co.uk

Executioner

WinAPE also has another little trick for visibly seeing the time taken for a section of code.... You can set breakpoints which change the palette as part of their condition ;)

arnoldemu

normally I do this:

ld bc,&7f10
out (c),c
ld bc,&7f4b
out (c),c

code

ld bc,&7f10
out (c),c
ld bc,&7f54
out (c),c

this changes the border colour, does the code and changes it back to black.
the thickness of the stripe in the border indicates the time it takes to execute.
then you modify the code and see how the stripe thickness changes.

the stripe has to be visible within the display, so often a few halts (min 3) should do that.

halt
halt
timing code
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

endangermice

Excellent tips guys, I will have to look into these when I have some more time. Unfortunately right now I have a lot going on :(.
For all the latest Starquake remake news check out my website - www.endangermice.co.uk

Powered by SMFPacks Menu Editor Mod