mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-08-07 06:30:04 +00:00
794 lines
26 KiB
Plaintext
794 lines
26 KiB
Plaintext
// Interactive Explorer for C64DTV Screen Modes
|
|
import "c64dtv.kc"
|
|
import "print.kc"
|
|
import "keyboard.kc"
|
|
import "bitmap-draw.kc"
|
|
|
|
void main() {
|
|
asm { sei } // Disable normal interrupt (prevent keyboard reading glitches and allows to hide basic/kernal)
|
|
// Disable kernal & basic
|
|
*PROCPORT_DDR = PROCPORT_DDR_MEMORY_MASK;
|
|
*PROCPORT = PROCPORT_RAM_IO;
|
|
// Enable DTV extended modes
|
|
*DTV_FEATURE = DTV_FEATURE_ENABLE;
|
|
keyboard_init();
|
|
gfx_init();
|
|
while(true) {
|
|
// Let the user change the GFX configuration
|
|
form_mode();
|
|
// Show the GFX configuration
|
|
gfx_mode();
|
|
}
|
|
}
|
|
|
|
// VIC Screens
|
|
const byte* VIC_SCREEN0 = $4000;
|
|
const byte* VIC_SCREEN1 = $4400;
|
|
const byte* VIC_SCREEN2 = $4800;
|
|
const byte* VIC_SCREEN3 = $4c00;
|
|
const byte* VIC_SCREEN4 = $5000;
|
|
// VIC Charset from ROM
|
|
const byte* VIC_CHARSET_ROM = $5800;
|
|
// VIC Bitmap
|
|
const byte* VIC_BITMAP = $6000;
|
|
|
|
// 8BPP Chunky Bitmap (contains 8bpp pixels)
|
|
const dword PLANE_8BPP_CHUNKY = $20000;
|
|
// Plane with horisontal stripes
|
|
const dword PLANE_HORISONTAL = $30000;
|
|
// Plane with vertical stripes
|
|
const dword PLANE_VERTICAL = $32000;
|
|
// Plane with horisontal stripes every 2 pixels
|
|
const dword PLANE_HORISONTAL2 = $34000;
|
|
// Plane with vertical stripes every 2 pixels
|
|
const dword PLANE_VERTICAL2 = $36000;
|
|
// Plane with blank pixels
|
|
const dword PLANE_BLANK = $38000;
|
|
// Plane with all pixels
|
|
const dword PLANE_FULL = $3a000;
|
|
// Plane with all pixels
|
|
const dword PLANE_CHARSET8 = $3c000;
|
|
|
|
// Get plane address from a plane index (from the form)
|
|
dword get_plane(byte idx) {
|
|
if(idx==0) {
|
|
return (dword)VIC_SCREEN0;
|
|
} else if(idx==1) {
|
|
return (dword)VIC_SCREEN1;
|
|
} else if(idx==2) {
|
|
return (dword)VIC_SCREEN2;
|
|
} else if(idx==3) {
|
|
return (dword)VIC_SCREEN3;
|
|
} else if(idx==4) {
|
|
return (dword)VIC_BITMAP;
|
|
} else if(idx==5) {
|
|
return (dword)VIC_CHARSET_ROM;
|
|
} else if(idx==6) {
|
|
return (dword)PLANE_8BPP_CHUNKY;
|
|
} else if(idx==7) {
|
|
return (dword)PLANE_HORISONTAL;
|
|
} else if(idx==8) {
|
|
return (dword)PLANE_VERTICAL;
|
|
} else if(idx==9) {
|
|
return (dword)PLANE_HORISONTAL2;
|
|
} else if(idx==10) {
|
|
return (dword)PLANE_VERTICAL2;
|
|
} else if(idx==11) {
|
|
return (dword)PLANE_CHARSET8;
|
|
} else if(idx==12) {
|
|
return (dword)PLANE_BLANK;
|
|
} else if(idx==13) {
|
|
return (dword)PLANE_FULL;
|
|
}
|
|
return (dword)VIC_SCREEN0;
|
|
}
|
|
|
|
// Get the VIC screen address from the screen index
|
|
byte* get_vic_screen(byte idx) {
|
|
if(idx==0) {
|
|
return VIC_SCREEN0;
|
|
} else if(idx==1) {
|
|
return VIC_SCREEN1;
|
|
} else if(idx==2) {
|
|
return VIC_SCREEN2;
|
|
} else if(idx==3) {
|
|
return VIC_SCREEN3;
|
|
} else if(idx==4) {
|
|
return VIC_SCREEN4;
|
|
}
|
|
return VIC_SCREEN0;
|
|
}
|
|
|
|
// Get the VIC charset/bitmap address from the index
|
|
byte* get_vic_charset(byte idx) {
|
|
if(idx==0) {
|
|
return VIC_CHARSET_ROM;
|
|
} else if(idx==1) {
|
|
return VIC_BITMAP;
|
|
}
|
|
return VIC_CHARSET_ROM;
|
|
}
|
|
|
|
// Screen containing the FORM
|
|
const byte* FORM_SCREEN = $0400;
|
|
// Charset used for the FORM
|
|
const byte* FORM_CHARSET = $1800; // Charset ROM
|
|
|
|
byte[] FORM_TEXT =
|
|
" C64 DTV Graphics Mode Explorer @"z +
|
|
" @"z +
|
|
" PRESET 0 Standard Charset @"z +
|
|
" @"z +
|
|
" CONTROL PLANE A VIC II @"z +
|
|
" bmm 0 pattern p0 screen s0 @"z +
|
|
" mcm 0 start 00 gfx g0 @"z +
|
|
" ecm 0 step 00 colors c0 @"z +
|
|
" hicolor 0 modulo 00 @"z +
|
|
" linear 0 COLORS @"z +
|
|
" color off 0 PLANE B palet 0 @"z +
|
|
" chunky 0 pattern p0 bgcol0 00 @"z +
|
|
" border off 0 start 00 bgcol1 00 @"z +
|
|
" overscan 0 step 00 bgcol2 00 @"z +
|
|
" modulo 00 bgcol3 00 @"z +
|
|
"@"z ;
|
|
byte[] FORM_COLS =
|
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@"z +
|
|
" @"z +
|
|
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa@"z +
|
|
" @"z +
|
|
" nnnnnnnnnnnn mmmmmmmmmm ooooooooo @"z +
|
|
" nnnnnnnnnnnn mmmmmmmmmm ooooooooo @"z +
|
|
" nnnnnnnnnnnn mmmmmmmmmm ooooooooo @"z +
|
|
" nnnnnnnnnnnn mmmmmmmmmm ooooooooo @"z +
|
|
" nnnnnnnnnnnn mmmmmmmmmm @"z +
|
|
" nnnnnnnnnnnn jjjjjjjjj @"z +
|
|
" nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @"z +
|
|
" nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @"z +
|
|
" nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @"z +
|
|
" nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @"z +
|
|
" nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @"z +
|
|
" nnnnnnnnnnnn mmmmmmmmmm jjjjjjjjj @"z +
|
|
"@"z ;
|
|
|
|
// Number of form fields
|
|
byte form_fields_cnt = 36;
|
|
// Form fields x/y-positions
|
|
byte[] form_fields_x = { 8, 12, 12, 12, 12, 12, 12, 12, 12, 12, 25, 24, 25, 24, 25, 24, 25, 25, 24, 25, 24, 25, 24, 25, 37, 37, 37, 37, 36, 37, 36, 37, 36, 37, 36, 37 };
|
|
byte[] form_fields_y = { 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 5, 6, 6, 7, 7, 8, 8, 11, 12, 12, 13, 13, 14, 14, 5, 6, 7, 10, 11, 11, 12, 12, 13, 13, 14, 14 };
|
|
// Form field max values (all values are in the interval 0..max)
|
|
byte[] form_fields_max = { 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, $d, $f, $f, $f, $f, $f, $f, $d, $f, $f, $f, $f, $f, $f, $3, $1, $4, $1, $f, $f, $f, $f, $f, $f, $f, $f };
|
|
// Form fields values
|
|
byte[] form_fields_val = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
|
|
|
// Preset: Standard Char Mode
|
|
byte[] preset_stdchar = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
|
// Preset: Extended Color Char Mode
|
|
byte[] preset_ecmchar = { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 5, 0, 6 };
|
|
// Preset: Standard Bitmap
|
|
byte[] preset_stdbm = { 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
|
// Preset: MC Bitmap
|
|
byte[] preset_mcbm = { 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0 };
|
|
// Preset: Hicolor Standard Char Mode
|
|
byte[] preset_hi_stdchar = { 4, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
|
|
// Preset: Hicolor Extended Color Char Mode
|
|
byte[] preset_hi_ecmchar = { 5, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 3, 4, 6, 8, 9, $c, $c };
|
|
// Preset: Two plane mode
|
|
byte[] preset_twoplane = { 6, 1, 0, 1, 1, 1, 0, 0, 0, 0, 7, 0, 0, 0, 1, 0, 0, 8, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 7, 0, $d, 4, 0, 0, 0, 0 };
|
|
// Preset: Chunky 8bpp
|
|
byte[] preset_chunky = { 7, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 8, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
|
|
// Preset: Sixs FREDs mode
|
|
byte[] preset_sixsfred = { 8, 1, 1, 1, 1, 1, 0, 0, 0, 0, $9, 0, 0, 0, 1, 0, 0, $a, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
|
|
// Preset: Sixs FREDs 2 mode
|
|
byte[] preset_sixsfred2 = { 9, 1, 1, 1, 0, 1, 0, 0, 0, 0, $9, 0, 0, 0, 1, 0, 0, $a, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
|
|
// Preset: 8bpp Pixel Cell
|
|
byte[] preset_8bpppixelcell = { 10, 0, 1, 1, 1, 1, 0, 1, 0, 0, $0, 0, 0, 0, 1, 0, 0, $b, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
|
|
|
|
// Apply a form value preset to the form values
|
|
// idx is the ID of the preset
|
|
void apply_preset(byte idx) {
|
|
byte* preset;
|
|
if(idx==0) {
|
|
preset = preset_stdchar;
|
|
} else if(idx==1){
|
|
preset = preset_ecmchar;
|
|
} else if(idx==2){
|
|
preset = preset_stdbm;
|
|
} else if(idx==3){
|
|
preset = preset_mcbm;
|
|
} else if(idx==4){
|
|
preset = preset_hi_stdchar;
|
|
} else if(idx==5){
|
|
preset = preset_hi_ecmchar;
|
|
} else if(idx==6){
|
|
preset = preset_twoplane;
|
|
} else if(idx==7){
|
|
preset = preset_chunky;
|
|
} else if(idx==8){
|
|
preset = preset_sixsfred;
|
|
} else if(idx==9){
|
|
preset = preset_sixsfred2;
|
|
} else if(idx==10){
|
|
preset = preset_8bpppixelcell;
|
|
} else {
|
|
preset = preset_stdchar;
|
|
}
|
|
// Copy preset values into the fields
|
|
for( byte i=0; i != form_fields_cnt; i++) {
|
|
form_fields_val[i] = preset[i];
|
|
}
|
|
|
|
}
|
|
|
|
// Render form preset name in the form
|
|
// idx is the ID of the preset
|
|
void render_preset_name(byte idx) {
|
|
byte* name;
|
|
if(idx==0) {
|
|
name = "Standard Charset ";
|
|
} else if(idx==1){
|
|
name = "Extended Color Charset ";
|
|
} else if(idx==2){
|
|
name = "Standard Bitmap ";
|
|
} else if(idx==3){
|
|
name = "Multicolor Bitmap ";
|
|
} else if(idx==4){
|
|
name = "Hicolor Charset ";
|
|
} else if(idx==5){
|
|
name = "Hicolor Extended Color Charset";
|
|
} else if(idx==6){
|
|
name = "Twoplane Bitmap ";
|
|
} else if(idx==7){
|
|
name = "Chunky 8bpp ";
|
|
} else if(idx==8){
|
|
name = "Sixs Fred ";
|
|
} else if(idx==9){
|
|
name = "Sixs Fred 2 ";
|
|
} else if(idx==10){
|
|
name = "8bpp Pixel Cell ";
|
|
} else {
|
|
name = "Standard Charset ";
|
|
}
|
|
// Render it
|
|
print_str_at(name, FORM_SCREEN+40*2+10);
|
|
}
|
|
|
|
|
|
// Form fields direct addressing
|
|
const byte* form_preset = form_fields_val+0;
|
|
const byte* form_ctrl_bmm = form_fields_val+1;
|
|
const byte* form_ctrl_mcm = form_fields_val+2;
|
|
const byte* form_ctrl_ecm = form_fields_val+3;
|
|
const byte* form_ctrl_hicol = form_fields_val+4;
|
|
const byte* form_ctrl_line = form_fields_val+5;
|
|
const byte* form_ctrl_colof = form_fields_val+6;
|
|
const byte* form_ctrl_chunk = form_fields_val+7;
|
|
const byte* form_ctrl_borof = form_fields_val+8;
|
|
const byte* form_ctrl_overs = form_fields_val+9;
|
|
const byte* form_a_pattern = form_fields_val+10;
|
|
const byte* form_a_start_hi = form_fields_val+11;
|
|
const byte* form_a_start_lo = form_fields_val+12;
|
|
const byte* form_a_step_hi = form_fields_val+13;
|
|
const byte* form_a_step_lo = form_fields_val+14;
|
|
const byte* form_a_mod_hi = form_fields_val+15;
|
|
const byte* form_a_mod_lo = form_fields_val+16;
|
|
const byte* form_b_pattern = form_fields_val+17;
|
|
const byte* form_b_start_hi = form_fields_val+18;
|
|
const byte* form_b_start_lo = form_fields_val+19;
|
|
const byte* form_b_step_hi = form_fields_val+20;
|
|
const byte* form_b_step_lo = form_fields_val+21;
|
|
const byte* form_b_mod_hi = form_fields_val+22;
|
|
const byte* form_b_mod_lo = form_fields_val+23;
|
|
const byte* form_vic_screen = form_fields_val+24;
|
|
const byte* form_vic_gfx = form_fields_val+25;
|
|
const byte* form_vic_cols = form_fields_val+26;
|
|
const byte* form_dtv_palet = form_fields_val+27;
|
|
const byte* form_vic_bg0_hi = form_fields_val+28;
|
|
const byte* form_vic_bg0_lo = form_fields_val+29;
|
|
const byte* form_vic_bg1_hi = form_fields_val+30;
|
|
const byte* form_vic_bg1_lo = form_fields_val+31;
|
|
const byte* form_vic_bg2_hi = form_fields_val+32;
|
|
const byte* form_vic_bg2_lo = form_fields_val+33;
|
|
const byte* form_vic_bg3_hi = form_fields_val+34;
|
|
const byte* form_vic_bg3_lo = form_fields_val+35;
|
|
|
|
// Change graphics mode to show the selected graphics mode
|
|
void gfx_mode() {
|
|
// Show the GFX configuration
|
|
// DTV Graphics Mode
|
|
byte dtv_control = 0;
|
|
if(*form_ctrl_line!=0) {
|
|
dtv_control = dtv_control | DTV_LINEAR;
|
|
}
|
|
if(*form_ctrl_borof!=0) {
|
|
dtv_control = dtv_control | DTV_BORDER_OFF;
|
|
}
|
|
if(*form_ctrl_hicol!=0) {
|
|
dtv_control = dtv_control | DTV_HIGHCOLOR;
|
|
}
|
|
if(*form_ctrl_overs!=0) {
|
|
dtv_control = dtv_control | DTV_OVERSCAN;
|
|
}
|
|
if(*form_ctrl_colof!=0) {
|
|
dtv_control = dtv_control | DTV_COLORRAM_OFF;
|
|
}
|
|
if(*form_ctrl_chunk!=0) {
|
|
dtv_control = dtv_control | DTV_CHUNKY;
|
|
}
|
|
*DTV_CONTROL = dtv_control;
|
|
|
|
// VIC Graphics Mode
|
|
byte vic_control = VIC_DEN | VIC_RSEL | 3;
|
|
if(*form_ctrl_ecm!=0) {
|
|
vic_control = vic_control | VIC_ECM;
|
|
}
|
|
if(*form_ctrl_bmm!=0) {
|
|
vic_control = vic_control | VIC_BMM;
|
|
}
|
|
*VIC_CONTROL = vic_control;
|
|
byte vic_control2 = VIC_CSEL;
|
|
if(*form_ctrl_mcm!=0) {
|
|
vic_control2 = vic_control2 | VIC_MCM;
|
|
}
|
|
*VIC_CONTROL2 = vic_control2;
|
|
|
|
// Linear Graphics Plane A Counter
|
|
byte plane_a_offs = *form_a_start_hi<<4|*form_a_start_lo;
|
|
dword plane_a = get_plane(*form_a_pattern) + plane_a_offs;
|
|
*DTV_PLANEA_START_LO = < < plane_a;
|
|
*DTV_PLANEA_START_MI = > < plane_a;
|
|
*DTV_PLANEA_START_HI = < > plane_a;
|
|
*DTV_PLANEA_STEP = *form_a_step_hi<<4|*form_a_step_lo;
|
|
*DTV_PLANEA_MODULO_LO = *form_a_mod_hi<<4|*form_a_mod_lo;
|
|
*DTV_PLANEA_MODULO_HI = 0;
|
|
|
|
// Linear Graphics Plane B Counter
|
|
byte plane_b_offs = *form_b_start_hi<<4|*form_b_start_lo;
|
|
dword plane_b = get_plane(*form_b_pattern) + plane_b_offs;
|
|
*DTV_PLANEB_START_LO = < < plane_b;
|
|
*DTV_PLANEB_START_MI = > < plane_b;
|
|
*DTV_PLANEB_START_HI = < > plane_b;
|
|
*DTV_PLANEB_STEP = *form_b_step_hi<<4|*form_b_step_lo;
|
|
*DTV_PLANEB_MODULO_LO = *form_b_mod_hi<<4|*form_b_mod_lo;
|
|
*DTV_PLANEB_MODULO_HI = 0;
|
|
|
|
// VIC Graphics Bank
|
|
*CIA2_PORT_A_DDR = %00000011; // Set VIC Bank bits to output - all others to input
|
|
*CIA2_PORT_A = %00000011 ^ (byte)((word)VIC_SCREEN0/$4000); // Set VIC Bank
|
|
// VIC memory
|
|
*VIC_MEMORY = (byte)(((word)get_vic_screen(*form_vic_screen)&$3fff)>>6) | ((>((word)get_vic_charset(*form_vic_gfx)&$3fff))>>2);
|
|
|
|
// VIC Colors
|
|
byte* vic_colors = get_vic_screen(*form_vic_cols);
|
|
byte* col=COLS;
|
|
for(byte cy: 0..24 ) {
|
|
for(byte cx: 0..39) {
|
|
*col++ = *vic_colors++;
|
|
}
|
|
}
|
|
|
|
// Background colors
|
|
*BORDERCOL = 0;
|
|
*BGCOL1 = *form_vic_bg0_hi<<4|*form_vic_bg0_lo;
|
|
*BGCOL2 = *form_vic_bg1_hi<<4|*form_vic_bg1_lo;
|
|
*BGCOL3 = *form_vic_bg2_hi<<4|*form_vic_bg2_lo;
|
|
*BGCOL4 = *form_vic_bg3_hi<<4|*form_vic_bg3_lo;
|
|
|
|
// DTV Palette
|
|
if(*form_dtv_palet==0) {
|
|
// DTV Palette - default
|
|
for(byte i : 0..$f) {
|
|
DTV_PALETTE[i] = DTV_PALETTE_DEFAULT[i];
|
|
}
|
|
} else {
|
|
// DTV Palette - Grey Tones
|
|
for(byte j : 0..$f) {
|
|
DTV_PALETTE[j] = j;
|
|
}
|
|
}
|
|
|
|
// Wait for the user to press space
|
|
while(true) {
|
|
while(*RASTER!=$ff) {}
|
|
keyboard_event_scan();
|
|
byte keyboard_event = keyboard_event_get();
|
|
if(keyboard_event==KEY_SPACE) {
|
|
// If space pressed - change to form mode 4
|
|
return;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// Initialize the different graphics in the memory
|
|
void gfx_init() {
|
|
gfx_init_screen0();
|
|
gfx_init_screen1();
|
|
gfx_init_screen2();
|
|
gfx_init_screen3();
|
|
gfx_init_screen4();
|
|
gfx_init_charset();
|
|
gfx_init_vic_bitmap();
|
|
gfx_init_plane_8bppchunky();
|
|
gfx_init_plane_charset8();
|
|
gfx_init_plane_horisontal();
|
|
gfx_init_plane_vertical();
|
|
gfx_init_plane_horisontal2();
|
|
gfx_init_plane_vertical2();
|
|
gfx_init_plane_blank();
|
|
gfx_init_plane_full();
|
|
}
|
|
|
|
void gfx_init_charset() {
|
|
*PROCPORT = $32;
|
|
byte* chargen = CHARGEN;
|
|
byte* charset = VIC_CHARSET_ROM;
|
|
for(byte c: 0..$ff) {
|
|
for( byte l: 0..7) {
|
|
*charset++ = *chargen++;
|
|
}
|
|
}
|
|
*PROCPORT = $37;
|
|
}
|
|
|
|
// Initialize VIC screen 0 ( value is %yyyyxxxx where yyyy is ypos and xxxx is xpos)
|
|
void gfx_init_screen0() {
|
|
byte* ch=VIC_SCREEN0;
|
|
for(byte cy: 0..24 ) {
|
|
for(byte cx: 0..39) {
|
|
*ch++ = (cy&$f)<<4|(cx&$f);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Initialize VIC screen 1 ( value is %0000cccc where cccc is (x+y mod $f))
|
|
void gfx_init_screen1() {
|
|
byte* ch=VIC_SCREEN1;
|
|
for(byte cy: 0..24 ) {
|
|
for(byte cx: 0..39) {
|
|
*ch++ = (cx+cy)&$f;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Initialize VIC screen 2 ( value is %ccccrrrr where cccc is (x+y mod $f) and rrrr is %1111-%cccc)
|
|
void gfx_init_screen2() {
|
|
byte* ch=VIC_SCREEN2;
|
|
for(byte cy: 0..24 ) {
|
|
for(byte cx: 0..39) {
|
|
byte col = (cx+cy)&$f;
|
|
byte col2 = ($f-col);
|
|
*ch++ = col<<4 | col2;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Initialize VIC screen 3 ( value is %00xx00yy where xx is xpos and yy is ypos
|
|
void gfx_init_screen3() {
|
|
byte* ch=VIC_SCREEN3;
|
|
for(byte cy: 0..24 ) {
|
|
for(byte cx: 0..39) {
|
|
*ch++ = (cx&3)<<4|(cy&3);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Initialize VIC screen 4 - all chars are 00
|
|
void gfx_init_screen4() {
|
|
byte* ch=VIC_SCREEN4;
|
|
for(byte cy: 0..24 ) {
|
|
for(byte cx: 0..39) {
|
|
*ch++ = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Initialize VIC bitmap
|
|
void gfx_init_vic_bitmap() {
|
|
// Draw some lines on the bitmap
|
|
bitmap_init(VIC_BITMAP);
|
|
bitmap_clear();
|
|
byte[] lines_x = { $00, $ff, $ff, $00, $00, $80, $ff, $80, $00, $80 };
|
|
byte[] lines_y = { $00, $00, $c7, $c7, $00, $00, $64, $c7, $64, $00 };
|
|
byte lines_cnt = 9;
|
|
for(byte l=0; l<lines_cnt;l++) {
|
|
bitmap_line(lines_x[l], lines_x[l+1], lines_y[l], lines_y[l+1]);
|
|
}
|
|
}
|
|
|
|
// Initialize 8BPP Chunky Bitmap (contains 8bpp pixels)
|
|
void gfx_init_plane_8bppchunky() {
|
|
// 320x200 8bpp pixels for Plane
|
|
byte gfxbCpuBank = (byte)(PLANE_8BPP_CHUNKY/$4000);
|
|
dtvSetCpuBankSegment1(gfxbCpuBank++);
|
|
byte* gfxb = $4000;
|
|
for(byte y : 0..199) {
|
|
for (word x : 0..319) {
|
|
// If we have crossed to $8000 increase the CPU BANK segment and reset to $4000
|
|
if(gfxb==$8000) {
|
|
dtvSetCpuBankSegment1(gfxbCpuBank++);
|
|
gfxb = $4000;
|
|
}
|
|
byte c = (byte)(x+y);
|
|
*gfxb++ = c;
|
|
}
|
|
}
|
|
// Reset CPU BANK segment to $4000
|
|
dtvSetCpuBankSegment1((byte)($4000/$4000));
|
|
}
|
|
|
|
// Initialize Plane with Horizontal Stripes
|
|
void gfx_init_plane_horisontal() {
|
|
byte gfxbCpuBank = (byte)(PLANE_HORISONTAL/$4000);
|
|
dtvSetCpuBankSegment1(gfxbCpuBank++);
|
|
byte* gfxa = $4000 + (PLANE_HORISONTAL & $3fff);
|
|
for(byte ay : 0..199) {
|
|
for (byte ax : 0..39) {
|
|
if((ay&4)==0) {
|
|
*gfxa++ = %00000000;
|
|
} else {
|
|
*gfxa++ = %11111111;
|
|
}
|
|
}
|
|
}
|
|
// Reset CPU BANK segment to $4000
|
|
dtvSetCpuBankSegment1((byte)($4000/$4000));
|
|
}
|
|
|
|
// Initialize Plane with Horizontal Stripes every 2 pixels
|
|
void gfx_init_plane_horisontal2() {
|
|
byte gfxbCpuBank = (byte)(PLANE_HORISONTAL2/$4000);
|
|
dtvSetCpuBankSegment1(gfxbCpuBank++);
|
|
byte* gfxa = $4000 + (PLANE_HORISONTAL2 & $3fff);
|
|
byte[] row_bitmask = { %00000000, %01010101, %10101010, %11111111 };
|
|
for(byte ay : 0..199) {
|
|
for (byte ax : 0..39) {
|
|
byte row = (ay>>1) & 3;
|
|
*gfxa++ = row_bitmask[row];
|
|
}
|
|
}
|
|
// Reset CPU BANK segment to $4000
|
|
dtvSetCpuBankSegment1((byte)($4000/$4000));
|
|
}
|
|
|
|
// Initialize Plane with Vertical Stripes
|
|
void gfx_init_plane_vertical() {
|
|
byte gfxbCpuBank = (byte)(PLANE_VERTICAL/$4000);
|
|
dtvSetCpuBankSegment1(gfxbCpuBank++);
|
|
byte* gfxb = $4000 + (PLANE_VERTICAL & $3fff);
|
|
for(byte by : 0..199) {
|
|
for ( byte bx : 0..39) {
|
|
*gfxb++ = %00001111;
|
|
}
|
|
}
|
|
// Reset CPU BANK segment to $4000
|
|
dtvSetCpuBankSegment1((byte)($4000/$4000));
|
|
}
|
|
|
|
// Initialize Plane with 8bpp charset
|
|
void gfx_init_plane_charset8() {
|
|
// 8bpp cells for Plane B (charset) - ROM charset with 256 colors
|
|
byte gfxbCpuBank = (byte)(PLANE_CHARSET8/$4000);
|
|
dtvSetCpuBankSegment1(gfxbCpuBank++);
|
|
byte* gfxa = $4000 + (PLANE_CHARSET8 & $3fff);
|
|
byte* chargen = CHARGEN;
|
|
*PROCPORT = PROCPORT_RAM_CHARROM;
|
|
byte col = 0;
|
|
for(byte ch : $00..$ff) {
|
|
for ( byte cr : 0..7) {
|
|
byte bits = *chargen++;
|
|
for ( byte cp : 0..7) {
|
|
byte c = 0;
|
|
if((bits & $80) != 0) {
|
|
c = col;
|
|
}
|
|
*gfxa++ = c;
|
|
bits = bits<<1;
|
|
col++;
|
|
}
|
|
}
|
|
}
|
|
*PROCPORT = PROCPORT_RAM_IO;
|
|
// Reset CPU BANK segment to $4000
|
|
dtvSetCpuBankSegment1((byte)($4000/$4000));
|
|
}
|
|
|
|
// Initialize Plane with Vertical Stripes every 2 pixels
|
|
void gfx_init_plane_vertical2() {
|
|
gfx_init_plane_fill(PLANE_VERTICAL2, %00011011);
|
|
}
|
|
|
|
// Initialize Plane with blank pixels
|
|
void gfx_init_plane_blank() {
|
|
gfx_init_plane_fill(PLANE_BLANK, 0);
|
|
}
|
|
|
|
// Initialize Plane with all pixels
|
|
void gfx_init_plane_full() {
|
|
gfx_init_plane_fill(PLANE_FULL, $ff);
|
|
}
|
|
|
|
// Initialize 320*200 1bpp pixel ($2000) plane with identical bytes
|
|
void gfx_init_plane_fill(dword plane_addr, byte fill) {
|
|
byte gfxbCpuBank = < >(plane_addr<<2);
|
|
dtvSetCpuBankSegment1(gfxbCpuBank++);
|
|
byte* gfxb = $4000 + (<plane_addr & $3fff);
|
|
for(byte by : 0..199) {
|
|
for ( byte bx : 0..39) {
|
|
*gfxb++ = fill;
|
|
}
|
|
}
|
|
// Reset CPU BANK segment to $4000
|
|
dtvSetCpuBankSegment1((byte)($4000/$4000));
|
|
}
|
|
|
|
// Show the form - and let the user change values
|
|
void form_mode() {
|
|
// Show the form
|
|
|
|
// Form Colors
|
|
print_set_screen(COLS);
|
|
print_cls();
|
|
print_str_lines(FORM_COLS);
|
|
// Form Text
|
|
print_set_screen(FORM_SCREEN);
|
|
print_cls();
|
|
print_str_lines(FORM_TEXT);
|
|
// Form Fields
|
|
form_set_screen(FORM_SCREEN);
|
|
form_render_values();
|
|
render_preset_name(*form_preset);
|
|
|
|
// DTV Graphics Bank
|
|
*DTV_GRAPHICS_VIC_BANK = (byte)((dword)FORM_CHARSET/$10000);
|
|
// DTV Color Bank
|
|
*DTV_COLOR_BANK_LO = <((word)(DTV_COLOR_BANK_DEFAULT/$400));
|
|
*DTV_COLOR_BANK_HI = >((word)(DTV_COLOR_BANK_DEFAULT/$400));
|
|
// VIC Graphics Bank
|
|
*CIA2_PORT_A_DDR = %00000011; // Set VIC Bank bits to output - all others to input
|
|
*CIA2_PORT_A = %00000011 ^ (byte)((word)FORM_CHARSET/$4000); // Set VIC Bank
|
|
// DTV Graphics Mode
|
|
*DTV_CONTROL = 0;
|
|
// VIC Graphics Mode
|
|
*VIC_CONTROL = VIC_DEN|VIC_RSEL|3;
|
|
*VIC_CONTROL2 = VIC_CSEL;
|
|
// VIC Memory Pointers
|
|
*VIC_MEMORY = (byte)((((word)FORM_SCREEN&$3fff)/$40)|(((word)FORM_CHARSET&$3fff)/$400));
|
|
// DTV Plane A to FORM_SCREEN also
|
|
*DTV_PLANEA_START_LO = < FORM_SCREEN;
|
|
*DTV_PLANEA_START_MI = > FORM_SCREEN;
|
|
*DTV_PLANEA_START_HI = 0;
|
|
// DTV Palette - default
|
|
for(byte i : 0..$f) {
|
|
DTV_PALETTE[i] = DTV_PALETTE_DEFAULT[i];
|
|
}
|
|
// Screen colors
|
|
*BGCOL = 0;
|
|
*BORDERCOL = 0;
|
|
|
|
byte preset_current = *form_preset;
|
|
|
|
// Let the user change values in the form
|
|
while(true) {
|
|
while(*RASTER!=$ff) {}
|
|
if(form_control()!=0) {
|
|
// Space pressed - change to GFX mode
|
|
return;
|
|
}
|
|
if(preset_current!=*form_preset) {
|
|
// Preset changed - update field values and render
|
|
apply_preset(*form_preset);
|
|
preset_current = *form_preset;
|
|
form_render_values();
|
|
render_preset_name(*form_preset);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Table with addresses of the y-lines of the form. The first line contains the address of the form screen.
|
|
byte[25] form_line_lo;
|
|
byte[25] form_line_hi;
|
|
// Current selected field in the form
|
|
byte form_field_idx = 0;
|
|
|
|
// The number of frames to use for a full blink cycle
|
|
const signed byte FORM_CURSOR_BLINK = 40;
|
|
// Counts down to blink for form cursor (it is inversed in the lower half)
|
|
signed byte form_cursor_count = FORM_CURSOR_BLINK/2;
|
|
|
|
// Set the screen to use for the form.
|
|
// screen is the start address of the screen to use
|
|
void form_set_screen(byte* screen) {
|
|
// Calculate the field line table
|
|
byte* line = screen;
|
|
for(byte y: 0..24) {
|
|
form_line_lo[y] = <line;
|
|
form_line_hi[y] = >line;
|
|
line = line + 40;
|
|
}
|
|
}
|
|
|
|
// Get the screen address of a form field
|
|
// field_idx is the index of the field to get the screen address for
|
|
byte* form_field_ptr(byte field_idx) {
|
|
byte y = form_fields_y[field_idx];
|
|
byte* line = (byte*) { form_line_hi[y], form_line_lo[y] };
|
|
byte x = form_fields_x[field_idx];
|
|
byte* field = line+x;
|
|
return field;
|
|
}
|
|
|
|
// Render all form values from the form_fields_val array
|
|
void form_render_values() {
|
|
for( byte idx=0; idx<form_fields_cnt; idx++) {
|
|
byte* field = form_field_ptr(idx);
|
|
*field = print_hextab[form_fields_val[idx]];
|
|
}
|
|
}
|
|
|
|
// Reads keyboard and allows the user to navigate and change the fields of the form
|
|
// Returns 0 if space is not pressed, non-0 if space is pressed
|
|
byte form_control() {
|
|
byte* field = form_field_ptr(form_field_idx);
|
|
|
|
// Blinking cursor
|
|
if(--form_cursor_count < 0) {
|
|
form_cursor_count = FORM_CURSOR_BLINK;
|
|
}
|
|
if(form_cursor_count<FORM_CURSOR_BLINK/2) {
|
|
*field = *field | $80;
|
|
} else {
|
|
*field = *field & $7f;
|
|
}
|
|
|
|
// Scan the keyboard
|
|
keyboard_event_scan();
|
|
byte key_event = keyboard_event_get();
|
|
|
|
// Navigation using cursor up/down
|
|
if(key_event==KEY_CRSR_DOWN) {
|
|
// Unblink the cursor
|
|
*field = *field & $7f;
|
|
if((keyboard_modifiers&KEY_MODIFIER_SHIFT)==0) {
|
|
// Move to next field
|
|
if(++form_field_idx==form_fields_cnt) {
|
|
form_field_idx = 0;
|
|
}
|
|
} else {
|
|
// Move to previous field
|
|
if(--form_field_idx==$ff) {
|
|
form_field_idx = form_fields_cnt-1;
|
|
}
|
|
}
|
|
// Always blink cursor in new field
|
|
form_cursor_count = FORM_CURSOR_BLINK/2;
|
|
// Return to refresh
|
|
return 0;
|
|
}
|
|
|
|
// Change value with cursor left/right
|
|
if(key_event==KEY_CRSR_RIGHT) {
|
|
if((keyboard_modifiers&KEY_MODIFIER_SHIFT)==0) {
|
|
// Increase value
|
|
if(++form_fields_val[form_field_idx]>form_fields_max[form_field_idx]) {
|
|
form_fields_val[form_field_idx] = 0;
|
|
}
|
|
} else {
|
|
// Decrease value
|
|
if(--form_fields_val[form_field_idx]==$ff) {
|
|
form_fields_val[form_field_idx] = form_fields_max[form_field_idx];
|
|
}
|
|
}
|
|
// Render field value
|
|
*field = print_hextab[form_fields_val[form_field_idx]];
|
|
return 0;
|
|
}
|
|
|
|
// Check for space press
|
|
if(key_event==KEY_SPACE) {
|
|
return $ff;
|
|
}
|
|
return 0;
|
|
|
|
}
|