[cc65]How can I redefine characters and use colors?

Talk about programming of homebrew games only.
Fabrizio Caruso
Posts: 41
Joined: Mon Feb 05, 2018 9:23 am
Contact:

[cc65]How can I redefine characters and use colors?

Post by Fabrizio Caruso » Sat Feb 10, 2018 5:20 pm

Hi!

I have manage to get my universal game CROSS CHASE to use a 16k rom.
The game is using very crude graphics as provided by conio.h in CC65 for the Creativision, i.e., standard white characters on a black background in 32x24 text mode.

I would like to make it more colorful.
If the video chip works like the one on the MSX1, then it must be possible to assign a color to groups of 8 characters if I am not wrong.
How do I do it with the Creativision? How do I do it possibly in C with CC65?

I would also like to use redefined characters.
Again how?

Fabrizio
User avatar
carlsson
Posts: 514
Joined: Fri Jun 13, 2008 7:39 am
Location: Västerås, Sweden

Re: [cc65]How can I redefine characters and use colors?

Post by carlsson » Tue Feb 27, 2018 11:03 am

I believe you need to set up the VDP vectors at $BFF0. I used these values previously:

Code: Select all

  .byte $00  ; VDP 0: External video off, M2=0
  .byte $A2  ; VDP 1: 16K mode, Screen not active, Generate interrupts
             ;        M1=0, M3=0, Sprites = 16x16 unmagnified
  .byte $04  ; VDP 2: Pattern Name Table = 04 * $400 = $1000
  .byte $4E  ; VDP 3: Color Table Address =    0001 0011 1000 0000 = $1380
  .byte $00  ; VDP 4: Pattern Generator Table = $0000
  .byte $26  ; VDP 5: Sprite Attribute Table = 0001 0011 0000 0000 = $1300
  .byte $01  ; VDP 6: Sprite Generator Table = 0000 1000 0000 0000 = $0800
  .byte $05 ; VDP 7: TC=0 (transparent fg), BD=5 (light blue bg)

  ; VDP memory addresses (not CPU addresses)
  ; $0000 Pattern generator table = character definitions (2048 bytes)
  ; $0800 Sprite generator table = sprite definitions (2048 bytes)
  ; $1000 Pattern name table = screen memory (32x24 = 768 bytes)
  ; $1300 Sprite attribute table (128 bytes)
  ; $1380 Color table address (32 bytes)
Then I draw the start screen in a SEI and enable the screen:

Code: Select all

  LDA #$E2		;new value including set screen active bit
  STA VDP_Status_Write
  LDA #$81		;write into register 1
  STA VDP_Status_Write	;see comments on that BIOS routine above
I haven't used CC65 but I presume it sets up a lot of this already. You can probably peek at the VDP vectors in the end of the ROM to see which memory layout is used. As you can see, my pattern generator (characters) is at $0000, followed by pattern name table (screen matrix) at $1000 and color table at $1380, all within the VDP RAM.
Fabrizio Caruso
Posts: 41
Joined: Mon Feb 05, 2018 9:23 am
Contact:

Re: [cc65]How can I redefine characters and use colors?

Post by Fabrizio Caruso » Wed Mar 14, 2018 11:23 am

Thanks Carlsson,

I am coding in ANSI C and using nearly no Assembly.

I am not sure I understand your post.

I can guess that:
LDA #$E2 ;new value including set screen active bit
STA VDP_Status_Write
LDA #$81 ;write into register 1
STA VDP_Status_Write ;see comments on that BIOS routine above

Is writing #$E2 into the first register of the VDP.
Whay is 8 in #$81 used for?

Which registers should I sed to set the colors for the 8-character groups?

What are the VDP Vectors used for?
Do I need to POKE those values starting at $BFF0?
I.e., POKE(0xBFF0,0x00); POKE(0xBFF1,0xA2); etc....
Fabrizio Caruso
Posts: 41
Joined: Mon Feb 05, 2018 9:23 am
Contact:

Re: [cc65]How can I redefine characters and use colors?

Post by Fabrizio Caruso » Wed Mar 14, 2018 1:11 pm

@carlsson, in a previous reply you said I should add #$40 and not #$80 to write.

I would have expected
LDA #$E2 ;new value including set screen active bit
STA VDP_Status_Write
LDA #$41 ;write into register 1
...
instead of
LDA #$81 ;write into register 1
User avatar
carlsson
Posts: 514
Joined: Fri Jun 13, 2008 7:39 am
Location: Västerås, Sweden

Re: [cc65]How can I redefine characters and use colors?

Post by carlsson » Wed Mar 14, 2018 2:24 pm

Very good questions! Actually I copied that bit of code from Kurt's Titanic demo. In his comments he mentions the BIOS routine VDP_Regwrite at $FE1F:
BIOS_VDP_Regwrite = $FE1F
; this is a short subroutine which writes the contents of a into VDP register x. It can also be used for initializing the read/write
; address, in this case a is the LSB of the address, the lower 6 bits of x are the MSB, bit 6 of x contains 0 or 1 (0 for read, 1 for write),
; and bit 7 of x has to be set to 1 (which gets converted to 0 by the BIOS routine)
However neither he nor me are using the BIOS routines. Instead we address the VDP registers directly, either while interrupts are disabled or at vertical blank. I would need to investigate further into the VDP to tell the difference, if bit 7 needs to be set in order to write to the VDP registers 0-7 and needs to be cleared in order to write to VDP memory.

I can't recall if you really need to disable the screen when the program is booted, just that otherwise you might see the system drawing the screen instead of it appearing at once. For sure you want to disable interrupts or otherwise hook the VDP writes to the interrupt routine running at vertical blank. Writing to the VDP at any time will cause errors, which I observed once I moved my game from the old FunnyMu emulator to real hardware. The newer emulator is rather accurate about that.

VDP register 0: Graphics mode and flag for external video (I think this only works on NTSC TMS9918, not PAL TMS9929)
VDP register 1: Memory size (16K), enable/disable screen, enable/disable generation of interrupts (VBLANK), sprite size
VDP register 2: Pattern Name Table (768 bytes), value multiplied by 1024 so setting it to 4 means the table starts at VDP memory address $1000
VDP register 3: Color Address Table (32 bytes), value multiplied by 64 so setting it to $4E means the table starts at $1380
VDP register 4: Pattern Generator Table (2048 bytes), value multiplied by ? but usually you want this at $0000 anyway
VDP register 5: Sprite Attribute Table (128 bytes), value multiplied by 128 so setting it to $26 means the table starts at $1300
VDP register 6: Sprite Generator Table (2048 bytes), value multiplied by 2048 so setting it to $01 means the table starts at $0800
VDP register 7: Initial foreground color (upper nybble) and background color (lower nybble)

VDP register 3 thus sets the location of the 32 bytes long color address table, where each byte defines the background and foreground of 8 consequent characters.

I believe those vectors should already be at the end of the binary file produced by the compiler, together with vectors for the start address and interrupt handler. Check your file with a binary editor. How you can change them at compile time would need studying the library files. You can't POKE to $BFF0 because that will be game ROM and the BIOS has already copied the values from that location into the VDP when powering on. However you should be able to change VDP register values within the program, either with interrupts turned off or in the interrupt routine at VBLANK.
Fabrizio Caruso
Posts: 41
Joined: Mon Feb 05, 2018 9:23 am
Contact:

Re: [cc65]How can I redefine characters and use colors?

Post by Fabrizio Caruso » Thu Mar 15, 2018 10:45 am

Thanks Carlsson,

My project is written in ANSI C with almost no Assembly for obvious reasons (it is a universal 8-bit game and framework
for about 100 different 8-bit systems with any 8-bit CPU, i.e., Motorola 6809, Z80, 6502 and their clones/variants)
Moreover I am not fluent in any Assembly.

For the Creativision target, I would like to have to simple routines:
VPOKE(LOC, val) -> writes value val onto VDP address LOC
VPEEK(LOC) -> return value in VDP address LOC

What is the simplest way to do this?

I understand that the VDP vectors have to be set or I use whatever is the default setting done by CC65.

Fabrizio
User avatar
Mobsie
Posts: 717
Joined: Fri Jun 13, 2008 10:38 am
Location: Weinheim, Germany

Re: [cc65]How can I redefine characters and use colors?

Post by Mobsie » Fri May 11, 2018 9:38 am

you can change the VDP stuff at any time you want!
Fabrizio Caruso
Posts: 41
Joined: Mon Feb 05, 2018 9:23 am
Contact:

Re: [cc65]How can I redefine characters and use colors?

Post by Fabrizio Caruso » Fri Oct 04, 2019 8:03 am

Sorry guys, @carlsoon, I don't understand what the screen active bit is and how the VDP registers are accessed in your code
LDA #$E2 ;new value including set screen active bit
STA VDP_Status_Write
LDA #$81 ;write into register 1
STA VDP_Status_Write ;see comments on that BIOS routine above

Which is the value of the address VDP_Status_Write?

You are writing $E2 into the first register? The first register is addressed with $82?
What is the value in $E2 without the screen active bit?

I would like to do thing like redefine characters and set characters colors in mode 1.
Fabrizio Caruso
Posts: 41
Joined: Mon Feb 05, 2018 9:23 am
Contact:

Re: [cc65]How can I redefine characters and use colors?

Post by Fabrizio Caruso » Fri Oct 04, 2019 8:06 am

@Mobsie @Carlsson I understand I need to write into VDP memory and registers.
Are registers just part of VDP memory and are they addressed in the same (indirect) way by writing data into VDP_Status_Write?

MSX Basic has something as simple as VPOKE and VPEEK which let us write and read into video ram. How could I implement such macros?
Fabrizio Caruso
Posts: 41
Joined: Mon Feb 05, 2018 9:23 am
Contact:

Re: [cc65]How can I redefine characters and use colors?

Post by Fabrizio Caruso » Fri Oct 04, 2019 8:01 pm

I may have figured out how to write onto VDP registers and memory:

Code: Select all

#define VDP_DATA 0xC000
#define VDP_WRITE 0xC002
#include <peekpoke.h>

void VDP_REGISTER(unsigned char reg, unsigned char value)
{
    POKE(VDP_DATA,value);
    POKE(VDP_WRITE,(reg|0x80));
}

void VDP_POKE(unsigned short address, unsigned char value)
{
    POKE(VDP_DATA,(address&0x0F));
    POKE(VDP_DATA,(address>>4)|0x40);
    POKE(VDP_WRITE,value);
}


I hope this is correct.
Post Reply