CPCWiki forum

General Category => Programming => Topic started by: dub on 08:46, 23 September 16

Title: create good cpr for gx4000
Post by: dub on 08:46, 23 September 16
Hi, I want to initialize the gx4000 for my cpc+ game.

It's working on cpc+ format disk but not cpr.

Arnoldemu give met his code to initialize the gx4000 but I can't make it works.
Unofficial Amstrad WWW Resource (http://www.cpctech.org.uk/source.html)
;; This example shows a suggested startup for a cartridge

;; cartridge page 0 exists at &0000-&3fff
;; execution starts at &0000
;;
org &0000

start:

di ;; disable interrupts
im 1 ;; set interrupt mode 1
ld bc,&f782 ;; setup initial PPI port directions
out (c),c
ld bc,&f400 ;; set initial PPI port A (AY)
out (c),c
ld bc,&f600 ;; set initial PPI port C (AY direction)
out (c),c

ld bc,&7fc0 ;; set initial RAM configuration
out (c),c

;; unlock ASIC so we can access ASIC registers
ld b,&bc
ld hl,sequence
ld e,17
seq:
ld a,(hl)
out (c),a
inc hl
dec e
jr nz,seq

;; set initial CRTC settings (screen dimensions etc)
ld hl,end_crtc_data
ld bc,&bc0f
crtc_loop:
out (c),c
dec hl
ld a,(hl)
inc b
out (c),a
dec b
dec c
jp p,crtc_loop

ld hl,&c9fb
ld (&0038),hl
ei

;; enable asic ram (will be visible in range &4000-&7fff)
ld bc,&7fb8
out (c),c

;; your code here
loop:


jr loop

;; your crtc setup values here; these are examples
crtc_data:
defb &3f, &28, &2e, &8e, &26, &00, &19, &1e, &00, &07, &00,&00,&30,&00,&c0,&00
end_crtc_data:

;; sequence to unlock asic
sequence:
defb &ff,&00,&ff,&77,&b3,&51,&a8,&d4,&62,&39,&9c,&46,&2b,&15,&8a,&cd,&ee

end

What am I doing :

I add this little code in the loop: for adding color border, just for testing
LD        BC,#7F10
OUT      (C),C
LD        A,76
OUT      (C),A


I use winape for testing. And I have a black screen when I launch the cartridge.
If I launch an other cartridge before, and lauch my cartridge, I have red border.

I use two way for testing :

Directly in winape with a :
WRITE DIRECT 0,-1,&C0

or with the software cprtools after making the bin in winape with a : WRITE "cart.bin"

I certainly doing something wrong.

Title: Re: create good cpr for gx4000
Post by: arnoldemu on 13:11, 23 September 16
Ok there is a bug in the code. Sorry my mistake.

The EI is enabling the interrupts and the default interrupt for im 1 is 0038.

Change it to this:


org &0000
jp start
org &0038
ei
ret
start:

di ;; disable interrupts
im 1 ;; set interrupt mode 1
ld bc,&f782 ;; setup initial PPI port directions.
.
.
.


and it'll work better.

You should change the mainloop and things to call your code.
You can copy your code into ram, disable the roms and then take over the hardware :)


Title: Re: create good cpr for gx4000
Post by: Xifos on 14:12, 23 September 16
dub, it 's great to see you coding on the gx/cpc+ !
:)
Thanks for helping him, arnoldemu !
;)
Title: Re: create good cpr for gx4000
Post by: dub on 15:51, 23 September 16
Thanks, I'll try this and make a test on gx4000

@Xifos (http://www.cpcwiki.eu/forum/index.php?action=profile;u=186) : I'm just beginning, I need to rise my knowledge of the specificity of the hardware.  After I'll try to make a little game.
Title: Re: create good cpr for gx4000
Post by: dub on 10:11, 24 September 16
I "almost" succeeded  ;D

On the winape emulator, I have a good red border and my sprite. But on gx4000, I think I need to erase the ram before sending my data, as the picture show.

When I'll have a clear start, I'll begin my game dev.


The orange on the photo is red on my TV  :P
Title: Re: create good cpr for gx4000
Post by: Xifos on 11:21, 24 September 16
Well done !

And you are right, you need to clear memory.

The border is smaller on a tv ?
I did not know...
Title: Re: create good cpr for gx4000
Post by: arnoldemu on 11:36, 24 September 16
Quote from: dub on 10:11, 24 September 16
I "almost" succeeded  ;D

On the winape emulator, I have a good red border and my sprite. But on gx4000, I think I need to erase the ram before sending my data, as the picture show.

When I'll have a clear start, I'll begin my game dev.


The orange on the photo is red on my TV  :P
Good that you test on a real gx4000. Always do that. :)

You can also test on my emulator if you want.
Unofficial Amstrad WWW Resource (http://www.cpctech.org.uk/setup.zip)


You should assume hardware is not initialised and that you need to initialise it and clear the ram you want to use then you will have much more consistent and better results.

When testing with C4CPC you can do two things:
- connect PC to C4CPC with usb cable and run the cart direct on the C4CPC avoiding menu
- put the cpr into it's own slot and boot into that slot (select with dip switches).

If you use the menu it's possible some hardware will be initialised and you need to test it as close to "original" power on state.

:)
Title: Re: create good cpr for gx4000
Post by: arnoldemu on 11:38, 24 September 16
Quote from: Xifos on 11:21, 24 September 16
Well done !

And you are right, you need to clear memory.

The border is smaller on a tv ?
I did not know...
Border can be smaller or larger on CRT tv and it really depends on the television.

When developing for Wii or older consoles that can use use CRT there were instructions to tell us not to put HUD too close to the edges of the screen. (I think the "safe area" was 80% of the display).

The border should be almost the same on LCD televisions.


Title: Re: create good cpr for gx4000
Post by: gerald on 12:34, 24 September 16
Quote from: Xifos on 11:21, 24 September 16
The border is smaller on a tv ?
If you can properly read the C4CPC logo on the screen, that mean the CRCT is still configured for the cartridge selector : ie overscan.
That's why the border is so small.
Title: Re: create good cpr for gx4000
Post by: dub on 13:11, 24 September 16
Thanks
I'm used to deal with the safe area when I'm working on raspberry pi or with my 800xl.

I try try my cpr on his own slot (c4cpc) and I have only black on screen with bad frequency (or like bad screen refresh rate).
I try your emulator too and that's doesn't work. I have black left border and some color on top of the screen :  cf screenshot  :(

I continue my investigation   ;D
Title: Re: create good cpr for gx4000
Post by: arnoldemu on 13:36, 24 September 16
Try this instead:

Unofficial Amstrad WWW Resource (http://www.cpctech.org.uk/download/cart_setup.zip)

There are some examples here that may help. They are better tested. My code here must be old and not working fully.

"single": Good for single files to be executed from ram.
The boot program copies the code into ram and executes it. You still need to initialise the h/w. Look at the example.

"fs": The cart is treated like a read only filesystem.
You can read and write files as you need in your program. See the example. This is much easier if your used to disks and loading files. It's similar to how a lot of C64 carts work.

"absolute": You take control over each 16KB cart page so you need to manage both your code and your data to work with it.

Maybe it is better to work with these?

You can freely use this code in your own game. I would like a credit if you use it please.
Title: Re: create good cpr for gx4000
Post by: dub on 10:45, 25 September 16
I'm cursed or what ?  ;D

I try the arnoldemulator and the "single" example for beginning. And I had weird results.

I use the make.bat with pasmo for Windows. Everything compil. I've just add my code to see red border.
I launch arnold emu with the gx4000 configuration as you can see on the screenshot. And When I launch the cart, I have left black border and two color lines on the top.

I try my my_cart.bin and the cpr with the cprtools.

If I insert my_cart.cpr on winape emulator, I have the game working : red border and flashing in screen. (On the bottom of my screenshot).
But I need to compiling with pasmo and after use the crptools gui. Lot of manipulation.
Title: Re: create good cpr for gx4000
Post by: Xifos on 17:46, 25 September 16
What does cprtools ?

Transform a bin file into a cpr file ?
Title: Re: create good cpr for gx4000
Post by: Kris on 20:03, 25 September 16
Quote from: Xifos on 17:46, 25 September 16
What does cprtools ?

Transform a bin file into a cpr file ?


Exactly, in both way bin => CPR or CPR=> bin
Title: Re: create good cpr for gx4000
Post by: siudym on 19:27, 06 January 23
Is there any information about switching banks in the GX4000 cartridge? Some examples in ASM. How does the Bank Switch work in GX - are $0000-3FFF (Lower) and $C000-FFFF (upper) switched independently or, for example, $0000 as a fixed bank and $C000 is switched?
Title: Re: create good cpr for gx4000
Post by: asertus on 19:39, 06 January 23
Quote from: siudym on 19:27, 06 January 23Is there any information about switching banks in the GX4000 cartridge? Some examples in ASM. How does the Bank Switch work in GX - are $0000-3FFF (Lower) and $C000-FFFF (upper) switched independently or, for example, $0000 as a fixed bank and $C000 is switched?

@reidrac has written about that.

https://www.usebox.net/jjm/blog/cpc-cartridges-bank-switching/
Title: Re: create good cpr for gx4000
Post by: andycadley on 19:40, 06 January 23
The bank's can be switched independently. Any of the first 8 cartridge pages can be mapped using RMR2 and this can map to address 0000, 4000h or 8000h

Separately, the upper ROM mapping can be used to put any of the 32 cartridge pages into the memory at C000h (it could even be the same page, if desired). These are mapped using the old RMR register of the gate array, but with ROM numbers of 128 to 159 (7 selects the disk ROM and anything else selects ROM 0)
Title: Re: create good cpr for gx4000
Post by: reidrac on 19:49, 06 January 23
Also, on the wiki: https://www.cpcwiki.eu/index.php/Programming:Cartridges
Title: Re: create good cpr for gx4000
Post by: siudym on 20:41, 06 January 23
Are there any template/skeleton cartridge (pasm) code containing an example of a bank organization scheme? And how to compile it to create the proper bin ROM.
Title: Re: create good cpr for gx4000
Post by: roudoudou on 21:49, 06 January 23
Quote from: siudym on 20:41, 06 January 23Are there any template/skeleton cartridge (pasm) code containing an example of a bank organization scheme? And how to compile it to create the proper bin ROM.
you can use the skeleton above with RASM, then add at the beggining

buildcpr
bank 0
<the code>

bank 1
<another code>

bank 2
<...>

up to bank 31 for a 512K cartridge

it will generate a CPR as output file
Title: Re: create good cpr for gx4000
Post by: siudym on 22:38, 06 January 23
Thanks.

Do I need to set/define the cartridge format somehow? Is the bank switch method always the same everywhere?

Unfortunately there are quite a few compilation errors.
"- PASMO" is a compatibility mode?

rasm_x64 -pasmo main.asm
Pre-processing [main.asm]
Assembling
Error: [main.asm:11] Missing operand for calculation [&0000] Did you use & for an hexadecimal value?
Error: [main.asm:14] Missing operand for calculation [&0038] Did you use & for an hexadecimal value?
Error: [main.asm:14] ORG (output at #0000) located in a previous ORG section [#0000-#0003-B0] file [main.asm] line 11
Error: [main.asm:113] Assembling overwrite [main.asm] L11 [#0000-#0003-B0] with [main.asm] L14 [#0000/#0071]
Error: [main.asm:21] expression [&F782] keyword [F782] not found in variables, labels or aliases
Error: [main.asm:21] Missing operand for calculation [&F782] Did you use & for an hexadecimal value?
Error: [main.asm:23] expression [&F400] keyword [F400] not found in variables, labels or aliases
Error: [main.asm:23] Missing operand for calculation [&F400] Did you use & for an hexadecimal value?
Error: [main.asm:25] expression [&F600] keyword [F600] not found in variables, labels or aliases
Error: [main.asm:25] Missing operand for calculation [&F600] Did you use & for an hexadecimal value?
Error: [main.asm:28] expression [&7FC0] - 7FC0 is not a valid number
Error: [main.asm:28] Missing operand for calculation [&7FC0] Did you use & for an hexadecimal value?
Error: [main.asm:32] cannot use register &BC in this context
Error: [main.asm:32] Missing operand for calculation [&BC] Did you use & for an hexadecimal value?
Error: [main.asm:44] expression [&BC0F] keyword [BC0F] not found in variables, labels or aliases
Error: [main.asm:44] Missing operand for calculation [&BC0F] Did you use & for an hexadecimal value?
Error: [main.asm:55] expression [&C9FB] keyword [C9FB] not found in variables, labels or aliases
Error: [main.asm:55] Missing operand for calculation [&C9FB] Did you use & for an hexadecimal value?
Error: [main.asm:56] Missing operand for calculation [(&0038)]
Error: Too many errors!
Title: Re: create good cpr for gx4000
Post by: roudoudou on 23:16, 06 January 23
you should read (quickly) the documentation (and the error messages!) ;)

"&" is used for boolean AND operator. We may keep this hexadecimal syntax using -ampersand command line option but you will miss & for AND (you can still write plain AND)

the CPR produced is 100% compatible with C4CPC and Amstrad Plus emulators

ps: and i can quickly answer to you on discord (see the doc again :p )
Title: Re: create good cpr for gx4000
Post by: siudym on 11:38, 07 January 23
Quote from: arnoldemu on 13:11, 23 September 16org &0038
ei
ret

I'll ask just to be sure: shouldn't it be RETI instead of RET?
Title: Re: create good cpr for gx4000
Post by: andycadley on 12:27, 07 January 23
Quote from: siudym on 11:38, 07 January 23
Quote from: arnoldemu on 13:11, 23 September 16org &0038
ei
ret

I'll ask just to be sure: shouldn't it be RETI instead of RET?
It doesn't matter. RETI is designed so that Z80 aware peripherals can spot it on the bus and detect the end of an interrupt routine, mostly for daisy chained devices.

None of the hardware in the CPC pays any attention to it, so it's just a slower version of RET.
Title: Re: create good cpr for gx4000
Post by: siudym on 13:23, 07 January 23
I'm a total noob on Amstrad. I would like to display some text, display a simple sprite in this code.
For now, I'm trying to write Hello World but nothing comes out :)

pasmo test.asm test.bin
python mkcpr.py test.bin
pause

;------------------------------------

; This example shows a suggested startup for a Cartridge.
; Cartridge page 0 exists at $0000-$3FFF.
; Execution starts at $0000.

;------------------------------------

PrintChar EQU $BB5A

;------------------------------------

 ORG $0000

 JP Start

;------------------------------------

 ORG $0038
 EI
 RET ; Not RETI ?

;------------------------------------

Start:

 DI ; Disable Interrupts.
 IM 1 ; Set interrupt Mode 1.

 LD BC,$F782 ; Setup initial PPI port directions.
 OUT (C),C

 LD BC,$F400 ; Set initial PPI port A (AY).
 OUT (C),C

 LD BC,$F600 ; Set initial PPI port C (AY direction).
 OUT (C),C

 LD BC,$7FC0 ; Set initial RAM configuration.
 OUT (C),C

;------------------------------------

 LD B,$BC ; Unlock ASIC so we can access ASIC registers.
 LD HL,Sequence

 LD E,17
Seq:

 LD A,(HL)
 OUT (C),A
 INC HL
 DEC E
 JR NZ,Seq

;------------------------------------

 LD HL,CRTC_Data_end ; Set initial CRTC settings (screen dimensions etc).
 LD BC,$BC0F

CRTC_Loop:

 OUT (C),C
 DEC HL
 LD A,(HL)
 INC B
 OUT (C),A
 DEC B
 DEC C
 JP P,CRTC_Loop

;------------------------------------

 LD HL,$C9FB
 LD ($0038),HL

 EI

 LD BC,$7FB8 ; Enable ASIC Ram (will be visible in range $4000-$7FFF).
 OUT (C),C

;------------------------------------

; Your Code here...

 LD BC,$7F10 ; Kolor Border na Blue.
 OUT (C),C
 LD C,$55
 OUT (C),C

 LD BC,$6400 ; Kolor Border na Yellow.
 OUT (C),C
 LD C,$4A
 OUT (C),C

 LD HL,Message ; Jakies dziwne dziwadla sie dzieja...
 CALL PrintString

;------------------------------------

Forever:

; HALT

 JR Forever

;------------------------------------

PrintString:

 LD A,(HL) ; Print a '255' terminates String.
 CP 255
 RET Z
 INC HL
 CALL PrintChar
 JR PrintString

;------------------------------------

Message:

 DEFB "HELLO WORLD",255

;------------------------------------

CRTC_Data: ; Your crtc setup values her ; these are examples

 DEFB $3f, $28, $2e, $8e, $26, $00, $19, $1e, $00, $07, $00,$00,$30,$00,$c0,$00

CRTC_Data_end:

;------------------------------------

Sequence: ; Sequence to unlock ASIC.

 DEFB $ff,$00,$ff,$77,$b3,$51,$a8,$d4,$62,$39,$9c,$46,$2b,$15,$8a,$cd,$ee

 org $3FFF
 DEFB $00

 END



(https://i.postimg.cc/Cxvd3Mm9/picc.jpg)
Title: Re: create good cpr for gx4000
Post by: andycadley on 13:38, 07 January 23
Well, for one, you have to remember that all the firmware routines etc are in the BASIC cartridge, so you can't use any of those routines if you build your own cartridge.

So you'd need to write your own PrintChar routine. And include your own font too as the system font is also in the cartridge ROM.
Title: Re: create good cpr for gx4000
Post by: siudym on 14:34, 07 January 23
Where is the GX4000 screen memory located? $C000? Does a 40x25 character screen occupy a similar size to C64, i.e. 1000 bytes?
What register is used to set the Character Set's base location?
Title: Re: create good cpr for gx4000
Post by: andycadley on 14:41, 07 January 23
Wherever you put it via the CRTC registers.

It is never a character mapped mode like the C64 though, it is always a bitmap. Usually it takes up 16K but the are various ways to extend that if you want to overscan into the border.
Title: Re: create good cpr for gx4000
Post by: siudym on 20:03, 07 January 23
How can i synchronize cpu loop with screen refresh (vblank)? Using HALT doesn't work even though EI is enabled (so probably need to enable interrupts somewhere else?).
Title: Re: create good cpr for gx4000
Post by: andycadley on 21:08, 07 January 23
There some information on the wiki about synchronizing with the display at https://www.cpcwiki.eu/index.php/Synchronising_with_the_CRTC_and_display

Specifically you want something like:

ld b,&f5            ;; PPI port B input
.wait_vsync
in a,(c)            ;; [4] read PPI port B input
                    ;; (bit 0 = "1" if vsync is active,
                    ;;  or bit 0 = "0" if vsync is in-active)
rra                ;; [1] put bit 0 into carry flag
jp nc,wait_vsync    ;; [3] if carry not set, loop, otherwise continue
.continue

HALT alone won't work as the CPC normally has six interrupts per frame. And if you use the Plus features you can have interrupts on configurable scanlines as well as DMA interrupts (personally I often use a PRI interrupt after the main section of my game area to sync with, rather than the flyback so that I get more overall time but YMMV)
Title: Re: create good cpr for gx4000
Post by: siudym on 22:43, 07 January 23
Damn, it's hard to understand this system, I thought it was simpler :)

I have code that displays a sprite (4x size), simple write to XPos LSB Byte to make the movement visible. The sync code doesn't work.

What registers read Joystick in GX4000? I found such information, but I don't know what Bits are responsible for which button:

&B63B (6128) / &B4F1 (464) - (Joystick 1)
&B63E (6128) / &B4F4 (464) - (Joystick 2)

https://dl.dropboxusercontent.com/s/cs8jf1ggif8rw39/out.cpr

;------------------------------------------------

; This example shows a suggested startup for a Cartridge.
; Cartridge page 0 exists at $0000-$3FFF.
; Execution starts at $0000.

;------------------------------------------------

Variable        EQU $9000

;------------------------------------------------

    ORG $0000

    JP Start

;------------------------------------------------

    ORG $0038
    EI
    RET

;------------------------------------------------

Start:

    DI                            ; Disable Interrupts.
    IM 1                            ; Set interrupt Mode 1.

    LD BC,$F782                        ; Setup initial PPI port directions.
    OUT (C),C

    LD BC,$F400                        ; Set initial PPI port A (AY).
    OUT (C),C

    LD BC,$F600                        ; Set initial PPI port C (AY direction).
    OUT (C),C

    LD BC,$7FC0                        ; Set initial RAM configuration.
    OUT (C),C

;------------------------------------------------

    LD B,$BC                        ; Unlock ASIC so we can access ASIC registers.
    LD HL,Sequence

    LD E,17
Seq:

    LD A,(HL)
    OUT (C),A
    INC HL
    DEC E
    JR NZ,Seq

;------------------------------------------------
; Setup Sprite Pixel Data.
; The ASIC has internal "RAM" used to store the sprite pixel data.
; If you want to change the pixel data for a sprite then you need to copy new data into the internal "RAM".
; Page-in asic registers to $4000-$7FFF.
;------------------------------------------------

    LD BC,$7FB8
    OUT (C),C

    LD HL,Sprite_Pixel_Data                    ; Stored Sprite Pixel Data.

    LD DE,$4000                        ; Address of Sprite 0 pixel data, Sprite 0 pixel data is in the range $4000-$4100.

    LD BC,$100                        ; Length of pixel data for a single Sprite (16x16 = 256).
    LDIR

    LD BC,$7FA0                        ; Page-out ASIC Registers.
    OUT (C),C

;------------------------------------------------
; Setup Sprite Palette.
; The Sprites use a single 15 entry Sprite palette.
; Pen 0 is ALWAYS transparent.
; The Sprite palette is different to the screen palette.
;------------------------------------------------

    LD BC,$7FB8                        ; Page-in ASIC registers to $4000-$7FFF.
    OUT (C),C

    LD HL,Sprite_Colours                    ; Copy colours into ASIC sprite palette registers.
    LD DE,$6422
    LD BC,15*2
    LDIR

    LD BC,$7FA0                        ; Page-out ASIC registers.
    OUT (C),C

;------------------------------------------------
; Setup Sprite Properties.
; Each sprite has properties which define the x,y coordinates and x,y magnification.
;------------------------------------------------

    LD BC,$7FB8                        ; Page-in ASIC registers to $4000-$7FFF.
    OUT (C),C

    LD HL,0080                        ; Set x coordinate for Sprite 0.
    LD ($6000),HL

    LD HL,0080                        ; Set y coordinate for Sprite 0.
    LD ($6002),HL

    LD A,%1111                        ; Set Sprite x and y magnification, x magnification = 1, y magnification = 1.
    LD ($6004),A                        ; LD A,%1010 zwiekszy 2x X/Y Sprite, natomiast %1111 zwiekszy 4x X/Y

    LD BC,$7FA0                        ; Page-out ASIC registers.
    OUT (C),C

;------------------------------------------------

    LD HL,CRTC_Data_end                    ; Set initial CRTC settings (screen dimensions etc).
    LD BC,$BC0F

CRTC_Loop:

    OUT (C),C
    DEC HL
    LD A,(HL)
    INC B
    OUT (C),A
    DEC B
    DEC C
    JP P,CRTC_Loop

;------------------------------------------------

    LD HL,$C9FB
    LD ($0038),HL

    EI

    LD BC,$7FB8                        ; Enable ASIC Ram (will be visible in range $4000-$7FFF).
    OUT (C),C

;------------------------------------------------

; Your Code here...

    LD BC,$7F10                        ; Kolor Border na Blue.
    OUT (C),C
    LD C,$55
    OUT (C),C

    LD BC,$6400                        ; Kolor BGR na Yellow.
    OUT (C),C
    LD C,$4A
    OUT (C),C

    LD BC,$6401
    OUT (C),C
    LD C,$5C
    OUT (C),C

    LD BC,$6402
    OUT (C),C
    LD C,$56
    OUT (C),C

    LD BC,$6403
    OUT (C),C
    LD C,$4B
    OUT (C),C

    LD A,%11111111                        ; Little square...
    LD ($C000),A
    LD A,%11111111
    LD ($C800),A
    LD A,%11111111
    LD ($D000),A
    LD A,%11111111
    LD ($D800),A
    LD A,%11111111
    LD ($E000),A
    LD A,%11111111
    LD ($E800),A
    LD A,%11111111
    LD ($F000),A
    LD A,%11111111
    LD ($F800),A

;------------------------------------------------

Forever:

;    ld b,&f5        ;; PPI port B input
;wait_vsync
;    in a,(c)        ;; [4] read PPI port B input
;                ;; (bit 0 = "1" if vsync is active,
;                ;;  or bit 0 = "0" if vsync is in-active)
;    rra            ;; [1] put bit 0 into carry flag
;    jp nc,wait_vsync    ;; [3] if carry not set, loop, otherwise continue

    LD A,(Variable)
    INC A
    LD (Variable),A

    LD HL,($6000)                        ; Simple Sprite Moving Test.
    LD L,A
    LD ($6000),HL

    JR Forever

;------------------------------------------------

CRTC_Data:                            ; Your crtc setup values her ; these are examples

    DEFB $3f, $28, $2e, $8e, $26, $00, $19, $1e, $00, $07, $00,$00,$30,$00,$c0,$00

CRTC_Data_end:

;------------------------------------------------

Sprite_Colours:

    DEFW $0111                        ; Colour for Sprite Pen 01 (Najciemniejszy).
    DEFW $0222                        ; Colour for Sprite Pen 02.
    DEFW $0333                        ; Colour for Sprite Pen 03.
    DEFW $0444                        ; Colour for Sprite Pen 04.
    DEFW $0555                        ; Colour for Sprite Pen 05.
    DEFW $0666                        ; Colour for Sprite Pen 06.
    DEFW $0777                        ; Colour for Sprite Pen 07.
    DEFW $0888                        ; Colour for Sprite Pen 08.
    DEFW $0999                        ; Colour for Sprite Pen 09.
    DEFW $0AAA                        ; Colour for Sprite Pen 10.
    DEFW $0BBB                        ; Colour for Sprite Pen 11.
    DEFW $0CCC                        ; Colour for Sprite Pen 12.
    DEFW $0DDD                        ; Colour for Sprite Pen 13.
    DEFW $0EEE                        ; Colour for Sprite Pen 14.
    DEFW $0FFF                        ; Colour for Sprite Pen 15 (Najjasniejszy).

;------------------------------------------------
; - There is one Pixel per Byte (Bits 3..0 of each Byte define the palette index for this Pixel).
; - These Bytes are stored in a form that can be written direct to the ASIC Sprite Pixel Data.
;------------------------------------------------

Sprite_Pixel_Data:

    DEFB $01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01        ; Line 00.
    DEFB $01,$01,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$01,$01        ; Line 01.
    DEFB $01,$00,$02,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$02,$00,$01        ; Line 02.
    DEFB $01,$00,$00,$03,$00,$00,$00,$00,$00,$00,$00,$00,$03,$00,$00,$01        ; Line 03.
    DEFB $01,$00,$00,$00,$04,$00,$00,$00,$00,$00,$00,$04,$00,$00,$00,$01        ; Line 04.
    DEFB $01,$00,$00,$00,$00,$05,$00,$00,$00,$00,$05,$00,$00,$00,$00,$01        ; Line 05.
    DEFB $01,$00,$00,$00,$00,$00,$06,$00,$00,$06,$00,$00,$00,$00,$00,$01        ; Line 06.
    DEFB $01,$00,$00,$00,$00,$00,$00,$07,$07,$00,$00,$00,$00,$00,$00,$01        ; Line 07.
    DEFB $01,$00,$00,$00,$00,$00,$00,$08,$08,$00,$00,$00,$00,$00,$00,$01        ; Line 08.
    DEFB $01,$00,$00,$00,$00,$00,$09,$00,$00,$09,$00,$00,$00,$00,$00,$01        ; Line 09.
    DEFB $01,$00,$00,$00,$00,$0A,$00,$00,$00,$00,$0A,$00,$00,$00,$00,$01        ; Line 10.
    DEFB $01,$00,$00,$00,$0B,$00,$00,$00,$00,$00,$00,$0B,$00,$00,$00,$01        ; Line 11.
    DEFB $01,$00,$00,$0C,$00,$00,$00,$00,$00,$00,$00,$00,$0C,$00,$00,$01        ; Line 12.
    DEFB $01,$00,$0D,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$0D,$00,$01        ; Line 13.
    DEFB $01,$0E,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$0E,$01        ; Line 14.
    DEFB $01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01        ; Line 15.

;    DEFB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00        ; Line 00.
;    DEFB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00        ; Line 01.
;    DEFB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00        ; Line 02.
;    DEFB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00        ; Line 03.
;    DEFB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00        ; Line 04.
;    DEFB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00        ; Line 05.
;    DEFB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00        ; Line 06.
;    DEFB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00        ; Line 07.
;    DEFB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00        ; Line 08.
;    DEFB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00        ; Line 09.
;    DEFB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00        ; Line 10.
;    DEFB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00        ; Line 11.
;    DEFB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00        ; Line 12.
;    DEFB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00        ; Line 13.
;    DEFB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00        ; Line 14.
;    DEFB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00        ; Line 15.

;------------------------------------------------

Sequence:                            ; Sequence to unlock ASIC.

    DEFB $ff,$00,$ff,$77,$b3,$51,$a8,$d4,$62,$39,$9c,$46,$2b,$15,$8a,$cd,$ee

    org $3FFF
    DEFB $00

    END

Title: Re: create good cpr for gx4000
Post by: andycadley on 00:27, 08 January 23
The sync problem might be because your code is too fast. If you don't do enough after syncing with vblank, it'll still be active when you jump back. You can either introduce a big wait or use a similar loop but waiting for it to not be vblank first.

I'm not sure where you got those "registers" from, but reading the joystick isn't a straight IO read on the CPC. You have to do it via the keyboard, which is a bit more involved because it goes via the PPI.

See https://www.cpcwiki.eu/index.php/Programming:Keyboard_scanning
Title: Re: create good cpr for gx4000
Post by: andycadley on 13:49, 08 January 23
Looking through your code, I'm also not sure you have understood the colour selection properly. As it looks like, in the bit after "Your code here...", you set the border using the old gate array method and then try to set the other colours by OUTing to the Plus colour registers, but these are memory mapped rather than IO mapped so the results will not be what you expect.

As long as the ASIC is paged in you can set the screen and border colours by just writing to the memory addresses from $6400 to $6421 - you're already doing this with the hardware sprites, as their colour palette follows the display one. Doing it this way is easier and also allows access to the full 4096 colours, as opposed to the gate array method which restricts you to the standard 27 colour palette.

All the new Plus features are memory mapped in this way, so you have to be aware of whether the thing you want to access is memory mapped (i.e. use LD instructions) or IO mapped (uses OUT instructions). As well as being aware of whether the ASIC is paged in or OUT.
Title: Re: create good cpr for gx4000
Post by: siudym on 22:52, 14 January 23
How to set video mode on GX4000 ?
BC0E SCR_SET_MODE     ;in: A=mode (0=160x200x16, 1=320x200x4, 2=640x200x2)

It doesn't work because there is no BIOS Call's.
Title: Re: create good cpr for gx4000
Post by: roudoudou on 00:12, 15 January 23
you can change the color depth with RMR

https://www.cpcwiki.eu/index.php/Gate_Array#Register_2_-_Select_screen_mode_and_ROM_configuration

be aware that you do not change the "screen resolution" (CRTC is doing that) but only color depth (2, 4 or 16 colors aka 1, 2 or 4 bits)
Title: Re: create good cpr for gx4000
Post by: siudym on 12:40, 15 January 23
For someone experienced in the subject, it's probably simple, but for someone starting out, not quite.

Is it about writing to "&7Fxx" - where XX is the Register number, e.g.:

Register 2 - Select screen mode and ROM configuration - &7F02 ?

   LD BC,$7F02                  ; Register 2 - Select screen mode and ROM configuration.
   OUT (C),C

   LD A,%00000001               ; 0   1   Mode 1, 320x200 resolution, 4 colours
   OUT (C),A

?
It doesn't change anything.

I would like to change the mode to 160x200 in 16 colors.
Title: Re: create good cpr for gx4000
Post by: andycadley on 13:27, 15 January 23
&7Fxx is the port range, it's only partially decoded so it doesn't actually matter what the values in the lower byte are, all of them will go to the gate array.

The output byte is decode in one of four ways, depending on the upper two bits of the byte set - these are essentially selecting which of the gate array registers you end up writing to.

The screen mode is selected in the same register as the ROM banking and interrupt delay, so you need to be a little bit careful about what value you send depending on which ROMs need to be active.

In the simple case, you want both ROMs disabled, screen mode of 0 and writing to register 2, so that's a hex value of &8C and so you'd do something like.

LD BC, &7F8C
OUT (C), C


Title: Re: create good cpr for gx4000
Post by: siudym on 15:11, 15 January 23
It doesn't change anything, it's still 640x200 in 1BPP. :/
Title: Re: create good cpr for gx4000
Post by: siudym on 19:46, 15 January 23
OK I think you already know everything.... The screen does not change and is 80x25 characters, but the character in MODE0 is 2x8pix, MODE1 is in 4x8pix and MODE2 is in 8x8pix?
Title: Re: create good cpr for gx4000
Post by: andycadley on 20:27, 15 January 23
"Characters" don't really exist on the CPC hardware, they're a purely software construct because the display is a bitmap. 

Switching modes just trades the number of horizontal pixels for more colours, by doubling the size of pixels horizontally each time. The exact number of pixels can vary, because the CRTC settings can alter the physical dimensions of the screen area 

In mode 2, you have 2 colours, pixels are twice as high as they are wide and in 1us you get 16 pixels. On a "standard" CRTC setup, this is 80*25 8*8 characters.

In mode 1, you have 4 colours, pixels are approximately square and in 1us you get 8 pixels. On a "standard" CRTC setup, this is 40*25 8*8 characters.

In mode 0, you have 16 colours, pixels are twice as wide as they are high and in 1us you get 4 pixels. On a "standard" CRTC setup, this is 20*25 8*8 characters.
Title: Re: create good cpr for gx4000
Post by: gurneyh on 20:32, 15 January 23
The example given by andycadley defines the current mode as mode 0.

 
Can you show your complete current initialization code?
Title: Re: create good cpr for gx4000
Post by: siudym on 12:05, 16 January 23
Changing screen mode doesn't affect sprites pixel size? In the "1:1" size mode, they have the size of a pixel on the screen as if for the size of 640x200, so Sprite 16x16 in 1:1 is "squeezed" in width?
Title: Re: create good cpr for gx4000
Post by: andycadley on 12:41, 16 January 23
Correct. The resolution of the hardware sprites is entirely independent of the display mode. So at 1x1 magnification the pixel sizes are the same as Mode 2.
Title: Re: create good cpr for gx4000
Post by: roudoudou on 13:26, 16 January 23
this small source init a cartridge, then display 3 bitdeepth for background and 3 sprites with 3 different zoom

RASM source code
; first we need to define some constant in order to use RMR and RMR2

; RMR tags
MODE_0 equ 0
MODE_1 equ 1
MODE_2 equ 2
MODE_3 equ 3

ROM_OFF  equ %1100
ROM_BOTH equ 0
ROM_UP  equ %100
ROM_LOW  equ %1000

INTRESET equ %10000

macro RMR tags
ld bc,#7F80+{tags}
out (c),c
mend

; RMR2 tags
ROM0 equ 0
ROM1 equ 1
ROM2 equ 2
ROM3 equ 3
ROM4 equ 4
ROM5 equ 5
ROM6 equ 6
ROM7 equ 7

ASICOFF equ 0
ROM0000 equ 0
ROM4000 equ %01000
ROM8000 equ %10000
ASICON  equ %11000

macro RMR2 tags
ld bc,#7FA0+{tags}
out (c),c
mend


; init cartridge output mode
buildcpr

; write in the very first ROM, which will be mapped simultaneously in #0000 and #C000 at boot
bank 0

here_we_go

; interrupt should be disabled but this allow the code to be used as software reset
di
; unlike Winape, at boot, a real Amstrad Plus is not in IM 1
im 1
RMR ROM_LOW|MODE_2 ; disable upper ROM, in case of software reset

; reset RAM mapping in case of software reset, again...
ld bc,#7FC0
out (c),c

; reset RAM
ld hl,#0000
ld bc,4
.reset_ram repeat 32 : push hl : rend : djnz .reset_ram : dec c : jr nz,.reset_ram

; preset PPI
ld bc,#F782 : out (c),c
ld b,#F4 : out (c),0
ld b,#F6 : out (c),0

; setup a screen (not the one when prompt Basic on CPC...)
ld bc,#BC00 : out (c),c : ld bc,#BD00+63 : out (c),c
ld bc,#BC01 : out (c),c : ld bc,#BD00+32 : out (c),c
ld bc,#BC02 : out (c),c : ld bc,#BD00+42 : out (c),c
ld bc,#BC03 : out (c),c : ld bc,#BD8E    : out (c),c
ld bc,#BC04 : out (c),c : ld bc,#BD00+38 : out (c),c
ld bc,#BC06 : out (c),c : ld bc,#BD00+32 : out (c),c
ld bc,#BC07 : out (c),c : ld bc,#BD00+34 : out (c),c
ld bc,#BC09 : out (c),c : ld bc,#BD00+7  : out (c),c
ld bc,#BC0C : out (c),c : ld bc,#BD30    : out (c),c
ld bc,#BC0D : out (c),c : ld bc,#BD00    : out (c),c

; unlock asic
ld bc,#bc11
ld hl,asic_unlock_sequence
.unlock_asic
inc b
outi
dec c
jr nz,.unlock_asic

RMR2 ASICON|ROM0

; reset ASIC registers, in case of software reset...
ld sp,#8000
ld hl,#0000
ld b,l
.reset_asic repeat 32 : push hl : rend : djnz .reset_asic

;********************************************************************
;              now we are in an almost proper state
;********************************************************************

ld hl,#C9FB : ld (#38),hl ; install interrupt handler, doing nothing
ld hl,a_copier_en_ram     ; copy the code below into RAM
ld de,hl
ld bc,asic_unlock_sequence-a_copier_en_ram
ldir
a_copier_en_ram

RMR ROM_OFF ; then disconnect ROM, there will be only our interrupt handler in RAM, and this code
ld sp,#C000 ; place a stack outside video memory (better, not mandatory)
ei          ; enable interrupt

ld hl,#C000 ; put some garbage in #C000/#FFFF
.initvideoram ld (hl),l : inc l : jr nz,.initvideoram : inc h : jr nz,.initvideoram

ld hl,#4000 : ld b,3 ; put some garbage in first 3 sprites
.init3sprites ld (hl),l : inc l : jr nz,.init3sprites : inc h : djnz .init3sprites

ld hl,#6400 : ld b,128 ; put some linear colors in palette
.initcolors ld (hl),l : inc l : djnz .initcolors

ld ix,#6000 ; X/Y/Zoom settings
ld (ix+0),10 : ld (ix+2),72 : ld (ix+4),%101 ; no zoom
ld (ix+8),50 : ld (ix+10),70 : ld (ix+12),%1010 ; intermediate zoom
ld (ix+16),100 : ld (ix+18),50 : ld (ix+20),%1111 ; zoom max

ld hl,#6800 ; raster interrupt
multimode
ld (hl),80  : halt : RMR ROM_OFF|MODE_1 ; set mode 1 in line 81
ld (hl),160 : halt : RMR ROM_OFF|MODE_0 ; set mode 0 in line 161
ld (hl),255 : halt : RMR ROM_OFF|MODE_2 ; set mode 2 after the last visible line
jr multimode

asic_unlock_sequence defb #ff,#00,#ff,#77,#b3,#51,#a8,#d4,#62,#39,#9c,#46,#2b,#15,#8a,#cd,#ee
Title: Re: create good cpr for gx4000
Post by: siudym on 14:08, 23 January 23
Thanks. Works fine under both WinAPE and ARNOLD. But I still wonder what is wrong with the previous code (pasmo), because it works under WinAPE but under ARNOLD there are errors on the screen (random pixels).

Where is the error in the code?

(https://i.postimg.cc/FH673yPn/ape.jpg)

Arnold:
(https://i.postimg.cc/SNvyvyWn/arnold.jpg)
Title: Re: create good cpr for gx4000
Post by: roudoudou on 14:25, 23 January 23
Winape always initialize memory whereas CPC memory is NOT zeroed at boot (Arnold is wrong too, it's not random but a pattern of #00,#FF bytes)

that's why i always initialize RAM to zero at boot :)

Also Winape initialize CPC/Plus in IM 1 interrupt mode, so if you do not add IM 1 yourself, it will work with Winape, not with a real Plus
Title: Re: create good cpr for gx4000
Post by: andycadley on 16:57, 23 January 23
Interesting. I'm surprised that RAM values aren't random, do you have any further details on that? Not that relying on it is a good idea, just not something I would've expected to be set at power on.
Title: Re: create good cpr for gx4000
Post by: roudoudou on 17:17, 23 January 23
it's easy to see it on real situation if you dump memory before the firmware initialise it!

the pattern is 16x #00 | 16x #FF | ...

as far as i know, Caprice & CPCEmuPower initialize memory like this (because some softwares wont run properly if not)
Title: Re: create good cpr for gx4000
Post by: roudoudou on 18:00, 23 January 23
Quote from: andycadley on 16:57, 23 January 23Interesting. I'm surprised that RAM values aren't random, do you have any further details on that? Not that relying on it is a good idea, just not something I would've expected to be set at power on.
oups, i missed, it's 4x #00 then 4x #FF
on this photo, you can see random values in a memory expansion (XMEM) then the internal expansion of a 6128
(https://i.postimg.cc/9wBysMDH/extram-20221203-114824.jpg) (https://postimg.cc/9wBysMDH)
Title: Re: create good cpr for gx4000
Post by: TotO on 19:12, 23 January 23
There is a probability that you turn on the X-MEM and run an amazing DOOM game that nobody has programmed.
Title: Re: create good cpr for gx4000
Post by: roudoudou on 21:22, 23 January 23
Quote from: TotO on 19:12, 23 January 23There is a probability that you turn on the X-MEM and run an amazing DOOM game that nobody has programmed.
Maybe the board had an orgams (http://orgams.wikidot.com/guideutilisateur) ?
Title: Re: create good cpr for gx4000
Post by: siudym on 22:39, 23 January 23
I cleared C000-FFFF and now ARNOLD doesn't show garbage in the background. But I don't know why, but the yellow background color sets me to light blue/green. No matter what color I set, WinAPE displays it correctly and ARNOLD displays light blue/green.

(https://i.postimg.cc/qRTqMCH5/Bez-tytu-u.jpg)
Title: Re: create good cpr for gx4000
Post by: andycadley on 23:03, 23 January 23
Did you fix your palette selecting code?

As I mentioned on the previous page, the Plus palette registers are memory mapped rather than IO mapped, so you should be writing to them using LD rather than OUT (you can do it the old way but it limits you to the original 27 colours so I wouldn't if I were you).
Title: Re: create good cpr for gx4000
Post by: siudym on 11:38, 24 January 23
I changed and now I have Border Black, Background Color Green - instead of Blue Border and Yellow BGR :/


LD A,$55
LD HL,$7F10 ; Border Blue.
LD (HL),A

LD A,$4A
LD HL,$6400 ; BGR Yellow.
LD (HL),A

;LD A,$55                                                  ; Same
;LD ($7F10),A ; Border Blue.
;
;LD A,$4A
;LD ($6400),A ; BGR Yellow.

LD A,$5C
LD HL,$6401
LD (HL),A

LD A,$56
LD HL,$6402
LD (HL),A

LD A,$4B
LD HL,$6403
LD (HL),A

LD A,$56 ; Kolor 4 - Green.
LD HL,$6404
LD (HL),A

LD A,$5E ; Kolor 5 - .
LD HL,$6405
LD (HL),A

LD A,$40 ; Kolor 6 - .
LD HL,$6406
LD (HL),A

LD A,$4E ; Kolor 7 - .
LD HL,$6407
LD (HL),A

LD A,$5D ; Kolor 8 - .
LD HL,$6408
LD (HL),A

LD A,$5C ; Kolor 9 - .
LD HL,$6409
LD (HL),A

LD A,$52 ; Kolor 10 - .
LD HL,$640A
LD (HL),A

LD A,$53 ; Kolor 11 - .
LD HL,$640B
LD (HL),A

LD A,$59 ; Kolor 12 - .
LD HL,$640C
LD (HL),A

LD A,$47 ; Kolor 13 - Pink.
LD HL,$640D
LD (HL),A

LD A,$4F ; Kolor 14 - Pastel Magenta.
LD HL,$640E
LD (HL),A

LD A,$5B ; Kolor 15 - Pastel Cyan.
LD HL,$640F
LD (HL),A
Title: Re: create good cpr for gx4000
Post by: andycadley on 11:59, 24 January 23
Each colour register is two bytes long, because you have 4-bits of R, 4-bits of G and 4-bits B. The first byte of each register is R in the high bits and B in the low bits, the second is G in the low bits. So:

LD HL, &6400
LD A, &2F
LD (HL), A
INC L
LD A,&07
LD (HL),A

Will set PEN 0 to have an RGB value of &2F7

Pen 1 starts at &6402 and so on up to the border at &6420. This is then followed by the sprite colours in the same format.
Title: Re: create good cpr for gx4000
Post by: roudoudou on 12:01, 24 January 23
you can also use 16 bits write instruction

LD HL,#123 ; xGRB
LD (#6420),HL

@andy palette is from #6400 to #643F
Title: Re: create good cpr for gx4000
Post by: siudym on 12:39, 24 January 23
OK, now everything is clear, the colors work in both WinApe and Arnold.

LD HL,$000F ; xGRB Border max BLUE.
LD ($6420),HL

LD HL,$00F0 ; xGRB BGR 0 max RED.
LD ($6400),HL

LD HL,$0F00 ; xGRB BGR 1 max GREEN.
LD ($6402),HL

(...)

$6422+ = Sprite PAL.
Title: Re: create good cpr for gx4000
Post by: siudym on 14:37, 24 January 23
I would like to know how to set the size of the visible screen. Is it possible to change the screen from 640x200 to e.g. 512x200? I understand that there is no concept of "character" but let's say if I have a default size of visible "characters" in MODE2 in 80x25, change it to 64x25? So that the visible number of pixels horizontally change from 640 (80x8pix) to 512 (64x8pix) in mode2.
Title: Re: create good cpr for gx4000
Post by: andycadley on 14:41, 24 January 23
For that, you want the CRTC. https://www.cpcwiki.eu/index.php/CRTC

"Characters" as far as the CRTC are concerned are effectively 2 bytes of screen data horizontally, so it's like working with MODE 1 sized characters. So you'd set the width to 32 and the height to 25 to get what you're after. And then probably fiddle the position of the screen to recentre it.
Title: Re: create good cpr for gx4000
Post by: andycadley on 15:23, 24 January 23
To update the CRTC, first you select a register by OUTing to port BCxx, then send data to that register by OUTing to BDxx:

LD BC,&BC01; BCxx = Register Select
OUT (C), C : Select CRTC register 1
LD A, 32
INC B; BDxx = write data 
OUT (C), A; Set screen width to 64 bytes

DEC B
LD A,6
OUT (C), A; Select CRTC register 6
INC B
LD A, 25
OUT (C), A ; Set screen height to 25 chars
Title: Re: create good cpr for gx4000
Post by: siudym on 15:49, 24 January 23
I don't know what happened or I did something wrong, but suddenly when I try to check the code under winape and arnold, the background color is downloaded depending on the emulator from a different address...  :-X
I have WinApe background color from $6400, while Arnold uses it from $641E ....
Title: Re: create good cpr for gx4000
Post by: GUNHED on 16:37, 24 January 23
One is for colors, one is for sprites iirc.
Title: Re: create good cpr for gx4000
Post by: andycadley on 16:44, 24 January 23
$641E/1F is PEN 15. So either something is wrong with the code to clear the screen or you've changed something in the colour changing code that's broken something, I suspect. 
Title: Re: create good cpr for gx4000
Post by: siudym on 17:21, 24 January 23
sample code: winape yellow bgr (pen 0), on arnold red bgr (pen 15)

;------------------------------------------------

    ORG $0000

    JP Start

;------------------------------------------------

    ORG $0038
    EI
    RET

;------------------------------------------------

Start:

LD A,$00
LD ($C000),A

LD HL,$C000 ; clear screen
LD DE,$C001
LD BC,$3FF0
LDIR

    DI                            ; Disable Interrupts.
    IM 1                            ; Set interrupt Mode 1.

    LD BC,$F782                        ; Setup initial PPI port directions.
    OUT (C),C

    LD BC,$F400                        ; Set initial PPI port A (AY).
    OUT (C),C

    LD BC,$F600                        ; Set initial PPI port C (AY direction).
    OUT (C),C

    LD BC,$7FC0                        ; Set initial RAM configuration.
    OUT (C),C

;------------------------------------------------

    LD B,$BC                        ; Unlock ASIC so we can access ASIC registers.
    LD HL,Sequence

    LD E,17
Seq:

    LD A,(HL)
    OUT (C),A
    INC HL
    DEC E
    JR NZ,Seq

;------------------------------------------------
; Setup Sprite Pixel Data.
; The ASIC has internal "RAM" used to store the sprite pixel data.
; If you want to change the pixel data for a sprite then you need to copy new data into the internal "RAM".
; Page-in asic registers to $4000-$7FFF.
;------------------------------------------------

    LD BC,$7FB8
    OUT (C),C

    LD HL,Sprite_Pixel_Data                    ; Stored Sprite Pixel Data.

    LD DE,$4000                        ; Address of Sprite 0 pixel data, Sprite 0 pixel data is in the range $4000-$4100.

    LD BC,$100                        ; Length of pixel data for a single Sprite (16x16 = 256).
    LDIR

    LD BC,$7FA0                        ; Page-out ASIC Registers.
    OUT (C),C

;------------------------------------------------
; Setup Sprite Palette.
; The Sprites use a single 15 entry Sprite palette.
; Pen 0 is ALWAYS transparent.
; The Sprite palette is different to the screen palette.
;------------------------------------------------

    LD BC,$7FB8                        ; Page-in ASIC registers to $4000-$7FFF.
    OUT (C),C

    LD HL,Background_Colours
    LD DE,$6400
    LD BC,$22
    LDIR

    LD HL,Sprite_Colours                    ; Copy colours into ASIC sprite palette registers.
    LD DE,$6422
    LD BC,$20
    LDIR

    LD BC,$7FA0                        ; Page-out ASIC registers.
    OUT (C),C

;------------------------------------------------
; Setup Sprite Properties.
; Each sprite has properties which define the x,y coordinates and x,y magnification.
;------------------------------------------------

    LD BC,$7FB8                        ; Page-in ASIC registers to $4000-$7FFF.
    OUT (C),C

    LD HL,0080                        ; Set x coordinate for Sprite 0.
    LD ($6000),HL

    LD HL,0080                        ; Set y coordinate for Sprite 0.
    LD ($6002),HL

    LD A,%1111                        ; Set Sprite x and y magnification, x magnification = 1, y magnification = 1.
    LD ($6004),A                        ; LD A,%1010 zwiekszy 2x X/Y Sprite, natomiast %1111 zwiekszy 4x X/Y

    LD BC,$7FA0                        ; Page-out ASIC registers.
    OUT (C),C

;------------------------------------------------

    LD HL,CRTC_Data_end                    ; Set initial CRTC settings (screen dimensions etc).
    LD BC,$BC0F

CRTC_Loop:

    OUT (C),C
    DEC HL
    LD A,(HL)
    INC B
    OUT (C),A
    DEC B
    DEC C
    JP P,CRTC_Loop

;------------------------------------------------

    LD HL,$C9FB
    LD ($0038),HL

LD SP,$8000 ;  Set the Stack.

LD HL,$C9FB
LD ($8000),HL
EI

    LD BC,$7FB8                        ; Enable ASIC Ram (will be visible in range $4000-$7FFF).
    OUT (C),C

;------------------------------------------------

    LD A,%11111111                        ; Little square...
    LD ($C000),A
    LD A,%11111111
    LD ($C800),A
    LD A,%11111111
    LD ($D000),A
    LD A,%11111111
    LD ($D800),A
    LD A,%11111111
    LD ($E000),A
    LD A,%11111111
    LD ($E800),A
    LD A,%11111111
    LD ($F000),A
    LD A,%11111111
    LD ($F800),A

;------------------------------------------------

Forever:

    JR Forever

;------------------------------------------------

CRTC_Data:                            ; Your crtc setup values her ; these are examples

    DEFB $3f, $28, $2e, $8e, $26, $00, $19, $1e, $00, $07, $00,$00,$30,$00,$c0,$00

CRTC_Data_end:

;------------------------------------------------

Background_Colours: ; 16+1 color

DEFW $0FF0 ; xGRB Kolor 00 - Yellow ($6400).
DEFW $0FFF ; xGRB Kolor 01 - Bright White (255/255/255).
DEFW $0F00 ; xGRB Kolor 02 - MAX GREEN.
DEFW $0111 ; xGRB Kolor 03 -
DEFW $0111 ; xGRB Kolor 04 -
DEFW $0111 ; xGRB Kolor 05 -
DEFW $0111 ; xGRB Kolor 06 -
DEFW $0111 ; xGRB Kolor 07 -
DEFW $0111 ; xGRB Kolor 08
DEFW $0111 ; xGRB Kolor 09 -
DEFW $0111 ; xGRB Kolor 10 -
DEFW $0111 ; xGRB Kolor 11 -
DEFW $0111 ; xGRB Kolor 12 -
DEFW $0111 ; xGRB Kolor 13 -
DEFW $0111 ; xGRB Kolor 14 -
DEFW $00F0 ; xGRB Kolor 15 - MAX RED (ARNOLD BACKGROUND COLOR)...
DEFW $000F ; BORDER ($6420) - MAX Blue.

;------------------------------------------------

Sprite_Colours:

    DEFW $0000                       ; Colour for Sprite Pen 00.
    DEFW $0111                        ; Colour for Sprite Pen 01.
    DEFW $0222                        ; Colour for Sprite Pen 02.
    DEFW $0333                        ; Colour for Sprite Pen 03.
    DEFW $0444                        ; Colour for Sprite Pen 04.
    DEFW $0555                        ; Colour for Sprite Pen 05.
    DEFW $0666                        ; Colour for Sprite Pen 06.
    DEFW $0777                        ; Colour for Sprite Pen 07.
    DEFW $0888                        ; Colour for Sprite Pen 08.
    DEFW $0999                        ; Colour for Sprite Pen 09.
    DEFW $0AAA                        ; Colour for Sprite Pen 10.
    DEFW $0BBB                        ; Colour for Sprite Pen 11.
    DEFW $0CCC                        ; Colour for Sprite Pen 12.
    DEFW $0DDD                        ; Colour for Sprite Pen 13.
    DEFW $0EEE                        ; Colour for Sprite Pen 14.
    DEFW $0FFF                        ; Colour for Sprite Pen 15.

;------------------------------------------------

Sprite_Pixel_Data:

    DEFB $01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01        ; Line 00.
    DEFB $01,$01,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$01,$01        ; Line 01.
    DEFB $01,$00,$02,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$02,$00,$01        ; Line 02.
    DEFB $01,$00,$00,$03,$00,$00,$00,$00,$00,$00,$00,$00,$03,$00,$00,$01        ; Line 03.
    DEFB $01,$00,$00,$00,$04,$00,$00,$00,$00,$00,$00,$04,$00,$00,$00,$01        ; Line 04.
    DEFB $01,$00,$00,$00,$00,$05,$00,$00,$00,$00,$05,$00,$00,$00,$00,$01        ; Line 05.
    DEFB $01,$00,$00,$00,$00,$00,$06,$00,$00,$06,$00,$00,$00,$00,$00,$01        ; Line 06.
    DEFB $01,$00,$00,$00,$00,$00,$00,$07,$07,$00,$00,$00,$00,$00,$00,$01        ; Line 07.
    DEFB $01,$00,$00,$00,$00,$00,$00,$08,$08,$00,$00,$00,$00,$00,$00,$01        ; Line 08.
    DEFB $01,$00,$00,$00,$00,$00,$09,$00,$00,$09,$00,$00,$00,$00,$00,$01        ; Line 09.
    DEFB $01,$00,$00,$00,$00,$0A,$00,$00,$00,$00,$0A,$00,$00,$00,$00,$01        ; Line 10.
    DEFB $01,$00,$00,$00,$0B,$00,$00,$00,$00,$00,$00,$0B,$00,$00,$00,$01        ; Line 11.
    DEFB $01,$00,$00,$0C,$00,$00,$00,$00,$00,$00,$00,$00,$0C,$00,$00,$01        ; Line 12.
    DEFB $01,$00,$0D,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$0D,$00,$01        ; Line 13.
    DEFB $01,$0E,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$0E,$01        ; Line 14.
    DEFB $01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01,$01        ; Line 15.


;------------------------------------------------

Sequence:                            ; Sequence to unlock ASIC.

    DEFB $ff,$00,$ff,$77,$b3,$51,$a8,$d4,$62,$39,$9c,$46,$2b,$15,$8a,$cd,$ee

    ORG $3FFF
    DEFB $00

    END
Title: Re: create good cpr for gx4000
Post by: andycadley on 18:19, 24 January 23
I can't see it with a quick skim. I assume everything else still works? Sprites displayed etc? I.e. you haven't accidentally switched Arnold over to emulating a non-Plus CPC?
Title: Re: create good cpr for gx4000
Post by: siudym on 19:09, 24 January 23
Everything seems ok in the emulator settings.
Title: Re: create good cpr for gx4000
Post by: roudoudou on 20:27, 24 January 23
you cannot use LDIR "inside" the Asic, at least for colors because only green bits will be copied in blue/red
the 4 upper bits will be zeroed, as this is not a byte of memory, but an Asic register containing only 4 low bits
take a look at the source i posted some posts before
every init are done with stack (PUSH, PUSH, PUSH) or LD (HL),A : INC HL ... without reading a value to write it further
https://www.cpcwiki.eu/forum/programming/create-good-cpr-for-gx4000/msg224549/#msg224549

Title: Re: create good cpr for gx4000
Post by: siudym on 21:02, 24 January 23
I found Sprtes code on cpcwiki:
https://www.cpcwiki.eu/index.php/Programming:CPC_Plus_Hardware_Sprites

So is there an error?


;; page-in asic registers to &4000-&7fff
ld bc,&7fb8
out (c),c

;; copy colours into ASIC sprite palette registers
ld hl,sprite_colours
ld de,&6422
ld bc,15*2
ldir

;; page-out asic registers
ld bc,&7fa0
out (c),c

Title: Re: create good cpr for gx4000
Post by: roudoudou on 21:13, 24 January 23
oups, sorry, i've read too fast

you can copy from memory to Asic with an LDIR

but you cant (it's not recommended i mean) zero Asic values with a LDIR (source & destination inside Asic mapping) because some addresses cant be fully read
Title: Re: create good cpr for gx4000
Post by: siudym on 11:04, 25 January 23
The ASIC has its own built-in 16KB RAM? Any interference requires switching the 4000-7FFF range to its internal RAM?
Title: Re: create good cpr for gx4000
Post by: roudoudou on 11:38, 25 January 23
He surely have RAM (for sprites) but when reading in Asic memory-range, you do not read RAM. You read what Asic wants you to read, it's something else
As pixels of sprite are 4 bits only, you cannot assume you will have 0 or #F in the 4 upper bits
But you can write #FF in a sprite pixel because only 4 lower bits will be taken into account
some asic registers cannot be read back, they are write only (but winape will let you do such things...)
Title: Re: create good cpr for gx4000
Post by: siudym on 12:28, 25 January 23
So it works by "mapping" certain cpu addresses into the internal RAM built into the ASIC? Doesn't replace the whole 4000-7FFF with "your" RAM?
Title: Re: create good cpr for gx4000
Post by: andycadley on 13:01, 25 January 23
People use the phrase "ASIC RAM" unfortunately, because it's all memory mapped but there isn't really any RAM involved.

Paging the ASIC in just assigns the address space from $4000 to $7FFF to the ASICs registers. Some registers are duplicated (because they only partially decode the address bus), some are read/write. While the ASIC is paged in nothing should write to RAM in this address space (although using a non-compatible RAM expansion can cause issues if banked RAM is paged in when the ASIC is paged in)
Title: Re: create good cpr for gx4000
Post by: andycadley on 21:35, 25 January 23
Ah, I bet it'll be this bit:

LD A,$00
LD ($C000),A

LD HL,$C000 ; clear screen
LD DE,$C001
LD BC,$3FF0
LDIR


When you switch the CPC on, the Upper and Lower ROMs are paged in, but your cart only has a single 16K ROM so the upper ROM is effectively missing. I'll hazard a guess that WinAPE is treating that as a ROM full of 0's and Arnold (or RVM which I tried it in) is treating it as FFs (I suspect this is the correct value, but I'm not 100% on that).

So why does it break your code? Well when a ROM is paged in, reads come from the ROM by writes go to the RAM underneath. Using LDIR to block clear RAM like that doesn't work in that case, because instead of copying the RAM values, it's copying the ROM values instead. You could either turn the upper ROM off first (since you don't need it paged in) or just write a standard loop to iterate over the address range and write 0 to every byte.
Title: Re: create good cpr for gx4000
Post by: roudoudou on 22:17, 25 January 23
when booting CPR, with any number of ROM, the ROM 0 is mapped both LOW and HIGH :) (even with a 16K cartridge)
Title: Re: create good cpr for gx4000
Post by: andycadley on 22:36, 25 January 23
Quote from: roudoudou on 22:17, 25 January 23when booting CPR, with any number of ROM, the ROM 0 is mapped both LOW and HIGH :) (even with a 16K cartridge)
The docs disagree:

"At reset, page 0 is visible in the range &0000-&3fff. DFxx is reset to 0 at this time (logical page is set to 0). This means on GX4000 page 1 will be visible at &c000-&ffff. On the Plus, it depends on /EXP. If /EXP is low, page 1 will be visible at &c000-&ffff, otherwise page 3 will be visible and CPM will be auto booted."
Title: Re: create good cpr for gx4000
Post by: siudym on 11:58, 30 January 23
I made a simple demo of the game, but still a lot of work because I still don't fully understand some things in CPC+.
I have no idea if it works on real hardware, on WinAPE and Arnold it seems OK..
Title: Re: create good cpr for gx4000
Post by: roudoudou on 18:48, 30 January 23
this cannot RUN, you enable interrupt with stack in #8000 and Asic enabled, so the return address can't be written in Asic #7FFE
an interrupt will occur soon, return to zero, infinite loop
sure Winape is ok with that?
put stack in #C000 to be safe, this will push first values in #BFFE, #BFFC, ...
Title: Re: create good cpr for gx4000
Post by: andycadley on 19:00, 30 January 23
It looks like it runs in WinAPE, though not RetroVirtualMachine. On a real machine the ASIC registers would prevent write-through or reading of RAM locations even where there aren't registers, so I'd call that a WinAPE bug. Easily fixed by moving the stack to a "safe" location where you aren't going to be paging the ROM or ASIC in and out, #C000 is a good call (the Z80 decrements the stack pointer before PUSHing a value so it won't matter that #C000 itself might be under a ROM).

From what I can see in WinAPE though, you've certainly come along and I'm looking forward to seeing where you go with it. Keep asking questions if there is anything you don't understand. I'm thinking of trying to make some "how to write a game for the GX4000" tutorials and so seeing the bits that don't make sense to someone starting out is helpful in and of itself.
Title: Re: create good cpr for gx4000
Post by: siudym on 11:24, 31 January 23
Right. I changed it to $C000, forgot about it :/ I try not to use or change 4000-7FFF at all and leave "unswitchable" only for ASIC, and use 8000-BFFF as typical user RAM (I understand that in GX4000 it is safe, free space and NOTHING is using anything there?)

A tutorial like this would be great. Please believe me, but recently I started writing something for the first time for 3 systems - C64, Atari 8Bit and Amstrad. In the case of the C64/A8, I managed to do a lot in a short time and everything was very clear and transparent, while the Amstrad, I don't know why, but it is "not clear" for a beginner.

For now, I'm finishing my adventure with Amstrad, but I'm still glad that I got to know this interesting architecture a bit.
Title: Re: create good cpr for gx4000
Post by: andycadley on 11:44, 31 January 23
Yeah 8000-BFFF is free RAM, unless you deliberately map the lower ROM there (and you've probably no reason too).

I think one of the "interesting" things about the GX is that the hardware was originally designed to be a home computer and then the console features are kind of bolted on in a way that minimises backwards compatibility issues. The result is a system that doesn't work like a typical games console - a large bitmap display with no tiling, screen modes geared around text, a bunch of quirky legacy features  like the way hardware scrolling is split into two different bits etc.

By contrast the C64 hardware was basically designed as a games console and turned into a home computer in response to issues with the console market in the US. As a result its hardware is more like a traditional console (tiled display, sprites that can be multiplexed easily, sprite priorities and collision detection etc) and also doesn't suffer from having had to be shoehorned back onto an existing design.
Title: Re: create good cpr for gx4000
Post by: siudym on 12:32, 31 January 23
Does access to ASIC registers, e.g. interfering with asic sprite ram, consume more cpu cycles in any way? (relative to other systems with hardware sprites). I noticed that too many calculations on sprites can significantly slow down the CPU (the amount of code is not that big, and eats up cpu cycles relatively heavily).
Title: Re: create good cpr for gx4000
Post by: andycadley on 13:08, 31 January 23
No, if anything it's less because the sprites are entirely stored in hardware registers rather than in main memory (like most console designs) the ASIC doesn't ever need to stall the CPU to display sprites etc. Where it hurts though, is that you can't do something like change the entire sprite image by just re-pointing it at different memory - you always have to reload all the pixels (and do it individually). 

It's still an 8-bit CPU though, so obviously CPU time is very precious. And you annoyingly have to deal with 16-bit horizontal values (or scale them up at the last moment) because sprites positions are based on Mode 2 pixels.
Title: Re: create good cpr for gx4000
Post by: GUNHED on 23:19, 01 February 23
With some nice routines one can update only the changed bytes in the hardware sprites. That's not very flexible (and not usable for generic systems), but still quick.

Sadly of every byte only four bits are uses, that double the amount up 'bytes to by updated' roughly and sadly. But hey, that's what we got - time to make the best out of it.
Powered by SMFPacks Menu Editor Mod