Ciriciao folks!
This is another post with preparatory work for the ones that will follow.
I'd like to add features to VIC-II, these features will be controlled by flags in control registers the same way the current features are controlled now, e.g. to enable multicolor mode bit #6 of Control Register 1 ($D011) needs to be set.
I want to add two 8 bit registers that I'll call Control Register 3 and 4 (CR3 and CR4), at what addresses?
VIC-II uses 47 registers mapped to C64 memory locations from $D000 to $D02E, the range from $D02F to $D03F is available-ish,
then all registers repeat every 64 bytes until $D400 where the SID registers begin.
On one hand VIC-II evolutions use some or all of the available registers after $2E (VIC-IIe of the Commodore 128, VIC-II Kawari, VIC-III of the Commodore 65, VIC-IV of the Mega 65),
and on another hand if I added some new features in a new register, say at $D031, how would I initialize it and reset it?
Let's look at how the Kernal initializes the other VIC-II registers:
E5A8 A2 2F LDX #$2F E5AA BD B8 EC LDA $ECB8,X E5AD 9D FF CF STA $CFFF,X E5B0 CA DEX E5B1 D0 F7 BNE $E5AA
Registers from $CFFF + $2F down to $CFFF + $01, that is in the $D000-$D02E range, are initialized with values from a table at $ECB9:
ECB9 .BY $00,$00 ; sprite 0 x,y ECBB .BY $00,$00 ; sprite 1 x,y ECBD .BY $00,$00 ; sprite 2 x,y ECBF .BY $00,$00 ; sprite 3 x,y ECC1 .BY $00,$00 ; sprite 4 x,y ECC3 .BY $00,$00 ; sprite 5 x,y ECC5 .BY $00,$00 ; sprite 6 x,y ECC7 .BY $00,$00 ; sprite 7 x,y ECC9 .BY $00 ; sprite x MSBs ECCA .BY $9B ; control register 1: text mode ECCB .BY $37 ; raster = $137 ECCC .BY $00 ; light pen X ECCD .BY $00 ; light pen Y ECCE .BY $00 ; enabled sprites ECCF .BY $08 ; control register 2: hires ECD0 .BY $00 ; sprite Y expansion ECD1 .BY $14 ; video at $400, chars at $1000 ECD2 .BY $0F ; akcnowledge all interrupts ECD3 .BY $00 ; disable all interrupts ECD4 .BY $00 ; sprite priority ECD5 .BY $00 ; sprite multicolor ECD6 .BY $00 ; sprite X expansion ECD7 .BY $00 ; sprite-sprite collision ECD8 .BY $00 ; sprite-display collision ECD9 .BY $0E ; border color ECDA .BY $06 ; background color 0 ECDB .BY $01 ; background color 1 ECDC .BY $02 ; background color 2 ECDD .BY $03 ; background color 3 ECDE .BY $04 ; sprite multicolor 0 ECDF .BY $00 ; sprite multicolor 1 ECE0 .BY $01 ; sprite 0 color ECE1 .BY $02 ; sprite 1 color ECE2 .BY $03 ; sprite 2 color ECE3 .BY $04 ; sprite 3 color ECE4 .BY $05 ; sprite 4 color ECE5 .BY $06 ; sprite 5 color ECE6 .BY $07 ; sprite 6 color ECE7 .BY $4C ; sprite 7 color
Notice that also the two read-only registesr for the light pen are written to, with a nice $00 value.
This is where I want to add my two new registers, CR3 at $D013 and CR4 at $D014.
The default behavior will be that reads will give the light pen X and Y values and writes will go to the new registers.
To begin with, only bit #0 of CR3 will be implemented, it will be used to enable reading control registers 3 and 4.
The Kernal reset routine will clear the flag for us so that after reset the registers will behave like in a standard VIC-II.
Implementation in Vice
First let's add a macro in file vice/src/viciisc/viciitypes.h that will be used to access the new flag Control Registers Enable:
/* VIC-II WIF flags */ #define WIV_CRE (vicii.regs[0x13] & 0x01) /* Control Registers Enable: reads to $13 and $14 give control registers instead of light pen position */
Then in file vice/src/viciisc/vicii-mem.c mainly two new store functions are added:
inline static void d013_store(const uint8_t value) { VICII_DEBUG_REGISTER(("WIV Control register 3: $%02X", value)); vicii.regs[0x13] = value; } inline static void d014_store(const uint8_t value) { VICII_DEBUG_REGISTER(("WIV Control register 4: $%02X", value)); vicii.regs[0x14] = value; }
to be called from the switch() for write accesses to registers:
/* Store a value in a VIC-II register. */ void vicii_store(uint16_t addr, uint8_t value) { // ... switch (addr) { //... case 0x13: /* $D013: VIC-II WIV Control Register 3 */ if (IS_WIV) { d013_store(value); } break; case 0x14: /* $D014: VIC-II WIV Control Register 4 */ if (IS_WIV) { d014_store(value); } break;
and return the new registers content for read accesses to registers:
/* Read a value from a VIC-II register. */ uint8_t vicii_read(uint16_t addr) { // ... switch (addr) { // ... case 0x13: /* $D013: Light Pen X or VIC-II WIV Control Register 3 */ if (IS_WIV && WIV_CRE) { VICII_DEBUG_REGISTER(("WIV Control Register 3: $%02X", vic.regs[addr])); value = vicii.regs[addr]; break; } VICII_DEBUG_REGISTER(("Light pen X: %d", vicii.light_pen.x)); value = vicii.light_pen.x; break; case 0x14: /* $D014: Light Pen Y or VIC-II WIV Control Register 4 */ if (IS_WIV && WIV_CRE) { VICII_DEBUG_REGISTER(("WIV Control Register 4: $%02X", vic.regs[addr])); value = vicii.regs[addr]; break; }
Implementation in VIC-II Kawari
Let's add a new configuration file for our variant of the VIC-II Kawari firmware, that I will call WIV1, where I define a macro to guard my new extensions, the rest is based on the MAIN variant.
I'm adding the new configuration file boards/rev_4H/config.vh.WIV1LH only in the rev_4H directory because I'm developing on a mini board.
... `define VARIANT_NAME1 8'h57 // W `define VARIANT_NAME2 8'h49 // I `define VARIANT_NAME3 8'h56 // V `define VARIANT_NAME4 8'h31 // 1 `define VARIANT_SUFFIX_1 8'd76 // L `define VARIANT_SUFFIX_2 8'd72 // H `define VARIANT_SUFFIX_3 8'd0 `define VARIANT_SUFFIX_4 8'd0 ... `define WIV_EXTENSIONS 1 ...
Then in file hdl/registers.v,
similarly to what has been done for Vice, reading and writing to registers is extended to implenmet CR3 and CR4.
Reading:
`ifdef WIV_EXTENSIONS /* 0x13 */ `REG_LIGHT_PEN_X: begin if (wiv_cre) begin dbo[0] <= wiv_cre; dbo[7:1] <= wiv_cr3_unused; end else begin dbo[7:0] <= lpx; end end /* 0x14 */ `REG_LIGHT_PEN_Y: begin if (wiv_cre) begin dbo[7:0] <= wiv_cr4_unused; end else begin dbo[7:0] <= lpx; end end `else
and writing:
`ifdef WIV_EXTENSIONS /* 0x13 */ `REG_LIGHT_PEN_X: begin wiv_cre <= dbi[0]; wiv_cr3_unused[7:1] = dbi[7:1]; end /* 0x14 */ `REG_LIGHT_PEN_Y: begin wiv_cr4_unused[7:0] = dbi[7:0]; end `endif //WIV_EXTENSIONS
BASIC example
This simple BASIC example writes two even numbers (with bit 0 clear) to CR3 and CR4 and tries to read it back,
then tries with two odd numbers (with bit 0 set).
Reading from CR3 and CR4 when bit 0 of CR3 is clear gives back the X and Y positions of the light pen,
reading when bit 0 is set gives back the content of the brand new CR3 and CR4 registers, yay!
5 rem ** read/write new registers 10 c3=53267 15 c4=53268 20 poke c3,100 25 poke c4,100 30 printpeek(c3)" = 100? (might be)" 35 printpeek(c4)" = 100? (might be)" 40 poke c3,101 45 poke c4,101 50 printpeek(c3)" = 101! (must be)" 55 printpeek(c4)" = 101! (must be)"
No comments:
Post a Comment