-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathbackground.ice
207 lines (191 loc) · 9.01 KB
/
background.ice
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
// STRUCTURE OF A COPPER PROGRAM ENTRY
bitfield CU{
uint3 command,
uint3 flag,
uint1 valueflag,
uint10 value,
uint4 mode,
uint6 colour_alt,
uint6 colour
}
algorithm background_writer(
input uint10 pix_x,
input uint10 pix_y,
input uint1 pix_active,
input uint1 pix_vblank,
input uint6 backgroundcolour,
input uint6 backgroundcolour_alt,
input uint4 backgroundcolour_mode,
input uint2 background_update,
input uint1 copper_status,
input uint1 copper_program,
input uint6 copper_address,
input uint3 copper_command,
input uint3 copper_condition,
input uint11 copper_coordinate,
input uint10 copper_cpu_input,
input uint4 copper_mode,
input uint6 copper_alt,
input uint6 copper_colour,
output uint6 BACKGROUNDcolour,
output uint6 BACKGROUNDalt,
output uint4 BACKGROUNDmode
) <autorun,reginputs> {
// BACKGROUND CO-PROCESSOR PROGRAM STORAGE
// { 3 bit command, 3 bit mask, { 1 bit for cpuinput flag, 10 bit coordinate }, 4 bit mode, 6 bit colour 2, 6 bit colour 1 }
simple_dualport_bram uint33 copper[ 64 ] = uninitialised;
uint1 copper_execute = uninitialised; uint1 copper_branch = uninitialised;
uint6 PC = 0; uint6 PCplus1 <:: PC + 1;
uint10 copper_variable = 0;
// COPPER PROGRAM ENTRY
uint10 value <:: CU(copper.rdata0).valueflag ? copper_cpu_input : CU(copper.rdata0).value;
uint10 negvalue <:: -value;
// COPPER FLAGS
copper.addr0 := PC; copper.wenable1 := 1; copper_execute := 0; copper_branch := 0;
always_after {
switch( background_update ) {
case 2b00: {
// UPDATE THE BACKGROUND GENERATOR FROM THE COPPER
if( copper_status ) {
switch( CU(copper.rdata0).command ) {
case 3b000: {
// JUMP ON CONDITION
switch( CU(copper.rdata0).flag ) {
default: { copper_branch = 1; }
case 3b001: { copper_branch = ( pix_vblank == value[0,1] ); }
case 3b010: { copper_branch = ( pix_active == value[0,1] ); }
case 3b011: { copper_branch = ( pix_y < value ); }
case 3b100: { copper_branch = ( pix_x < value ); }
case 3b101: { copper_branch = ( copper_variable < value ); }
}
PC = copper_branch ? CU(copper.rdata0).colour : PCplus1;
}
default: {
switch( CU(copper.rdata0).command ) {
case 3b001: { copper_execute = pix_vblank; }
case 3b010: { copper_execute = ~pix_active; }
case 3b011: { copper_execute = ( pix_y == value ); }
case 3b100: { copper_execute = ( pix_x == value ); }
case 3b101: { copper_execute = ( copper_variable == ( value[0,1] ? pix_x : pix_y ) ); }
case 3b110: {
copper_variable = CU(copper.rdata0).flag[0,1] ? value : copper_variable + ( CU(copper.rdata0).flag[2,1] ? negvalue : value );
copper_branch = 1;
}
default: {
if( CU(copper.rdata0).flag[0,1] ) { BACKGROUNDcolour = copper_variable; }
if( CU(copper.rdata0).flag[1,1] ) { BACKGROUNDalt = copper_variable; }
if( CU(copper.rdata0).flag[2,1] ) { BACKGROUNDmode = copper_variable;}
copper_branch = 1;
}
}
if( copper_execute ) {
if( CU(copper.rdata0).flag[0,1] ) { BACKGROUNDcolour = CU(copper.rdata0).colour; }
if( CU(copper.rdata0).flag[1,1] ) { BACKGROUNDalt = CU(copper.rdata0).colour_alt; }
if( CU(copper.rdata0).flag[2,1] ) { BACKGROUNDmode = CU(copper.rdata0).mode; }
copper_branch = 1;
}
if( copper_branch ) { PC = PCplus1; }
}
}
} else{
// CHANGE A PROGRAM LINE IN THE COPPER MEMORY
if( copper_program ) {
copper.addr1 = copper_address;
copper.wdata1 = { copper_command[0,3], copper_condition[0,3], copper_coordinate[0,11], copper_mode[0,4], copper_alt[0,6], copper_colour[0,6] };
}
PC = 0;
}
}
// UPDATE THE BACKGROUND FROM RISC-V
case 2b01: { BACKGROUNDcolour = backgroundcolour; }
case 2b10: { BACKGROUNDalt = backgroundcolour_alt; }
case 2b11: { BACKGROUNDmode = backgroundcolour_mode; }
}
}
}
algorithm rainbow(
input uint3 y,
output uint6 colour
) <autorun> {
always_after {
switch( y ) {
case 3b000: { colour = 6b100000; }
case 3b001: { colour = 6b110000; }
case 3b010: { colour = 6b111000; }
case 3b011: { colour = 6b111100; }
case 3b100: { colour = 6b001100; }
case 3b101: { colour = 6b000011; }
case 3b110: { colour = 6b010010; }
case 3b111: { colour = 6b011011; }
}
}
}
algorithm background_display(
input uint10 pix_x,
input uint10 pix_y,
input uint1 pix_active,
input uint1 pix_vblank,
output! uint6 pixel,
input uint2 staticGenerator,
input uint6 b_colour,
input uint6 b_alt,
input uint4 b_mode
) <autorun,reginputs> {
// TRUE FOR COLOUR, FALSE FOR ALT
pattern PATTERN( pix_x <: pix_x, pix_y <: pix_y, b_mode <: b_mode );
rainbow RAINBOW( y <: pix_y[6,3] );
always_after {
// RENDER - SELECT ACTUAL COLOUR
switch( PATTERN.condition ) {
case 0: { pixel = b_alt; } // EVERYTHING ELSE
case 1: { pixel = b_colour; }
case 2: { pixel = RAINBOW.colour; } // RAINBOW
case 3: { pixel = {3{staticGenerator}}; } // STATIC
}
}
}
algorithm starfield(
input uint10 pix_x,
input uint10 pix_y,
output uint1 star
) <autorun> {
// Variables for SNOW (from @sylefeb)
int10 dotpos = 0; int2 speed = 0; int2 inv_speed = 0;
int12 rand_x = 0; int12 new_rand_x <:: rand_x * 31421 + 6927; int32 frame = 0;
always_before {
rand_x = ( ~|pix_x ) ? 1 : new_rand_x;
speed = rand_x[10,2];
dotpos = ( frame >> speed ) + rand_x;
star = ( pix_y == dotpos );
}
always_after {
// Increment frame number for the snow/star field
frame = frame + ( ( pix_x == 639 ) & ( pix_y == 479 ) );
}
}
algorithm pattern(
input uint10 pix_x,
input uint10 pix_y,
input uint4 b_mode,
output! uint2 condition
) <autorun> {
uint1 tophalf <: ( pix_y < 240 ); uint1 lefthalf <: ( pix_x < 320 ); uint4 checkmode <: b_mode - 7;
starfield STARS( pix_x <: pix_x, pix_y <: pix_y );
always {
// SELECT COLOUR OR ALT
switch( b_mode ) {
case 0: { condition = 1; } // SOLID
case 1: { condition = tophalf; } // 50:50 HORIZONTAL SPLIT
case 2: { condition = ( lefthalf ); } // 50:50 VERTICAL SPLIT
case 3: { condition = ( lefthalf ^ tophalf ); } // QUARTERS
case 5: { condition = STARS.star; } // SNOW (from @sylefeb)
case 11: { condition = ( pix_x[0,1] | pix_y[0,1] ); } // CROSSHATCH
case 12: { condition = ( pix_x[0,2] == pix_y[0,2] ); } // LSLOPE
case 13: { condition = ( pix_x[0,2] == ~pix_y[0,2] ); } // RSLOPE
case 14: { condition = pix_x[0,1]; } // VSTRIPES
case 15: { condition = pix_y[0,1]; } // HSTRIPES
case 4: { condition = 2; } case 6: { condition = 3; } // STATIC AND RAINBOW (placeholder, done in main)
default: { condition = ( pix_x[checkmode,1] ^ pix_y[checkmode,1] ); } // CHECKERBOARDS (7,8,9,10)
}
}
}