Thanks
if disassembling the "garbage" reveals that isn't garbeage, what is
wrong ought to be in the handling of 6510 control port. Normally,
writing in a location in the rom area writes in the ram and reading it
gives the value in the rom.
Pages 5.39 to 5.46 of the PRG describes the use of the 6510 control port
and the memory maps obtainable thru the manipultation of the control
register.
HTH and
Best regards from Italy,
dott. Piergiorgio.
You probably set wrong d018 value or even forgot to add your own charset. If
you want to use ROM charset simply copy it somewhere in the same bank, it's
handy to have it on the same ROM address at $d000, the RAM under $d000 is
rarely used.
*=$0801
word eop
word 7102
byte $9e,"2061",0
eop
word 0
;-------------------------
charset = $d000
screen = $f000
;calc d018/bank values
ns = >screen<<2
nc = [>charset&$3f]>>2
v18 = [ns|nc]&$ff
bank = 3-[>screen>>6]
;-------------------------
; save cursorpos
jsr $e513
stx $fd
sty $fe
; set the vic bank and screen/charset in use
lda #v18
sta $d018
lda $dd00
and #$fc
ora #bank
sta $dd00
; copy charset from chargen to the RAM at the same address
; else load your favourite charset here
sei
ldx #$08
lda #$33 ; see the chargen at $d000
sta $01
lda #>charset
sta $fc
ldy #$00
sty $fb
lp1
lda ($fb),y
inc $01
sta ($fb),y
dec $01
iny
bne lp1
inc $fc
dex
bne lp1
lda #$37 ; ROM active
sta $01
cli
; now let's "print" something by writing directly on the new screen.
; write on RAM while ROM is active, VIC-II always sees the RAM
; apart the chargen shadow copies at $1xxx and $9xxx.
ldy #[endtext-ctext-1]
ptext
lda ctext,y
sta screen,y
dey
bpl ptext
jsr k1
; the KERNAL still uses the screen at $0400
; let's point it to the new screen
lda #>screen
sta $0288
jsr $e544
ldy #>ttext
lda #<ttext
jsr $ab1e
jsr k1
; now let's get back to normal (beware: color RAM is altered)
lda #$04
sta $0288
lda #$14
sta $d018
lda $dd00
and #$fc
ora #$03
sta $dd00
ldx $fd
ldy $fe
jmp $e50c
;--------------
k1
jsr $ffe4
beq k1
rts
ctext
scru "THIS TEXT WILL APPEAR AT $F000"
endtext
ttext
asc "THIS IS PRINTED WITH "
byte $9e,$12
asc "JSR $AB1E"
byte $92,$0d,$9a
asc "ON THE NEW SCREEN"
byte 0
http://iancoog.altervista.org/hid/screenf000.zip
--
-=[]=--- iAN CooG/HVSC & C64Intros ---=[]=-
I love you!, ohh mhhh, ahhh... Please Insert Coin to Continue!
Character or bitmap? If Character, likely what iAN CooG said. AFAIR,
iAN CooG is right on about the RAM at $D000, underneath the Device
memory space and Character ROM as a good place to put a stable soft
character map.
The "golden RAM" at $C000 is good for one that may be rewritten on the
fly (as with some tiled games) ~ and if you flip character map pointer
at the right line, you can have text tiles on the top part of the
screen and text input/output on the bottom.
Obviously bitmapped screen doesn't care about character sets.
> Character or bitmap?
He talks about character (text) screen of course, bitmap can't be at $f000
but $e000-$ff3f (or c000-df3f).
--
-=[]=--- iAN CooG/HVSC & C64Intros ---=[]=-
without words
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <stdbool.h>
#include <string.h>
void saveScreen(void);
void retrieveScreen(void);
bool initialized = false;
unsigned char d018;
unsigned char dd00;
unsigned char dd02;
void beginDoubleBuffer(void)
{
// We need to ensure that the character set is available when the
// VIC-II is pointed at the alternate screen location of $F000.
if(!initialized)
{
*(unsigned int*)(0xDC0E) = *(unsigned int*)(0xDC0E) & 0xFE; // Turn off interrupts
*(unsigned int*)(0x01) = *(unsigned int*)(0x01) & 0xFB; // Switch in RAM
memcpy( // Copy character set from ROM to RAM at $F800
(void*)0xF800,
(void*)0xD800,
0x0800);
*(unsigned int*)(0x01) = *(unsigned int*)(0x01) | 0x04; // Switch out RAM
*(unsigned int*)(0xDC0E) = *(unsigned int*)(0xDC0E) | 0x01; // Turn on interrupts
initialized = true;
}
// Save original values
d018 = *(unsigned int*)(0xD018);
dd00 = *(unsigned int*)(0xDD00);
dd02 = *(unsigned int*)(0xDD02);
// This is an assembler routine to save the screen under Kernel ROM at $F000
saveScreen();
// Make sure bits 0 and 1 are set to outputs
*(unsigned int*)(0xDD02) = *(unsigned int*)(0xDD02) | 0x03;
// Change banks
*(unsigned int*)(0xDD00) = (*(unsigned int*)(0xDD00) & 0xFC) | 0x00;
// Change screen memory offset
*(unsigned int*)(0xD018) = (*(unsigned int*)(0xD018) & 0x0F) | 0xC0;
// Change character set offset
*(unsigned int*)(0xD018) = (*(unsigned int*)(0xD018) & 0xF0) | 0x0E;
}
void endDoubleBuffer(void)
{
// Restore original values
*(unsigned int*)(0xDD02) = dd02;
*(unsigned int*)(0xDD00) = dd00;
*(unsigned int*)(0xD018) = d018;
}
int main(void)
{
clrscr();
(void)textcolor(COLOR_WHITE);
gotoxy(0, 19);
cprintf("Entering double buffer.");
gotoxy(0, 20);
cprintf("Press key to leave double buffer.");
beginDoubleBuffer();
(void)textcolor(COLOR_CYAN);
gotoxy(0, 21);
cprintf("During double buffer.");
(void)cgetc();
endDoubleBuffer();
(void)textcolor(COLOR_LIGHTBLUE);
gotoxy(0, 22);
cprintf("After double buffer.");
return EXIT_SUCCESS;
}
These, and all others, should be *(unsigned char *), right now you're
doing 16-bit peeks and pokes. You should consider #include
<peekpoke.h> though, and use PEEK() and POKE() instead, as they are
much easier to read. If you #include <c64.h> you can also use symbolic
names, like VIC.ctrl2, CIA2.pra, and CIA2.ddra.
(snip of C code)
Don't you feel that all this is a bit awkward, when in asm it's so simple to
achieve? You're spending a lot of time to make this work in C when in asm
it's done in few instructions and ACTUALLY works, always. C on C64 is a
waste of time for these low level things, use it only for what it's worth.
Anyway seems that you missed to set $288 to the new screen page ($f0), but
anyway cprintf seems to print always at $0400 whatever you poke there.
Switch to asm, less problems.
Thanks for the tips. I already knew about PEEKPOKE.H and actually used it when creating the code, then I converted it to pointer references to make the code smaller.
How does that make the code smaller by one bit, when peekpoke.h is
simply a set of macros that expand to pointer references at compile
time? Its only purpose is readability.
--
Linards Ticmanis
Payton,
cprintf uses the kernel screen pointer at $D1/$D2. First set $0288 to
the high byte of your video matrix, then call clrscr() to correctly
initialize the $D1/$D2 pointer.
Also why not write a function that takes the addresses of your desired
video matrix and dot data, checks them for consistency, and then sets up
$DD00, $D018 and $0288 automatically? It's a good exercise in
bit-twiddling and should make your calling code more readable.
--
Linards Ticmanis