Merge branch 'bios' into 'master'

Link bootloader with bios to get access to symbols

See merge request bslathi19/super6502!18
This commit is contained in:
Byron Lathi
2023-08-24 04:15:04 +00:00
69 changed files with 1311 additions and 2362 deletions

View File

@@ -19,6 +19,6 @@ assign o_divider_cs = i_addr >= 16'hefe8 && i_addr <= 16'hefef;
assign o_uart_cs = i_addr >= 16'hefe6 && i_addr <= 16'hefe7;
assign o_spi_cs = i_addr >= 16'hefd8 && i_addr <= 16'hefdb;
assign o_leds_cs = i_addr == 16'hefff;
assign o_sdram_cs = i_addr < 16'h8000;
assign o_sdram_cs = i_addr < 16'he000;
endmodule

View File

@@ -3,7 +3,7 @@
{
"name": "la0",
"type": "la",
"uuid": "fc5ad0b7db9846e2b64719110e7975d8",
"uuid": "376f85320e7b4d47a35d93dea8b58f08",
"trigin_en": false,
"trigout_en": false,
"auto_inserted": true,
@@ -21,48 +21,43 @@
"width": 1,
"probe_type": 1
},
{
"name": "cpu_sync",
"width": 1,
"probe_type": 1
},
{
"name": "cpu_resb",
"width": 1,
"probe_type": 1
},
{
"name": "cpu_addr",
"width": 16,
"probe_type": 1
},
{
"name": "cpu_phi2",
"name": "cpu_sync",
"width": 1,
"probe_type": 1
},
{
"name": "spi_clk",
"name": "cpu_rdy",
"width": 1,
"probe_type": 1
},
{
"name": "spi_mosi",
"name": "spi_controller/r_input_data",
"width": 8,
"probe_type": 1
},
{
"name": "spi_controller/r_output_data",
"width": 8,
"probe_type": 1
},
{
"name": "spi_controller/o_spi_clk",
"width": 1,
"probe_type": 1
},
{
"name": "sd_cs",
"name": "spi_controller/o_spi_mosi",
"width": 1,
"probe_type": 1
},
{
"name": "spi_miso",
"width": 1,
"probe_type": 1
},
{
"name": "spi_controller/active",
"name": "spi_controller/i_spi_miso",
"width": 1,
"probe_type": 1
}
@@ -192,7 +187,7 @@
},
{
"name": "la0_clk",
"net": "clk_50",
"net": "clk_2",
"path": []
},
{
@@ -241,123 +236,224 @@
"path": []
},
{
"name": "la0_probe2",
"net": "cpu_sync",
"path": []
},
{
"name": "la0_probe3",
"net": "cpu_resb",
"path": []
},
{
"name": "la0_probe4[0]",
"name": "la0_probe2[0]",
"net": "cpu_addr[0]",
"path": []
},
{
"name": "la0_probe4[1]",
"name": "la0_probe2[1]",
"net": "cpu_addr[1]",
"path": []
},
{
"name": "la0_probe4[2]",
"name": "la0_probe2[2]",
"net": "cpu_addr[2]",
"path": []
},
{
"name": "la0_probe4[3]",
"name": "la0_probe2[3]",
"net": "cpu_addr[3]",
"path": []
},
{
"name": "la0_probe4[4]",
"name": "la0_probe2[4]",
"net": "cpu_addr[4]",
"path": []
},
{
"name": "la0_probe4[5]",
"name": "la0_probe2[5]",
"net": "cpu_addr[5]",
"path": []
},
{
"name": "la0_probe4[6]",
"name": "la0_probe2[6]",
"net": "cpu_addr[6]",
"path": []
},
{
"name": "la0_probe4[7]",
"name": "la0_probe2[7]",
"net": "cpu_addr[7]",
"path": []
},
{
"name": "la0_probe4[8]",
"name": "la0_probe2[8]",
"net": "cpu_addr[8]",
"path": []
},
{
"name": "la0_probe4[9]",
"name": "la0_probe2[9]",
"net": "cpu_addr[9]",
"path": []
},
{
"name": "la0_probe4[10]",
"name": "la0_probe2[10]",
"net": "cpu_addr[10]",
"path": []
},
{
"name": "la0_probe4[11]",
"name": "la0_probe2[11]",
"net": "cpu_addr[11]",
"path": []
},
{
"name": "la0_probe4[12]",
"name": "la0_probe2[12]",
"net": "cpu_addr[12]",
"path": []
},
{
"name": "la0_probe4[13]",
"name": "la0_probe2[13]",
"net": "cpu_addr[13]",
"path": []
},
{
"name": "la0_probe4[14]",
"name": "la0_probe2[14]",
"net": "cpu_addr[14]",
"path": []
},
{
"name": "la0_probe4[15]",
"name": "la0_probe2[15]",
"net": "cpu_addr[15]",
"path": []
},
{
"name": "la0_probe5",
"net": "cpu_phi2",
"name": "la0_probe3",
"net": "cpu_sync",
"path": []
},
{
"name": "la0_probe6",
"net": "spi_clk",
"name": "la0_probe4",
"net": "cpu_rdy",
"path": []
},
{
"name": "la0_probe5[0]",
"net": "r_input_data[0]",
"path": [
"spi_controller"
]
},
{
"name": "la0_probe5[1]",
"net": "r_input_data[1]",
"path": [
"spi_controller"
]
},
{
"name": "la0_probe5[2]",
"net": "r_input_data[2]",
"path": [
"spi_controller"
]
},
{
"name": "la0_probe5[3]",
"net": "r_input_data[3]",
"path": [
"spi_controller"
]
},
{
"name": "la0_probe5[4]",
"net": "r_input_data[4]",
"path": [
"spi_controller"
]
},
{
"name": "la0_probe5[5]",
"net": "r_input_data[5]",
"path": [
"spi_controller"
]
},
{
"name": "la0_probe5[6]",
"net": "r_input_data[6]",
"path": [
"spi_controller"
]
},
{
"name": "la0_probe5[7]",
"net": "r_input_data[7]",
"path": [
"spi_controller"
]
},
{
"name": "la0_probe6[0]",
"net": "r_output_data[0]",
"path": [
"spi_controller"
]
},
{
"name": "la0_probe6[1]",
"net": "r_output_data[1]",
"path": [
"spi_controller"
]
},
{
"name": "la0_probe6[2]",
"net": "r_output_data[2]",
"path": [
"spi_controller"
]
},
{
"name": "la0_probe6[3]",
"net": "r_output_data[3]",
"path": [
"spi_controller"
]
},
{
"name": "la0_probe6[4]",
"net": "r_output_data[4]",
"path": [
"spi_controller"
]
},
{
"name": "la0_probe6[5]",
"net": "r_output_data[5]",
"path": [
"spi_controller"
]
},
{
"name": "la0_probe6[6]",
"net": "r_output_data[6]",
"path": [
"spi_controller"
]
},
{
"name": "la0_probe6[7]",
"net": "r_output_data[7]",
"path": [
"spi_controller"
]
},
{
"name": "la0_probe7",
"net": "spi_mosi",
"path": []
"net": "o_spi_clk",
"path": [
"spi_controller"
]
},
{
"name": "la0_probe8",
"net": "sd_cs",
"path": []
"net": "o_spi_mosi",
"path": [
"spi_controller"
]
},
{
"name": "la0_probe9",
"net": "spi_miso",
"path": []
},
{
"name": "la0_probe10",
"net": "active",
"net": "i_spi_miso",
"path": [
"spi_controller"
]
@@ -380,7 +476,7 @@
{
"name": "cpu_data_in",
"width": 8,
"clk_domain": "clk_50",
"clk_domain": "clk_2",
"selected_probe_type": "DATA AND TRIGGER",
"child": [],
"path": [],
@@ -390,23 +486,7 @@
{
"name": "cpu_rwb",
"width": 1,
"clk_domain": "clk_50",
"selected_probe_type": "DATA AND TRIGGER",
"child": [],
"path": []
},
{
"name": "cpu_sync",
"width": 1,
"clk_domain": "clk_50",
"selected_probe_type": "DATA AND TRIGGER",
"child": [],
"path": []
},
{
"name": "cpu_resb",
"width": 1,
"clk_domain": "clk_50",
"clk_domain": "clk_2",
"selected_probe_type": "DATA AND TRIGGER",
"child": [],
"path": []
@@ -414,7 +494,7 @@
{
"name": "cpu_addr",
"width": 16,
"clk_domain": "clk_50",
"clk_domain": "clk_2",
"selected_probe_type": "DATA AND TRIGGER",
"child": [],
"path": [],
@@ -422,49 +502,69 @@
"net_idx_right": 0
},
{
"name": "cpu_phi2",
"name": "cpu_sync",
"width": 1,
"clk_domain": "clk_50",
"clk_domain": "clk_2",
"selected_probe_type": "DATA AND TRIGGER",
"child": [],
"path": []
},
{
"name": "spi_clk",
"name": "cpu_rdy",
"width": 1,
"clk_domain": "clk_50",
"clk_domain": "clk_2",
"selected_probe_type": "DATA AND TRIGGER",
"child": [],
"path": []
},
{
"name": "spi_mosi",
"width": 1,
"clk_domain": "clk_50",
"name": "r_input_data",
"width": 8,
"clk_domain": "clk_2",
"selected_probe_type": "DATA AND TRIGGER",
"child": [],
"path": []
"path": [
"spi_controller"
],
"net_idx_left": 7,
"net_idx_right": 0
},
{
"name": "sd_cs",
"width": 1,
"clk_domain": "clk_50",
"name": "r_output_data",
"width": 8,
"clk_domain": "clk_2",
"selected_probe_type": "DATA AND TRIGGER",
"child": [],
"path": []
"path": [
"spi_controller"
],
"net_idx_left": 7,
"net_idx_right": 0
},
{
"name": "spi_miso",
"name": "o_spi_clk",
"width": 1,
"clk_domain": "clk_50",
"clk_domain": "clk_2",
"selected_probe_type": "DATA AND TRIGGER",
"child": [],
"path": []
"path": [
"spi_controller"
]
},
{
"name": "active",
"name": "o_spi_mosi",
"width": 1,
"clk_domain": "clk_50",
"clk_domain": "clk_2",
"selected_probe_type": "DATA AND TRIGGER",
"child": [],
"path": [
"spi_controller"
]
},
{
"name": "i_spi_miso",
"width": 1,
"clk_domain": "clk_2",
"selected_probe_type": "DATA AND TRIGGER",
"child": [],
"path": [

View File

@@ -1,257 +1,257 @@
@00000000
8D 0E 02 8E 0F 02 8D 15 02 8E 16 02 88 B9 FF FF
8D 1F 02 88 B9 FF FF 8D 1E 02 8C 21 02 20 FF FF
A0 FF D0 E8 60 A2 FF 9A D8 A9 F0 85 00 A9 7E 85
01 20 72 F8 20 F0 F6 20 45 F0 58 20 03 F1 6C FC
FF 20 E4 F6 00 A0 00 F0 07 A9 45 A2 F0 4C 00 02
60 AD FF EF A2 00 60 8D FF EF 60 20 E9 F0 C9 0A
D0 05 A9 0D 20 E9 F0 60 DA 5A A8 B2 00 AA A9 1B
20 E9 F0 A9 5B 20 E9 F0 98 20 E9 F0 A9 3B 20 E9
F0 8A 20 E9 F0 A9 48 20 E9 F0 7A FA 60 DA A9 1B
20 E9 F0 A9 63 20 E9 F0 68 60 40 DA BA 48 E8 E8
BD 00 01 29 10 D0 06 68 FA 20 02 F1 40 4C AD F0
48 A0 04 B1 00 09 40 20 D9 F0 88 B1 00 20 D9 F0
88 10 F8 68 09 01 20 D9 F0 20 AC F7 60 A9 01 8D
DB EF 60 9C DB EF 60 A9 00 8D DA EF AD DB EF 30
FB AD D9 EF 60 8D E6 EF 60 48 8D E6 EF AD E7 EF
89 02 D0 F9 68 60 AD E6 EF A2 00 60 AD E7 EF A2
00 60 60 20 70 F7 A2 00 86 02 86 03 A9 00 20 DD
F7 20 49 F7 A9 B9 A2 F8 20 27 F7 20 45 F1 C9 00
20 F5 F7 D0 03 4C 32 F1 A9 95 A2 F8 20 27 F7 4C
39 F1 A9 AA A2 F8 20 27 F7 4C 3C F1 4C 3C F1 A0
0C 20 D7 F6 60 20 7D F7 A9 00 20 25 F8 20 B7 F2
4C 7C F1 A0 00 A2 00 18 A9 01 71 00 91 00 A0 00
A2 00 B1 00 C9 FF 20 FB F7 D0 03 4C 7C F1 A9 DB
A2 F8 20 27 F7 A2 00 A9 01 4C B3 F2 20 69 F4 A0
01 91 00 C9 01 20 F5 F7 D0 C9 A2 00 A9 00 A0 06
20 69 F8 A0 07 20 C1 F7 E0 03 D0 02 C9 E8 20 14
F8 F0 03 4C A9 F1 4C B5 F1 A0 06 A2 00 A9 01 20
C7 F6 4C 93 F1 A9 01 20 C8 F7 20 C3 F4 A0 01 A2
00 B1 00 C9 01 20 F5 F7 D0 03 4C DB F1 A9 D1 A2
F8 20 27 F7 A2 00 A9 01 4C B3 F2 A0 05 A2 00 B1
00 C9 AA 20 F5 F7 D0 03 4C F2 F1 A2 00 A9 01 4C
B3 F2 A2 00 A9 00 A0 00 91 00 A0 00 A2 00 B1 00
C9 FF 20 FB F7 D0 03 4C 18 F2 A9 C1 A2 F8 20 27
F7 A2 00 A9 01 4C B3 F2 20 E5 F5 A0 01 91 00 A0
01 A2 00 B1 00 C9 02 20 14 F8 D0 03 4C 36 F2 20
3F F6 A0 01 91 00 A2 00 A9 00 A0 06 20 69 F8 A0
07 20 C1 F7 E0 03 D0 02 C9 E8 20 14 F8 F0 03 4C
55 F2 4C 61 F2 A0 06 A2 00 A9 01 20 C7 F6 4C 3F
F2 A0 00 A2 00 18 A9 01 71 00 91 00 A0 01 A2 00
B1 00 C9 00 20 F5 F7 D0 81 A2 00 A9 00 A0 06 20
69 F8 A0 07 20 C1 F7 E0 03 D0 02 C9 E8 20 14 F8
F0 03 4C 98 F2 4C A4 F2 A0 06 A2 00 A9 01 20 C7
F6 4C 82 F2 A9 01 20 C8 F7 20 6B F5 A2 00 A9 00
4C B3 F2 20 B1 F7 60 20 56 F7 A2 00 A9 00 20 D3
F0 A2 00 A9 00 A0 01 20 69 F8 A0 02 20 C1 F7 E0
03 D0 02 C9 E8 20 14 F8 F0 03 4C E0 F2 4C EC F2
A0 01 A2 00 A9 01 20 C7 F6 4C CA F2 A2 00 A9 FF
20 D9 F0 A2 00 A9 00 20 D3 F0 A2 00 A9 00 A0 00
91 00 A0 00 A2 00 B1 00 C9 50 20 14 F8 F0 03 4C
15 F3 4C 2A F3 A2 00 A9 FF 20 D9 F0 A0 00 A2 00
18 A9 01 71 00 91 00 4C 02 F3 20 A7 F7 60 A9 00
20 25 F8 20 40 F7 4C 59 F3 A0 01 A2 00 18 A9 01
71 00 91 00 A0 01 A2 00 B1 00 C9 09 A9 00 A2 00
2A D0 03 4C 59 F3 4C 6B F3 A2 00 A9 FF 20 D9 F0
A0 00 91 00 C9 FF 20 FB F7 D0 CE A0 00 A2 00 B1
00 4C 74 F3 20 99 F7 60 20 3B F8 A0 01 20 C1 F7
20 3B F8 20 2E F3 A0 00 20 51 F8 A0 01 20 C1 F7
1A D0 01 E8 20 3B F8 A2 00 A9 FF 20 D9 F0 A0 00
20 51 F8 20 99 F7 60 20 3B F8 A0 01 20 C1 F7 20
3B F8 20 2E F3 A0 00 20 51 F8 A0 01 20 C1 F7 A0
00 20 B6 F7 C9 02 A9 00 A2 00 2A D0 03 4C D3 F3
4C E6 F3 A0 01 20 C1 F7 1A D0 01 E8 20 3B F8 A2
00 A9 04 20 2D F4 20 99 F7 60 20 3B F8 A0 01 20
C1 F7 20 3B F8 20 2E F3 A0 00 20 51 F8 A0 01 20
C1 F7 A0 00 20 B6 F7 C9 02 A9 00 A2 00 2A D0 03
4C 16 F4 4C 29 F4 A0 01 20 C1 F7 1A D0 01 E8 20
3B F8 A2 00 A9 04 20 2D F4 20 99 F7 60 20 25 F8
4C 52 F4 A0 02 20 C1 F7 20 3B F8 A2 00 A9 FF 48
A0 03 A2 00 A9 01 20 C7 F6 68 20 D9 F0 A0 00 20
51 F8 A0 00 B1 00 08 A0 00 A2 00 B1 00 38 E9 01
91 00 28 D0 CE 20 A7 F7 60 20 40 F7 A2 00 A9 FF
20 D9 F0 A2 00 A9 00 20 CD F0 A2 00 A9 FF 20 D9
F0 A2 00 A9 00 20 25 F8 A2 00 86 02 86 03 A9 00
20 DD F7 A2 00 A9 94 20 B0 F0 20 2E F3 A0 00 91
00 A2 00 A9 FF 20 D9 F0 A2 00 A9 00 20 D3 F0 A2
00 A9 FF 20 D9 F0 A0 00 A2 00 B1 00 4C BF F4 20
8A F7 60 20 3B F8 A2 00 A9 FF 20 D9 F0 A2 00 A9
00 20 CD F0 A2 00 A9 FF 20 D9 F0 A2 00 A9 08 20
25 F8 A2 01 A9 00 85 02 A9 00 85 03 A9 AA 20 DD
F7 A2 00 A9 86 20 B0 F0 A0 01 20 C1 F7 20 EA F3
A2 00 A9 FF 20 D9 F0 A2 00 A9 00 20 D3 F0 A2 00
A9 FF 20 D9 F0 20 99 F7 60 20 3B F8 A2 00 A9 FF
20 D9 F0 A2 00 A9 00 20 CD F0 A2 00 A9 FF 20 D9
F0 A2 00 A9 0D 20 25 F8 A2 00 86 02 86 03 A9 00
20 DD F7 A2 00 A9 00 20 B0 F0 A0 01 20 C1 F7 20
78 F3 A2 00 A9 FF 20 D9 F0 A2 00 A9 00 20 D3 F0
A2 00 A9 FF 20 D9 F0 20 99 F7 60 20 3B F8 20 40
F7 A2 00 A9 FF 20 D9 F0 A2 00 A9 00 20 CD F0 A2
00 A9 FF 20 D9 F0 A0 00 91 00 A0 00 A2 00 B1 00
C9 FF 20 F5 F7 D0 03 4C AB F5 4C 9D F5 A2 00 A9
FF 20 D9 F0 C9 FF 20 F5 F7 D0 F2 A2 00 A9 3A 20
25 F8 A2 00 86 02 86 03 A9 00 20 DD F7 A2 00 A9
00 20 B0 F0 A0 02 20 C1 F7 20 A7 F3 A2 00 A9 FF
20 D9 F0 A2 00 A9 00 20 D3 F0 A2 00 A9 FF 20 D9
F0 20 A7 F7 60 20 40 F7 A2 00 A9 FF 20 D9 F0 A2
00 A9 00 20 CD F0 A2 00 A9 FF 20 D9 F0 A2 00 A9
37 20 25 F8 A2 00 86 02 86 03 A9 00 20 DD F7 A2
00 A9 00 20 B0 F0 20 2E F3 A0 00 91 00 A2 00 A9
FF 20 D9 F0 A2 00 A9 00 20 D3 F0 A2 00 A9 FF 20
D9 F0 A0 00 A2 00 B1 00 4C 3B F6 20 8A F7 60 20
40 F7 A2 00 A9 FF 20 D9 F0 A2 00 A9 00 20 CD F0
A2 00 A9 FF 20 D9 F0 A2 00 A9 29 20 25 F8 A2 00
86 02 A9 40 85 03 A9 00 20 DD F7 A2 00 A9 00 20
B0 F0 20 2E F3 A0 00 91 00 A2 00 A9 FF 20 D9 F0
A2 00 A9 00 20 D3 F0 A2 00 A9 FF 20 D9 F0 A0 00
A2 00 B1 00 4C 97 F6 20 8A F7 60 20 3B F8 20 70
F7 A0 05 A2 00 B1 00 4C AA F6 A0 0E 20 D7 F6 60
20 3B F8 20 70 F7 A0 03 A2 00 B1 00 4C BF F6 A0
0E 20 D7 F6 60 A0 00 18 71 00 91 00 48 C8 8A 71
00 91 00 AA 68 60 C8 48 18 98 65 00 85 00 90 02
E6 01 68 60 A0 00 F0 07 A9 45 A2 F0 4C 00 02 60
A9 00 85 08 A9 F0 85 09 A9 00 85 0A A9 02 85 0B
A2 DA A9 FF 85 10 A0 00 E8 F0 0D B1 08 91 0A C8
D0 F6 E6 09 E6 0B D0 F0 E6 10 D0 EF 60 85 08 86
09 20 68 F0 4C 2B F7 85 08 86 09 A0 00 B1 08 F0
0E C8 84 10 20 5B F0 A4 10 D0 F2 E6 09 D0 EE 60
A4 00 D0 02 C6 01 C6 00 60 A5 00 38 E9 02 85 00
90 01 60 C6 01 60 A5 00 38 E9 03 85 00 90 01 60
C6 01 60 A5 00 38 E9 04 85 00 90 01 60 C6 01 60
A5 00 38 E9 06 85 00 90 01 60 C6 01 60 A5 00 38
E9 07 85 00 90 01 60 C6 01 60 E6 00 D0 02 E6 01
60 A0 01 B1 00 AA 88 B1 00 E6 00 F0 05 E6 00 F0
03 60 E6 00 E6 01 60 A0 03 4C D7 F6 A0 05 4C D7
F6 A0 08 4C D7 F6 85 08 86 09 A2 00 B1 08 60 A0
01 B1 00 AA 88 B1 00 60 A2 00 18 65 00 48 8A 65
01 AA 68 60 A9 00 AA A0 00 84 02 84 03 48 20 63
F7 A0 03 A5 03 91 00 88 A5 02 91 00 88 8A 91 00
68 88 91 00 60 D0 06 A2 00 8A 60 D0 FA A2 00 A9
01 60 F0 F9 30 F7 A2 00 8A 60 F0 02 10 EF A2 00
8A 60 F0 E9 90 E7 A2 00 8A 60 F0 DB A2 00 8A 2A
60 A0 00 B1 00 A4 00 F0 07 C6 00 A0 00 91 00 60
C6 01 C6 00 91 00 60 A9 00 A2 00 48 A5 00 38 E9
02 85 00 B0 02 C6 01 A0 01 8A 91 00 68 88 91 00
60 48 84 10 A0 01 B1 00 85 09 88 B1 00 85 08 A4
10 68 91 08 4C 99 F7 A0 00 91 00 C8 48 8A 91 00
68 60 A9 25 85 08 A9 02 85 09 A9 00 A8 A2 02 F0
0A 91 08 C8 D0 FB E6 09 CA D0 F6 C0 00 F0 05 91
08 C8 D0 F7 60 45 72 72 6F 72 20 69 6E 69 74 20
53 44 20 43 41 52 44 0D 0A 00 53 44 20 43 61 72
64 20 69 6E 69 74 0D 0A 00 53 74 61 72 74 0D 0A
00 6F 70 5F 63 6F 6E 64 20 65 72 72 6F 72 0D 0A
00 49 46 20 43 6F 6E 64 0D 0A 00 47 6F 20 49 44
4C 45 0D 0A 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 9A F0 25 F0 9B F0
00 80 4C 00 00 8D 13 92 8E 14 92 8D 1A 92 8E 1B
92 88 B9 FF FF 8D 24 92 88 B9 FF FF 8D 23 92 8C
26 92 20 FF FF A0 FF D0 E8 60 00 00 90 FD 00 00
00 00 A2 FF 9A D8 A9 00 85 02 A9 DF 85 03 20 08
FE 20 B9 FA 20 52 F0 58 20 69 F2 6C FC FF 20 AD
FA 00 A0 00 F0 07 A9 52 A2 F0 4C 05 92 60 AD FF
EF A2 00 60 8D FF EF 60 20 4F F2 C9 0A D0 05 A9
0D 20 4F F2 60 DA 5A A8 B2 02 AA A9 1B 20 4F F2
A9 5B 20 4F F2 98 20 4F F2 A9 3B 20 4F F2 8A 20
4F F2 A9 48 20 4F F2 7A FA 60 DA A9 1B 20 4F F2
A9 63 20 4F F2 68 60 40 DA BA 48 E8 E8 BD 00 01
29 10 D0 06 68 FA 20 68 F2 40 68 FA 7C BF F0 C5
F0 C9 F0 CA F0 20 9A F0 40 40 20 68 F0 40 48 A0
04 B1 02 09 40 20 3F F2 88 B1 02 20 3F F2 88 10
F8 68 09 01 20 3F F2 20 A9 FB 60 A2 08 A9 FF 20
3F F2 C9 FF D0 03 CA D0 F4 60 85 0A 86 0B 20 EB
F0 92 0A A9 FF 20 3F F2 A0 01 91 0A 20 96 FB 60
AA 20 E4 FC A9 FF 20 3F F2 92 0A E6 0A D0 02 E6
0B CA D0 F0 60 85 0A 86 0B 20 EB F0 C9 02 B0 12
E6 0A D0 02 E6 0A A5 0A A6 0B 20 11 FD A9 04 20
10 F1 60 48 A9 FF 20 3F F2 A9 00 20 33 F2 A9 FF
20 3F F2 68 20 CE F0 20 EB F0 A8 A9 FF 20 3F F2
A9 00 20 39 F2 A9 FF 20 3F F2 98 A2 00 60 A9 00
20 39 F2 20 8B F1 A9 FF 20 3F F2 A9 00 20 39 F2
A2 50 A9 FF 20 3F F2 CA D0 F8 60 A2 01 A9 C8 3A
D0 FD CA D0 F8 60 85 0C 86 0D A9 FF 92 0C 20 E4
FC A5 02 85 0E A5 03 85 0F 20 51 FB A0 00 B1 0E
91 02 C8 B1 0E 91 02 C8 B1 0E 91 02 C8 B1 0E 91
02 A9 FF 20 3F F2 A9 00 20 33 F2 A9 FF 20 3F F2
A9 11 A0 04 91 02 A9 00 20 CE F0 20 EB F0 C9 FF
F0 3F 85 14 A0 00 A9 FF 20 3F F2 85 13 A5 13 C9
FF D0 05 C8 D0 F0 80 23 A2 02 A0 00 A9 FF 20 3F
F2 92 0A E6 0A D0 02 E6 0B 88 D0 F0 A0 00 CA D0
EB A9 FF 20 3F F2 A9 FF 20 3F F2 A5 13 92 0C A5
14 48 A9 FF 20 3F F2 A9 00 20 39 F2 A9 FF 20 3F
F2 68 60 A9 01 8D DB EF 60 9C DB EF 60 A9 00 8D
DA EF AD DB EF 30 FB AD D9 EF 60 8D E6 EF 60 48
8D E6 EF AD E7 EF 89 02 D0 F9 68 60 AD E6 EF A2
00 60 AD E7 EF A2 00 60 60 20 74 FB A2 00 86 04
86 05 A9 00 20 0B FC 20 5A FB A9 4D A2 FE 20 1A
FB 20 3A F3 C9 00 20 B8 FC D0 03 4C 98 F2 A9 45
A2 FE 20 1A FB 4C 2E F3 A9 3B A2 FE 20 1A FB A0
05 20 C7 FB 20 0B FC AD 00 92 AE 01 92 20 11 FD
A9 0C 20 D8 FB 20 96 F1 A0 07 91 02 A0 07 A2 00
B1 02 C9 00 20 BE FC D0 03 4C DC F2 A0 06 A2 00
B1 02 C9 FE 20 BE FC F0 03 4C E5 F2 A2 00 A9 00
D0 03 4C E9 F2 A2 00 A9 01 D0 03 4C FA F2 AD 00
92 AE 01 92 20 3C F6 4C 2B F3 A0 06 A2 00 B1 02
A2 00 29 F0 20 9F FA D0 03 4C 16 F3 A9 45 A2 FE
20 1A FB 4C 2B F3 A9 2B A2 FE 20 11 FD A0 08 A2
00 B1 02 20 11 FD A0 04 20 E6 FA 6C 00 92 4C 31
F3 4C 31 F3 A0 0C 20 85 FA 60 20 81 FB A9 00 20
FB FC 20 6E F1 4C 71 F3 A0 00 A2 00 18 A9 01 71
02 91 02 A0 00 A2 00 B1 02 C9 FF 20 BE FC D0 03
4C 71 F3 A9 6F A2 FE 20 1A FB A2 00 A9 01 4C A8
F4 20 AC F4 A0 01 91 02 C9 01 20 B8 FC D0 C9 A2
00 A9 00 A0 06 20 29 FD A0 07 20 BE FB E0 03 D0
02 C9 E8 20 D7 FC F0 03 4C 9E F3 4C AA F3 A0 06
A2 00 A9 01 20 75 FA 4C 88 F3 A9 01 20 D8 FB 20
C9 F4 A0 01 A2 00 B1 02 C9 01 20 B8 FC D0 03 4C
D0 F3 A9 65 A2 FE 20 1A FB A2 00 A9 01 4C A8 F4
A0 05 A2 00 B1 02 C9 AA 20 B8 FC D0 03 4C E7 F3
A2 00 A9 01 4C A8 F4 A2 00 A9 00 A0 00 91 02 A0
00 A2 00 B1 02 C9 FF 20 BE FC D0 03 4C 0D F4 A9
55 A2 FE 20 1A FB A2 00 A9 01 4C A8 F4 20 EB F5
A0 01 91 02 A0 01 A2 00 B1 02 C9 02 20 D7 FC D0
03 4C 2B F4 20 08 F6 A0 01 91 02 A2 00 A9 00 A0
06 20 29 FD A0 07 20 BE FB E0 03 D0 02 C9 E8 20
D7 FC F0 03 4C 4A F4 4C 56 F4 A0 06 A2 00 A9 01
20 75 FA 4C 34 F4 A0 00 A2 00 18 A9 01 71 02 91
02 A0 01 A2 00 B1 02 C9 00 20 B8 FC D0 81 A2 00
A9 00 A0 06 20 29 FD A0 07 20 BE FB E0 03 D0 02
C9 E8 20 D7 FC F0 03 4C 8D F4 4C 99 F4 A0 06 A2
00 A9 01 20 75 FA 4C 77 F4 A9 01 20 D8 FB 20 71
F5 A2 00 A9 00 4C A8 F4 20 AE FB 60 A2 00 A9 00
20 FB FC A2 00 86 04 86 05 A9 00 20 0B FC A2 00
A9 94 20 43 F1 4C C8 F4 60 20 11 FD A2 00 A9 FF
20 3F F2 A2 00 A9 00 20 33 F2 A2 00 A9 FF 20 3F
F2 A2 00 A9 08 20 FB FC A2 01 A9 00 85 04 A9 00
85 05 A9 AA 20 0B FC A2 00 A9 86 20 CE F0 A0 01
20 BE FB 20 25 F1 A2 00 A9 FF 20 3F F2 A2 00 A9
00 20 39 F2 A2 00 A9 FF 20 3F F2 20 96 FB 60 20
11 FD A2 00 A9 FF 20 3F F2 A2 00 A9 00 20 33 F2
A2 00 A9 FF 20 3F F2 A2 00 A9 0D 20 FB FC A2 00
86 04 86 05 A9 00 20 0B FC A2 00 A9 00 20 CE F0
A0 01 20 BE FB 20 FA F0 A2 00 A9 FF 20 3F F2 A2
00 A9 00 20 39 F2 A2 00 A9 FF 20 3F F2 20 96 FB
60 20 11 FD 20 51 FB A2 00 A9 FF 20 3F F2 A2 00
A9 00 20 33 F2 A2 00 A9 FF 20 3F F2 A0 00 91 02
A0 00 A2 00 B1 02 C9 FF 20 B8 FC D0 03 4C B1 F5
4C A3 F5 A2 00 A9 FF 20 3F F2 C9 FF 20 B8 FC D0
F2 A2 00 A9 3A 20 FB FC A2 00 86 04 86 05 A9 00
20 0B FC A2 00 A9 00 20 CE F0 A0 02 20 BE FB 20
25 F1 A2 00 A9 FF 20 3F F2 A2 00 A9 00 20 39 F2
A2 00 A9 FF 20 3F F2 20 A4 FB 60 A2 00 A9 37 20
FB FC A2 00 86 04 86 05 A9 00 20 0B FC A2 00 A9
00 20 43 F1 4C 07 F6 60 A2 00 A9 29 20 FB FC A2
00 86 04 A9 40 85 05 A9 00 20 0B FC A2 00 A9 00
20 43 F1 4C 26 F6 60 20 11 FD 20 74 FB A0 03 A2
00 B1 02 4C 36 F6 A0 0E 20 85 FA 60 20 11 FD A9
00 20 FB FC 20 5A FB A2 00 A9 00 A0 00 20 29 FD
A0 01 20 BE FB E0 02 20 D7 FC F0 03 4C 62 F6 4C
C4 F6 A9 79 A2 FE 20 11 FD A0 06 20 BE FB A0 00
20 B3 FB 20 11 FD A0 07 A2 00 A9 01 20 75 FA A0
04 20 E6 FA A0 02 A2 00 B1 02 C9 1F 20 BE FC D0
03 4C A6 F6 A9 7D A2 FE 20 1A FB A2 00 A9 00 A0
02 91 02 4C B8 F6 A2 00 A9 20 20 68 F0 A0 02 A2
00 18 A9 01 71 02 91 02 A0 00 A2 00 A9 01 20 75
FA 4C 50 F6 A9 7D A2 FE 20 1A FB 20 A9 FB 60 A0
00 B1 18 E6 18 D0 02 E6 19 60 AD 3D 92 8D 38 92
20 7B F7 A9 38 A2 92 20 11 FD 20 F2 FC 4C 02 92
A5 16 38 E9 02 85 16 B0 02 C6 17 60 AD 42 92 D0
11 20 19 F7 4C 98 FA AD 42 92 D0 06 20 19 F7 4C
92 FA 20 19 F7 85 04 86 05 20 F0 F6 A0 01 B1 16
AA 88 B1 16 60 A0 00 84 0A 84 0B B1 18 38 E9 30
90 2C C9 0A B0 28 20 D3 F6 48 A5 0A A6 0B 06 0A
26 0B 06 0A 26 0B 65 0A 85 0A 8A 65 0B 85 0B 06
0A 26 0B 68 65 0A 85 0A 90 D1 E6 0B B0 CD A5 0A
A6 0B 60 AC 44 92 EE 44 92 99 45 92 60 A9 45 A2
92 18 6D 44 92 90 01 E8 4C 11 FD A5 1A A6 1B 4C
11 FD 20 DA F6 EE 3E 92 D0 F8 EE 3F 92 D0 F3 60
20 7B F7 AD 59 92 AE 5A 92 20 11 FD AD 5B 92 AE
5C 92 20 11 FD 4C 02 92 84 0A 20 0B FC 20 6D F7
A5 0A 4C 3B FC 84 0A 20 0B FC 20 6D F7 A5 0A 4C
7C FC 48 A0 05 B9 16 00 99 32 92 88 10 F7 68 85
16 86 17 20 8E FB 85 18 86 19 20 8E FB 85 1A 86
1B A9 00 A8 91 1A C8 91 1A C8 B1 1A 8D 03 92 C8
B1 1A 8D 04 92 A5 18 85 0A A5 19 85 0B A0 00 B1
18 F0 0B C9 25 F0 07 C8 D0 F5 E6 19 D0 F1 98 18
65 18 85 18 90 02 E6 19 38 E5 0A 85 0C A5 19 E5
0B 85 0D 05 0C F0 25 20 74 FB A0 05 A5 1B 91 02
88 A5 1A 91 02 88 A5 0B 91 02 88 A5 0A 91 02 88
A5 0D 91 02 88 A5 0C 91 02 20 02 92 20 CF F6 AA
D0 0B A2 05 BD 32 92 95 16 CA 10 F8 60 C9 25 D0
09 B1 18 C9 25 D0 09 20 D3 F6 20 DD F6 4C F5 F7
A9 00 A2 0B 9D 39 92 CA 10 FA B1 18 C9 2D D0 05
8E 39 92 F0 19 C9 2B D0 05 8E 3A 92 F0 10 C9 20
D0 05 8E 3B 92 F0 07 C9 23 D0 09 8E 3C 92 20 D3
F6 4C 7A F8 A2 20 C9 30 D0 06 AA 20 D3 F6 B1 18
8E 3D 92 C9 2A D0 09 20 D3 F6 20 19 F7 4C C3 F8
20 25 F7 8D 3E 92 8E 3F 92 8C 40 92 8C 41 92 B1
18 C9 2E D0 1B 20 D3 F6 B1 18 C9 2A D0 09 20 D3
F6 20 19 F7 4C EA F8 20 25 F7 8D 40 92 8E 41 92
B1 18 C9 7A F0 19 C9 68 F0 15 C9 74 F0 11 C9 6A
F0 08 C9 4C F0 04 C9 6C D0 0B A9 FF 8D 42 92 20
D3 F6 4C F0 F8 8C 44 92 A2 45 8E 59 92 A2 92 8E
5A 92 20 D3 F6 C9 63 D0 0D 20 19 F7 8D 45 92 A2
00 A9 01 4C 1C FA C9 64 F0 04 C9 69 D0 2D A2 00
AD 3B 92 F0 02 A2 20 AD 3A 92 F0 02 A2 2B 8E 43
92 20 07 F7 A4 05 30 0B AC 43 92 F0 06 8C 45 92
EE 44 92 A0 0A 20 A8 F7 4C 13 FA C9 6E D0 15 20
19 F7 85 0A 86 0B A0 00 B1 1A 91 0A C8 B1 1A 91
0A 4C F5 F7 C9 6F D0 27 20 07 F7 AC 3C 92 F0 17
48 86 12 05 12 05 04 05 05 0D 40 92 0D 41 92 F0
06 A9 30 20 63 F7 68 A0 08 20 A8 F7 4C 13 FA C9
70 D0 0D A2 00 8E 42 92 E8 8E 3C 92 A9 78 D0 27
C9 73 D0 0C 20 19 F7 8D 59 92 8E 5A 92 4C 13 FA
C9 75 D0 0B 20 FC F6 A0 0A 20 B5 F7 4C 13 FA C9
78 F0 04 C9 58 D0 29 48 AD 3C 92 F0 0A A9 30 20
63 F7 A9 58 20 63 F7 20 FC F6 A0 10 20 B5 F7 68
C9 78 D0 09 AD 59 92 AE 5A 92 20 69 FD 4C 13 FA
4C F5 F7 AD 59 92 AE 5A 92 20 53 FD 8D 5B 92 8E
5C 92 AD 40 92 0D 41 92 F0 15 AE 40 92 EC 5B 92
AD 41 92 A8 ED 5C 92 B0 06 8E 5B 92 8C 5C 92 38
AD 3E 92 ED 5B 92 AA AD 3F 92 ED 5C 92 B0 03 A9
00 AA 49 FF 8D 3F 92 8A 49 FF 8D 3E 92 AD 39 92
D0 03 20 85 F7 20 90 F7 AD 39 92 F0 03 20 85 F7
4C F5 F7 A0 00 18 71 02 91 02 48 C8 8A 71 02 91
02 AA 68 60 C8 48 18 98 65 02 85 02 90 02 E6 03
68 60 A0 FF E0 80 B0 02 A0 00 84 04 84 05 60 E0
00 D0 06 AA D0 03 A9 01 60 A2 00 8A 60 A0 00 F0
07 A9 52 A2 F0 4C 05 92 60 A9 00 85 0A A9 F0 85
0B A9 00 85 0C A9 92 85 0D A2 CD A9 FF 85 12 A0
00 E8 F0 0D B1 0A 91 0C C8 D0 F6 E6 0B E6 0D D0
F0 E6 12 D0 EF 60 8C 5D 92 88 88 98 18 65 02 85
0A A6 03 90 01 E8 86 0B A0 01 B1 0A AA 88 B1 0A
20 11 FD A5 0A A6 0B 20 D8 FD AC 5D 92 4C 85 FA
85 0A 86 0B 20 75 F0 4C 1E FB 85 0A 86 0B A0 00
B1 0A F0 0E C8 84 12 20 68 F0 A4 12 D0 F2 E6 0B
D0 EE 60 E0 00 D0 15 4A AA BD A7 FE 90 05 4A 4A
4A 4A 18 29 0F AA BD 9C FE A2 00 60 38 A9 00 AA
60 A4 02 D0 02 C6 03 C6 02 60 A5 02 38 E9 02 85
02 90 01 60 C6 03 60 A5 02 38 E9 04 85 02 90 01
60 C6 03 60 A5 02 38 E9 06 85 02 90 01 60 C6 03
60 A5 02 38 E9 07 85 02 90 01 60 C6 03 60 A0 01
B1 02 AA 88 B1 02 E6 02 F0 05 E6 02 F0 03 60 E6
02 E6 03 60 A0 03 4C 85 FA A0 05 4C 85 FA A0 08
4C 85 FA 85 0A 86 0B A2 00 B1 0A 60 A0 01 B1 02
AA 88 B1 02 60 A0 03 B1 02 85 05 88 B1 02 85 04
88 B1 02 AA 88 B1 02 60 A2 00 18 65 02 48 8A 65
03 AA 68 60 18 49 FF 69 01 48 8A 49 FF 69 00 AA
A5 04 49 FF 69 00 85 04 A5 05 49 FF 69 00 85 05
68 60 A9 00 AA A0 00 84 04 84 05 48 20 67 FB A0
03 A5 05 91 02 88 A5 04 91 02 88 8A 91 02 68 88
91 02 60 85 12 20 8E FB 85 0C 86 0D 85 0E 86 0F
20 E4 FC 20 8E FB 85 04 86 05 60 20 23 FC A6 05
A4 12 C0 0A D0 39 A5 04 05 0B 05 0A D0 11 E0 80
D0 0D A0 0B B9 90 FE 91 0C 88 10 F8 4C B3 FC 8A
10 1D A9 2D A0 00 91 0C E6 0C D0 02 E6 0D A5 0A
A6 0B 20 E4 FB 85 0A 86 0B 4C 7F FC 20 23 FC A9
00 48 A0 20 A9 00 06 0A 26 0B 26 04 26 05 2A C5
12 90 04 E5 12 E6 0A 88 D0 EC A8 B9 80 FE 48 A5
0A 05 0B 05 04 05 05 D0 D9 A0 00 68 91 0C F0 03
C8 D0 F8 A5 0E A6 0F 60 D0 06 A2 00 8A 60 D0 FA
A2 00 A9 01 60 F0 F9 30 F7 A2 00 8A 60 F0 02 10
EF A2 00 8A 60 F0 E9 90 E7 A2 00 8A 60 F0 DB A2
00 8A 2A 60 A0 01 B1 02 85 0B 88 B1 02 85 0A 4C
96 FB A9 01 4C 0F FD A0 00 B1 02 A4 02 F0 07 C6
02 A0 00 91 02 60 C6 03 C6 02 91 02 60 A9 00 A2
00 48 A5 02 38 E9 02 85 02 B0 02 C6 03 A0 01 8A
91 02 68 88 91 02 60 A0 00 91 02 C8 48 8A 91 02
68 60 85 0C 86 0D 20 E4 FC B1 0A D1 0C D0 0C AA
F0 10 C8 D0 F4 E6 0B E6 0D D0 EE B0 03 A2 FF 60
A2 01 60 85 0C 86 0D A2 00 A0 00 B1 0C F0 08 C8
D0 F9 E6 0D E8 D0 F4 98 60 85 0A 86 0B 85 0C 86
0D A0 00 B1 0A F0 14 20 37 FB 29 02 F0 06 B1 0A
69 20 91 0A C8 D0 EC E6 0B D0 E8 A5 0C A6 0D 60
20 8E FB 85 0C 86 0D E8 8E 31 92 AA E8 8E 30 92
20 E4 FC 20 8E FB 85 0E 86 0F A0 00 84 12 B1 0E
18 65 0C 91 0E C8 B1 0E 65 0D 91 0E CE 30 92 F0
11 A4 12 B1 0A C8 D0 02 E6 0B 84 12 20 68 F0 4C
BC FD CE 31 92 D0 EA 60 85 0A 86 0B A9 00 8D 2A
92 8D 2B 92 A0 01 B1 02 AA 88 B1 02 20 11 FD A0
02 A9 2A 91 02 C8 A9 92 91 02 A5 0A A6 0B 20 C2
F7 AD 2A 92 AE 2B 92 60 A9 32 85 0A A9 92 85 0B
A9 00 A8 A2 00 F0 0A 91 0A C8 D0 FB E6 0B CA D0
F6 C0 2C F0 05 91 0A C8 D0 F7 60 62 61 64 20 74
6F 6B 65 6E 3A 20 25 78 0D 0A 00 53 75 63 63 65
73 73 0D 0A 00 45 72 72 6F 72 0D 0A 00 53 74 61
72 74 0D 0A 00 6F 70 5F 63 6F 6E 64 20 65 72 72
6F 72 0D 0A 00 49 46 20 43 6F 6E 64 0D 0A 00 47
6F 20 49 44 4C 45 0D 0A 00 25 32 78 00 0D 0A 00
30 31 32 33 34 35 36 37 38 39 41 42 43 44 45 46
2D 32 31 34 37 34 38 33 36 34 38 00 00 01 02 0C
09 0A 10 40 50 A0 D0 66 66 66 66 A6 88 88 66 66
66 66 66 66 66 66 66 09 00 00 00 00 00 00 00 33
33 33 33 33 00 00 00 50 55 55 25 22 22 22 22 22
22 22 22 22 02 00 00 40 44 44 14 11 11 11 11 11
11 11 11 11 01 00 70 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 A7 F0 32 F0 A8 F0

View File

@@ -23,12 +23,12 @@
},
"output": {
"external_source_source": [
"/home/byron/Projects/super6502/hw/efinix_fpga/ip/uart/uart_tmpl.v",
"/home/byron/Projects/super6502/hw/efinix_fpga/ip/uart/uart.v",
"/home/byron/Projects/super6502/hw/efinix_fpga/ip/uart/uart_tmpl.vhd",
"/home/byron/Projects/super6502/hw/efinix_fpga/ip/uart/uart_define.vh"
"/home/byron/Projects/super6502/hw/efinix_fpga/ip/uart/uart_define.vh",
"/home/byron/Projects/super6502/hw/efinix_fpga/ip/uart/uart_tmpl.v",
"/home/byron/Projects/super6502/hw/efinix_fpga/ip/uart/uart.v"
]
},
"sw_version": "2023.1.150",
"generated_date": "2023-07-23T03:23:04.338270"
"generated_date": "2023-08-06T21:23:16.380430"
}

View File

@@ -43,7 +43,7 @@
//
////////////////////////////////////////////////////////////////////////////////
`define IP_UUID _8d7ceb45e0e64e208e634a02f6a59365
`define IP_UUID _d5f4d7c01b1345bca7e33275f3464327
`define IP_NAME_CONCAT(a,b) a``b
`define IP_MODULE_NAME(name) `IP_NAME_CONCAT(name,`IP_UUID)
module uart (

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<efx:project name="super6502" description="" last_change_date="Sun July 23 2023 16:23:00" location="/home/byron/Projects/super6502/hw/efinix_fpga" sw_version="2023.1.150" last_run_state="pass" last_run_tool="efx_pgm" last_run_flow="bitstream" config_result_in_sync="true" design_ood="sync" place_ood="sync" route_ood="sync" xmlns:efx="http://www.efinixinc.com/enf_proj" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.efinixinc.com/enf_proj enf_proj.xsd">
<efx:project name="super6502" description="" last_change_date="Mon August 21 2023 19:23:14" location="/home/byron/Projects/super6502/hw/efinix_fpga" sw_version="2023.1.150" last_run_state="pass" last_run_tool="efx_pgm" last_run_flow="bitstream" config_result_in_sync="true" design_ood="sync" place_ood="sync" route_ood="sync" xmlns:efx="http://www.efinixinc.com/enf_proj" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.efinixinc.com/enf_proj enf_proj.xsd">
<efx:device_info>
<efx:family name="Trion"/>
<efx:device name="T20F256"/>
@@ -100,7 +100,7 @@
</efx:bitstream_generation>
<efx:debugger>
<efx:param name="work_dir" value="work_dbg" value_type="e_string"/>
<efx:param name="auto_instantiation" value="on" value_type="e_bool"/>
<efx:param name="auto_instantiation" value="off" value_type="e_bool"/>
<efx:param name="profile" value="debug_profile.wizard.json" value_type="e_string"/>
</efx:debugger>
</efx:project>

View File

@@ -1,39 +1,39 @@
CC=../cc65/bin/cl65
CFLAGS=-T -t none -I. --cpu "65C02"
test: CFLAGS=-T -t sim65c02 -I.
LDFLAGS=-C link.ld -m $(NAME).map
SIM=sim65
SIMARGS=-v -c -x 1000000
NAME=bootloader
NAME=bios
TEST_BIN=test.bin
BIN=$(NAME).bin
HEX=$(NAME).hex
FPGA_IMG=../../hw/efinix_fpga/init_hex.mem
EFX_RUN=/home/byron/Software/efinity/2023.1/scripts/efx_run.py
EFX_PRJ=/home/byron/Projects/super6502/hw/efinix_fpga/super6502.xml
LISTS=lists
TESTS=tests
SRCS=$(wildcard *.s) $(wildcard *.c)
SRCS+=$(filter-out $(wildcard tests/*), $(wildcard **/*.s)) $(filter-out $(wildcard tests/*) $(wildcard filesystem/*), $(wildcard **/*.c))
SRCS+=$(filter-out $(wildcard tests/*), $(wildcard **/*.s)) $(filter-out $(wildcard tests/*), $(wildcard **/*.c))
OBJS+=$(patsubst %.s,%.o,$(filter %s,$(SRCS)))
OBJS+=$(patsubst %.c,%.o,$(filter %c,$(SRCS)))
TEST_SRCS=$(wildcard $(TESTS)/*.s) $(wildcard $(TESTS)/*.c)
TEST_OBJS+=$(patsubst %.s,%.o,$(filter %s,$(TEST_SRCS)))
TEST_OBJS+=$(patsubst %.c,%.o,$(filter %c,$(TEST_SRCS)))
TEST_OBJS+=$(filter-out boot.o,$(filter-out main.o,$(filter-out vectors.o,$(OBJS))))
all: $(HEX)
test: $(TEST_BIN)
$(SIM) $(SIMARGS) $(TEST_BIN)
$(TEST_BIN): $(OBJS) $(TEST_OBJS)
$(CC) $(CFLAGS) $(TEST_OBJS) -o $@
$(HEX): $(BIN)
objcopy --input-target=binary --output-target=verilog $(BIN) $(HEX)
cp boot2.bin ../fsdir
cmp $(HEX) $(FPGA_IMG); \
RETVAL=$$?; \
if [ $$RETVAL -eq 0 ]; then \
echo "SAME"; \
else \
echo "NOT SAME"; \
cp bios.hex ../../hw/efinix_fpga/init_hex.mem; \
echo "Update ROM or rebuild FPGA image!"; \
fi
$(BIN): $(OBJS)
@@ -47,10 +47,8 @@ $(BIN): $(OBJS)
$(LISTS):
mkdir -p $(addprefix $(LISTS)/,$(sort $(dir $(SRCS))))
mkdir $(LISTS)/$(sort $(dir $(TEST_SRCS)))
.PHONY: clean
clean:
rm -rf $(OBJS) $(BIN) $(HEX) $(LISTS) $(NAME).map
rm -rf $(TEST_OBJS) $(TEST_BIN)

161
sw/bios/boot2.s Normal file
View File

@@ -0,0 +1,161 @@
.importzp sp, ptr1, ptr2, ptr3, ptr4, tmp1, tmp2, tmp3, sreg, data_start
.autoimport on
.export fatbuf
.feature string_escapes
.MACPACK generic
fatbuf = $A000
filebuf = $B000
.segment "BOOTLOADER"
sectors_per_cluster = $800D
reserved_sectors = $800E
fat_count = $8010
sectors_per_fat = $8024
_start:
lda #<str
ldx #>str
jsr _cputs
; Read root directory entry into fatbuf
lda data_start
ldx data_start + 1
jsr pushax
stz sreg
stz sreg+1
jsr pusheax
lda #<fatbuf
ldx #>fatbuf
jsr pushax
lda #<ptr1
ldx #>ptr1
jsr _SD_readSingleBlock
lda #<fatbuf
ldx #>fatbuf
jsr _SD_printBuf
lda #$20 ; Start at first directory entry (first is a disk label)
sta ptr3
lda #>fatbuf
sta ptr3 + 1
ldy #$0b ; look for attributes
@1: lda (ptr3),y
cmp #$0f ; if attribute is 0xf, this is a lfn
bne @2 ; if not an lfn, then try to read filename
@next: clc ; otherwise, go to the next entry (+0x20)
lda ptr3
adc #$20
sta ptr3
bcc @4
inc ptr3 + 1
@4: lda #<word_str
ldx #>word_str
jsr pushax
lda ptr3
ldx ptr3 + 1
pha
phx
jsr pushax
phy
ldy #$4
jsr _cprintf
ply
plx
stx ptr3 + 1
pla
sta ptr3
bra @1
@2: ldy #11 ; ignore the attributes. Write null to make a string
lda #$00
sta (ptr3),y
lda ptr3 ; store address of the filename string on the stack
pha
ldx ptr3 + 1
phx
jsr _cputs ; print out short filenames as we read them
lda #$0d
jsr _cputc
lda #$0a
jsr _cputc
lda #<kernel_str ; load the string "KERNEL O65"
ldx #>kernel_str
jsr pushax
plx ; then push the string we read earlier
pla
jsr _strcmp
bne @next ; if they are not equal then try next entry
lda #<_good ; print match if we found it
ldx #>_good
jsr _cputs ; otherwise continue on
lda #<word_str
ldx #>word_str
jsr pushax
lda ptr3
pha
lda ptr3 + 1
pha
ldy #$1d ; load file size (256)
lda (ptr3),y
lsr ; divide by 2 to get file size (512)
jsr pusha0
ldy #$4
jsr _cprintf
pla
sta ptr3 + 1
pla
sta ptr3
ldy #$1b ; load high byte of low first cluster
lda (ptr3),y
tax
dey
lda (ptr3),y ; load low byte of low first cluster
sec
sbc #$02 ; don't handle carry, assume low byte is not 0 or 1
ldx data_start + 1 ; load x as high data start
asl ; multiply cluster num (minus 2) by 8
asl
asl
clc
adc data_start ; add that to low data start
bcc @5 ; handle carry
inx
@5: stz sreg
stz sreg+1
phx
pha
jsr pusheax
lda #<filebuf
ldx #>filebuf
jsr pushax
lda #<ptr1
ldx #>ptr1
jsr _SD_readSingleBlock
lda #<filebuf
ldx #>filebuf
jsr _SD_printBuf
@end: bra @end
str: .asciiz "boot2\r\n"
kernel_str: .asciiz "KERNEL O65"
_good: .asciiz "Found KERNEL\r\n"
word_str: .asciiz "Word Value: %x\r\n"

195
sw/bios/bootloader.s Normal file
View File

@@ -0,0 +1,195 @@
.importzp sp, ptr1, ptr2, ptr3, ptr4, tmp1, tmp2, tmp3, sreg
.exportzp data_start
.autoimport on
.feature string_escapes
.MACPACK generic
.MACPACK longbranch
_console_clear = $0
_console_read_char = $2
_console_write_char = $4
_sd_readblock = $6
sectors_per_cluster = $800D
reserved_sectors = $800E
fat_count = $8010
sectors_per_fat = $8024
buf = $8200
addrh = $0000
addrl = $0000
.zeropage
data_start: .res 2
.segment "BOOTSECTOR"
_start:
jmp _main
.byte "SUPR6502"
_preamble:
.res (11+_start-_preamble)
_bpb: .res 60
_main:
lda #<str
ldx #>str
jsr _cputs
lda fat_count
cmp #$2
jne @fail
lda sectors_per_fat
asl
pha
lda sectors_per_fat + 1
rol
tax
pla
adc reserved_sectors
bcc @a
inx
@a: sta data_start
stx data_start + 1
jsr pushax
stz sreg
stz sreg+1
jsr pusheax
lda #<buf
ldx #>buf
jsr pushax
lda #<ptr1
ldx #>ptr1
jsr _SD_readSingleBlock
lda #<buf
ldx #>buf
jsr _SD_printBuf
lda #$20 ; Start at first directory entry (first is a disk label)
sta ptr3
lda #>buf
sta ptr3 + 1
ldy #$0b ; look for attributes
@1: lda (ptr3),y
cmp #$0f ; if attribute is 0xf, this is a lfn
bne @2 ; if not an lfn, then try to read filename
clc ; otherwise, go to the next entry (+0x20)
lda ptr3
adc #$20
sta ptr3
bra @1
@2: ldy #11 ; ignore the attributes. Write null to make a string
lda #$00
sta (ptr3),y
lda ptr3 ; store address of the filename string on the stack
pha
ldx ptr3 + 1
phx
lda #<_boot2_str ; load the string "BOOT2 BIN"
ldx #>_boot2_str
jsr pushax
plx ; then push the string we read earlier
pla
jsr _strcmp
bne @fail ; if they are not equal then fail
lda #<_good ; TODO: We should try the next entry
ldx #>_good
jsr _cputs ; otherwise continue on
ldy #$1b ; load the high byte of the low first cluster
lda (ptr3),y
tax
dey
lda (ptr3),y ; load the low byte of the low first cluster
sec
sbc #$02 ; don't handle carry, assume low byte is not 0 or 1
ldx data_start + 1 ; load x as high data start
asl ; multiply cluster num (minus 2) by 8
asl
asl
clc
adc data_start ; add that to low data start
bcc @3 ; handle carry
inx
@3: stz sreg
stz sreg+1
phx
pha
jsr pusheax
lda #<buf
ldx #>buf
jsr pushax
lda #<ptr1
ldx #>ptr1
jsr _SD_readSingleBlock
stz sreg
stz sreg+1
pla
plx
inc
jsr pusheax
lda #<buf
ldx #>buf
inx
inx
jsr pushax
lda #<ptr1
ldx #>ptr1
jsr _SD_readSingleBlock
jmp buf
bra @end
; Now we have the cluster number of the bootloader (3)
; this means we need to read from address 00ef_e000 + ((3 -2) * 8 * 512)
; 00eff000 is the address we want, which is efe000 + 4096
@fail: lda #<_fail
ldx #>_fail
jsr _cputs
@end: bra @end
str: .asciiz "boot\r\n"
_boot2_str: .asciiz "BOOT2 BIN"
_fail: .asciiz "not bootloader\r\n"
_good: .asciiz "found bootloader!\r\n"
_cluster: .asciiz "cluster: %lx\r\n"
_addr: .asciiz "addr: %x\r\n"
_end:
.res (440+_start-_end)
.res 6
.res 16
.res 16
.res 16
.res 16
.byte $55
.byte $AA

View File

@@ -7,9 +7,9 @@
; Checks for a BRK instruction and returns from all valid interrupts.
.import _handle_irq
.import _cputc, _clrscr
.export _irq_int, _nmi_int
.export _irq_get_status, _irq_set_status
.include "io.inc65"
@@ -45,14 +45,56 @@ irq: PLA ; Restore accumulator contents
; ---------------------------------------------------------------------------
; BRK detected, stop
break: JMP break ; If BRK is detected, something very bad
; has happened, so stop running
break:
pla
plx
jmp (bios_table,x)
_irq_get_status:
lda IRQ_STATUS
ldx #$00
rts
_irq_set_status:
sta IRQ_STATUS
rts
bios_table:
.addr _console_clear
.addr _console_read_char
.addr _console_write_char
_console_clear:
jsr _clrscr
rti
_console_read_char:
; not supported
rti
_console_write_char:
jsr _cputc
rti
; What functions do we need?
; UART
; clear
; write character
; read character
; DISK
; init (or should it just init on boot?)
; read sector into memory
; FS
; init (if disk init succeeds, should it always try?)
; find add
; I think that is all we need for now?
; How do we call the functions?
; we have to call `brk` to trigger the interrupt
; in any of the three registers we can have arguments
; or we could have them pushed to the stack, assuming
; the stack is in the same location
; Or you could pass a pointer which points to an array
; of arguments
; for things like clear, read/write character, and init you don't
; need any arguments.
; jump table index needs to be in x, but also needs to be a multiple
; of 2.

View File

@@ -276,56 +276,58 @@ void SD_sendStatus(uint8_t *res)
token = 0x0X - Data error
token = 0xFF - timeout
*******************************************************************************/
uint8_t SD_readSingleBlock(uint32_t addr, uint8_t *buf, uint8_t *token)
{
uint8_t res1, read;
uint16_t readAttempts;
uint16_t i;
// uint8_t SD_readSingleBlock(uint32_t addr, uint8_t *buf, uint8_t *token)
// {
// uint8_t res1, read;
// uint16_t readAttempts;
// uint16_t i;
// set token to none
*token = 0xFF;
// // set token to none
// *token = 0xFF;
// assert chip select
spi_exchange(0xFF);
spi_select(0);
spi_exchange(0xFF);
// // assert chip select
// spi_exchange(0xFF);
// spi_select(0);
// spi_exchange(0xFF);
// send CMD17
SD_command(CMD17, addr, CMD17_CRC);
// // send CMD17
// SD_command(CMD17, addr, CMD17_CRC);
// read R1
res1 = SD_readRes1();
// // read R1
// res1 = SD_readRes1();
// if response received from card
if(res1 != 0xFF)
{
// wait for a response token (timeout = 100ms)
readAttempts = 0;
while(++readAttempts != SD_MAX_READ_ATTEMPTS)
if((read = spi_exchange(0xFF)) != 0xFF) break;
// // if response received from card
// if(res1 != 0xFF)
// {
// // wait for a response token (timeout = 100ms)
// readAttempts = 0;
// while(++readAttempts != SD_MAX_READ_ATTEMPTS)
// if((read = spi_exchange(0xFF)) != 0xFF) break;
// if response token is 0xFE
if(read == SD_START_TOKEN)
{
// read 512 byte block
for(i = 0; i < SD_BLOCK_LEN; i++) *buf++ = spi_exchange(0xFF);
// cprintf("read attempts: %d\r\n", readAttempts);
// read 16-bit CRC
spi_exchange(0xFF);
spi_exchange(0xFF);
}
// // if response token is 0xFE
// if(read == SD_START_TOKEN)
// {
// // read 512 byte block
// for(i = 0; i < SD_BLOCK_LEN; i++) *buf++ = spi_exchange(0xFF);
// set token to card response
*token = read;
}
// // read 16-bit CRC
// spi_exchange(0xFF);
// spi_exchange(0xFF);
// }
// deassert chip select
spi_exchange(0xFF);
spi_deselect(0);
spi_exchange(0xFF);
// // set token to card response
// *token = read;
// }
return res1;
}
// // deassert chip select
// spi_exchange(0xFF);
// spi_deselect(0);
// spi_exchange(0xFF);
// return res1;
// }
#define SD_MAX_WRITE_ATTEMPTS 3907

View File

@@ -6,8 +6,9 @@
.export _SD_readBytes
.export _SD_powerUpSeq
.export _res1_cmd
.export _SD_readSingleBlock
.importzp sp, ptr1
.importzp sp, ptr1, ptr2, ptr3, ptr4, tmp1, tmp2, tmp3
.autoimport on
@@ -27,7 +28,7 @@
dey
arg_loop: ; send ARG
lda (sp),y
lda (sp),y ; is this sending only 3?
jsr _spi_exchange
dey
bpl arg_loop
@@ -187,4 +188,116 @@ read:
dex ; 2
bne @L1 ; 3
rts
.endproc
; ;uint8_t SD_readSingleBlock(uint32_t addr, uint8_t *buf, uint8_t *token)
.proc _SD_readSingleBlock: near
; token address in a/x
; buf address next on stack
; sd address above that
; ptr2 = *token
sta ptr2
stx ptr2 + 1
lda #$ff
sta (ptr2)
; ptr1 = *buf
jsr popptr1
; 4 bytes on stack are addr
; Move addr down on the stack
lda sp
sta ptr3
lda sp + 1
sta ptr3 + 1
; find a way to do this in a loop?
jsr decsp1
ldy #$0
lda (ptr3),y
sta (sp),y
iny
lda (ptr3),y
sta (sp),y
iny
lda (ptr3),y
sta (sp),y
iny
lda (ptr3),y
sta (sp),y
lda #$ff
jsr _spi_exchange
lda #$00 ; this gets ignored anyway
jsr _spi_select
lda #$ff
jsr _spi_exchange
; push cmd17
lda #$11
ldy #$4
sta (sp),y
; crc, 0
lda #$00
jsr _SD_command ; rely on command to teardown stack
jsr _SD_readRes1
cmp #$ff ; if 0xFF then you failed
beq end
sta tmp3 ; tmp3 = read
; y = read_attempts
ldy #$0
resp_loop:
lda #$ff
jsr _spi_exchange
sta tmp2 ; tmp2 = read
lda tmp2
cmp #$ff
bne got_resp
iny
bne resp_loop
bra after_read
got_resp:
ldx #$2
ldy #$00
load_loop:
lda #$ff
jsr _spi_exchange
sta (ptr1)
inc ptr1
bne @2
inc ptr1 + 1
@2: dey
bne load_loop
ldy #$00
dex
bne load_loop
lda #$ff
jsr _spi_exchange
lda #$ff
jsr _spi_exchange
after_read:
lda tmp2
sta (ptr2)
lda tmp3
end:
pha
lda #$ff
jsr _spi_exchange
lda #$00 ; this gets ignored anyway
jsr _spi_deselect
lda #$ff
jsr _spi_exchange
pla
rts
.endproc

View File

@@ -0,0 +1,26 @@
#include <conio.h>
#include "sd_print.h"
#include "sd_card.h"
void SD_printBuf(uint8_t *buf)
{
uint8_t colCount = 0;
uint16_t i;
for(i = 0; i < SD_BLOCK_LEN; i++)
{
cprintf("%2x", *buf++);
if(colCount == 31)
{
cputs("\r\n");
colCount = 0;
}
else
{
cputc(' ');
colCount++;
}
}
cputs("\r\n");
}

View File

@@ -1,7 +1,10 @@
MEMORY
{
ZP: start = $0, size = $100, type = rw, define = yes;
SDRAM: start = $200, size = $7cf0, type = rw, define = yes;
KERNEL: start = $1000, size = $7000, type = rw, define = yes;
SDRAM: start = $9200, size = $4d00, type = rw, define = yes;
BOOTSECTOR: start = $8000, size = $200, type = rw, define = yes, file = "bootloader.bin";
BOOTLOADER: start = $8200, size = $1000, type = rw, define = yes, file = "boot2.bin";
ROM: start = $F000, size = $1000, file = %O;
}
@@ -15,6 +18,8 @@ SEGMENTS {
CODE: load = ROM, type = ro;
RODATA: load = ROM, type = ro;
VECTORS: load = ROM, type = ro, start = $FFFA;
BOOTSECTOR: load = BOOTSECTOR, type = rw, start = $8000;
BOOTLOADER: load = BOOTLOADER, type = rw;
}
FEATURES {

51
sw/bios/main.c Normal file
View File

@@ -0,0 +1,51 @@
#include <stdint.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
#include "devices/board_io.h"
#include "devices/uart.h"
#include "devices/sd_card.h"
#include "devices/sd_print.h"
#define KERNEL_LOAD_ADDR 0xD000
//uint8_t buf[512];
uint8_t *buf = (uint8_t*)0x8000;
int main() {
// array to hold responses
uint8_t res[5], token;
uint32_t addr = 0x00000000;
uint16_t i;
cputs("Start\r\n");
// initialize sd card
if(SD_init() != SD_SUCCESS)
{
cputs("Error\r\n");
}
else
{
cputs("Success\r\n");
res[0] = SD_readSingleBlock(addr, buf, &token);
// if no error, print buffer
if((res[0] == 0x00) && (token == SD_START_TOKEN))
SD_printBuf(buf);
//else if error token received, print
else if(!(token & 0xF0))
{
cputs("Error\r\n");
} else {
cprintf("bad token: %x\r\n", token);
}
__asm__ ("jmp (%v)", buf);
}
while(1) ;
}

View File

@@ -1,48 +0,0 @@
; ---------------------------------------------------------------------------
; interrupt.s
; ---------------------------------------------------------------------------
;
; Interrupt handler.
;
; Checks for a BRK instruction and returns from all valid interrupts.
.import _handle_irq
.export _irq_int, _nmi_int
.include "io.inc65"
.segment "CODE"
.PC02 ; Force 65C02 assembly mode
; ---------------------------------------------------------------------------
; Non-maskable interrupt (NMI) service routine
_nmi_int: RTI ; Return from all NMI interrupts
; ---------------------------------------------------------------------------
; Maskable interrupt (IRQ) service routine
_irq_int: PHX ; Save X register contents to stack
TSX ; Transfer stack pointer to X
PHA ; Save accumulator contents to stack
INX ; Increment X so it points to the status
INX ; register value saved on the stack
LDA $100,X ; Load status register contents
AND #$10 ; Isolate B status bit
BNE break ; If B = 1, BRK detected
; ---------------------------------------------------------------------------
; IRQ detected, return
irq: PLA ; Restore accumulator contents
PLX ; Restore X register contents
jsr _handle_irq ; Handle the IRQ
RTI ; Return from all IRQ interrupts
; ---------------------------------------------------------------------------
; BRK detected, stop
break: JMP break ; If BRK is detected, something very bad
; has happened, so stop running

View File

@@ -1,188 +0,0 @@
#include <conio.h>
#include "sd_print.h"
#include "sd_card.h"
/*
void SD_printR1(uint8_t res)
{
if(res == 0xFF)
{ cputs("\tNo response\r\n"); return; }
if(res & 0x80)
{ cputs("\tError: MSB = 1\r\n"); return; }
if(res == 0)
{ cputs("\tCard Ready\r\n"); return; }
if(PARAM_ERROR(res))
cputs("\tParameter Error\r\n");
if(ADDR_ERROR(res))
cputs("\tAddress Error\r\n");
if(ERASE_SEQ_ERROR(res))
cputs("\tErase Sequence Error\r\n");
if(CRC_ERROR(res))
cputs("\tCRC Error\r\n");
if(ILLEGAL_CMD(res))
cputs("\tIllegal Command\r\n");
if(ERASE_RESET(res))
cputs("\tErase Reset Error\r\n");
if(IN_IDLE(res))
cputs("\tIn Idle State\r\n");
}
*/
/*
void SD_printR2(uint8_t *res)
{
SD_printR1(res[0]);
if(res[0] == 0xFF) return;
if(res[1] == 0x00)
cputs("\tNo R2 Error\r\n");
if(OUT_OF_RANGE(res[1]))
cputs("\tOut of Range\r\n");
if(ERASE_PARAM(res[1]))
cputs("\tErase Parameter\r\n");
if(WP_VIOLATION(res[1]))
cputs("\tWP Violation\r\n");
if(CARD_ECC_FAILED(res[1]))
cputs("\tECC Failed\r\n");
if(CC_ERROR(res[1]))
cputs("\tCC Error\r\n");
if(ERROR(res[1]))
cputs("\tError\r\n");
if(WP_ERASE_SKIP(res[1]))
cputs("\tWP Erase Skip\r\n");
if(CARD_LOCKED(res[1]))
cputs("\tCard Locked\r\n");
}
*/
/*
void SD_printR3(uint8_t *res)
{
SD_printR1(res[0]);
if(res[0] > 1) return;
cputs("\tCard Power Up Status: ");
if(POWER_UP_STATUS(res[1]))
{
cputs("READY\r\n");
cputs("\tCCS Status: ");
if(CCS_VAL(res[1])){ cputs("1\r\n"); }
else cputs("0\r\n");
}
else
{
cputs("BUSY\r\n");
}
cputs("\tVDD Window: ");
if(VDD_2728(res[3])) cputs("2.7-2.8, ");
if(VDD_2829(res[2])) cputs("2.8-2.9, ");
if(VDD_2930(res[2])) cputs("2.9-3.0, ");
if(VDD_3031(res[2])) cputs("3.0-3.1, ");
if(VDD_3132(res[2])) cputs("3.1-3.2, ");
if(VDD_3233(res[2])) cputs("3.2-3.3, ");
if(VDD_3334(res[2])) cputs("3.3-3.4, ");
if(VDD_3435(res[2])) cputs("3.4-3.5, ");
if(VDD_3536(res[2])) cputs("3.5-3.6");
cputs("\r\n");
}
*/
/*
void SD_printR7(uint8_t *res)
{
SD_printR1(res[0]);
if(res[0] > 1) return;
cputs("\tCommand Version: ");
cprintf("%x", CMD_VER(res[1]));
cputs("\r\n");
cputs("\tVoltage Accepted: ");
if(VOL_ACC(res[3]) == VOLTAGE_ACC_27_33) {
cputs("2.7-3.6V\r\n");
} else if(VOL_ACC(res[3]) == VOLTAGE_ACC_LOW) {
cputs("LOW VOLTAGE\r\n");
} else if(VOL_ACC(res[3]) == VOLTAGE_ACC_RES1) {
cputs("RESERVED\r\n");
} else if(VOL_ACC(res[3]) == VOLTAGE_ACC_RES2) {
cputs("RESERVED\r\n");
} else {
cputs("NOT DEFINED\r\n");
}
cputs("\tEcho: ");
cprintf("%x", res[4]);
cputs("\r\n");
}
*/
/*
void SD_printCSD(uint8_t *buf)
{
cputs("CSD:\r\n");
cputs("\tCSD Structure: ");
cprintf("%x", (buf[0] & 0b11000000) >> 6);
cputs("\r\n");
cputs("\tTAAC: ");
cprintf("%x", buf[1]);
cputs("\r\n");
cputs("\tNSAC: ");
cprintf("%x", buf[2]);
cputs("\r\n");
cputs("\tTRAN_SPEED: ");
cprintf("%x", buf[3]);
cputs("\r\n");
cputs("\tDevice Size: ");
cprintf("%x", buf[7] & 0b00111111);
cprintf("%x", buf[8]);
cprintf("%x", buf[9]);
cputs("\r\n");
}
*/
void SD_printBuf(uint8_t *buf)
{
uint8_t colCount = 0;
uint16_t i;
for(i = 0; i < SD_BLOCK_LEN; i++)
{
cprintf("%2x", *buf++);
if(colCount == 19)
{
cputs("\r\n");
colCount = 0;
}
else
{
cputc(' ');
colCount++;
}
}
cputs("\r\n");
}
/*
void SD_printDataErrToken(uint8_t token)
{
if(token & 0xF0)
cputs("\tNot Error token\r\n");
if(SD_TOKEN_OOR(token))
cputs("\tData out of range\r\n");
if(SD_TOKEN_CECC(token))
cputs("\tCard ECC failed\r\n");
if(SD_TOKEN_CC(token))
cputs("\tCC Error\r\n");
if(SD_TOKEN_ERROR(token))
cputs("\tError\r\n");
}
*/

View File

@@ -1,208 +0,0 @@
#include <conio.h>
#include <string.h>
#include <stdlib.h>
#include "fat.h"
#include "devices/sd_card.h"
uint8_t fat_buf[512];
static uint32_t fat_end_of_chain;
static full_bpb_t bpb;
static uint32_t data_region_start;
void fat_init(){
int i;
sd_readblock(0, fat_buf);
memcpy(&bpb, &fat_buf[11], sizeof(full_bpb_t));
sd_readblock(1, fat_buf);
sd_readblock(32, fat_buf);
data_region_start = bpb.reserved_sectors + bpb.fat_count*bpb.sectors_per_fat_32;
sd_readblock(bpb.reserved_sectors, fat_buf);
//uncomment to view start of FAT
/*
for (i = 0; i < FAT_CLUSTERS_PER_SECTOR; i++) {
cprintf("%lx ", ((uint32_t*)fat_buf)[i]);
}
cprintf("\n\n");
*/
fat_end_of_chain = ((uint32_t*)fat_buf)[1] & FAT_EOC_CLUSTERMASK;
cprintf("End of chain indicator: %lx\n", fat_end_of_chain);
}
// make sure you have enough space.
void fat_read_cluster(uint16_t cluster, uint8_t* buf) {
uint8_t i;
for (i = 0; i < bpb.sectors_per_cluster; i++) {
sd_readblock(data_region_start + i + (cluster - 2) * 8, buf+i*bpb.bytes_per_sector);
}
}
uint32_t fat_get_chain_value(uint16_t cluster) {
sd_readblock(bpb.reserved_sectors, fat_buf);
return ((uint32_t*)fat_buf)[cluster];
}
//the dentry is a double pointer because we need to increment it.
void fat_parse_vfat_filenamename(vfat_dentry_t** vfat_dentry, char* name, uint32_t cluster) {
uint8_t i;
uint8_t overflows;
uint8_t done;
char* shift_name;
uint8_t sequence_number = (*vfat_dentry)->sequence_number;
overflows = 0;
for (;;){
shift_name = name + 13*((sequence_number & FAT_LFN_ENTRY_MASK) - 1);
done = 0;
for(i = 0; i < 5; i++) {
shift_name[i] = (*vfat_dentry)->filename0[i];
if (!shift_name[i]) {
done = 1;
break;
}
}
if (!done) {
for(i = 0; i < 6; i++) {
shift_name[i+5] = (*vfat_dentry)->filename1[i];
if (!shift_name[i+5]) {
done = 1;
break;
}
}
}
if (!done) {
for(i = 0; i < 2; i++) {
shift_name[i+11] = (*vfat_dentry)->filename2[i];
if (!shift_name[i+11]) {
done = 1;
break;
}
}
}
if ((sequence_number & FAT_LFN_ENTRY_MASK) == 1) {
break;
} else {
do {
(*vfat_dentry)++;
if ((uint8_t*)*vfat_dentry >= fat_buf + sizeof(fat_buf)) {
overflows++;
if (overflows == bpb.sectors_per_cluster) {
cprintf("Too many overflows, go back to fat!\n"); //TODO this
return;
}
sd_readblock(data_region_start + (cluster - 2) * 8 + overflows, fat_buf);
*vfat_dentry = (vfat_dentry_t*)fat_buf;
}
} while((*vfat_dentry)->sequence_number == 0xe5);
sequence_number = (*vfat_dentry)->sequence_number;
}
}
}
uint32_t fat_find_cluster_num(char* name, uint32_t cluster) {
vfat_dentry_t* vfat_dentry;
dos_dentry_t* dos_dentry;
char* vfat_name;
cprintf("Looking for file %s\n", name);
sd_readblock(data_region_start + (cluster - 2) * 8, fat_buf);
vfat_dentry = (vfat_dentry_t*)fat_buf;
vfat_name = (char*)malloc(FAT_MAX_FILE_NAME);
while(vfat_dentry->sequence_number == 0xe5)
vfat_dentry++;
vfat_name[0] = '\0';
while(vfat_dentry->sequence_number) {
fat_parse_vfat_filenamename(&vfat_dentry, vfat_name, cluster);
cprintf("Parsed filename: %s\n", vfat_name);
if (!strcmp(vfat_name, name)) { //TODO this is probably unsafe, use strncmp
cprintf("Found file %s\n", vfat_name);
break;
} else {
vfat_dentry += 2;
while(vfat_dentry->sequence_number == 0xe5)
vfat_dentry++;
}
}
free(vfat_name);
if (!vfat_dentry->sequence_number) {
cprintf("File not found.\n");
return -1;
}
dos_dentry = (dos_dentry_t*) vfat_dentry + 1; //dos entry follows last vfat entry
cluster = ((uint32_t)dos_dentry->first_cluster_h << 16) + dos_dentry->first_cluster_l;
cprintf("Cluster: %ld\n", cluster);
return cluster;
}
uint16_t fat_parse_path_to_cluster(char* filename) {
//basically start at the root folder and search through it
int i;
int len;
uint8_t dirs = 0;
char* spaced_filename;
char* fragment;
uint32_t cluster = 2; //root chain is chain 2
if (filename[0] != '/') {
cprintf("Filename does not begin with '/'\n");
return 0;
}
filename++;
len = strlen(filename);
spaced_filename = (char*)malloc(len+1); //need to account for null byte
for (i = 0; i <= len; i++) {
if (filename[i] == '/') {
spaced_filename[i] = '\0';
dirs++;
} else {
spaced_filename[i] = filename[i];
}
}
fragment = spaced_filename;
cprintf("Dirs: %d\n", dirs);
for (i = 0; i <= dirs; i++) {
cprintf("Fragment: %s\n", fragment);
cluster = fat_find_cluster_num(fragment, cluster);
fragment = spaced_filename + strlen(fragment) + 1;
}
free(spaced_filename);
return cluster;
}

View File

@@ -1,122 +0,0 @@
#ifndef _FAT_H
#define _FAT_H
#include <stdint.h>
extern uint8_t fat_buf[];
#define FAT_MAX_FILE_NAME 255
#define FAT_CLUSTERS_PER_SECTOR 128
#define FAT_CLUSTERMASK 0x0fffffff
#define FAT_EOC_CLUSTERMASK 0x0ffffff8
#define FAT_LAST_LFN_MASK (1 << 6)
#define FAT_LFN_ENTRY_MASK 0x1f
typedef struct {
uint16_t bytes_per_sector;
uint8_t sectors_per_cluster;
uint16_t reserved_sectors;
uint8_t fat_count;
uint16_t max_dir_entries;
uint16_t total_sector_count;
uint8_t media_descriptor;
uint16_t sectors_per_fat;
} dos_2_bpb_t;
typedef struct {
dos_2_bpb_t bpb2;
uint16_t sectors_per_track;
uint16_t head_count;
uint32_t hidden_sector_count;
uint32_t logical_sector_count;
uint32_t sectors_per_fat;
uint16_t extended_flags;
uint16_t version;
uint32_t root_cluster;
uint16_t system_information;
uint16_t backup_boot_sector;
uint8_t reserved[12];
} dos_3_bpb_t;
typedef struct {
dos_3_bpb_t bpb3;
uint8_t drive_num;
uint8_t reserved;
uint8_t extended_signature;
uint32_t volume_id;
uint8_t partition_label[11];
uint8_t filesystem_type[8];
} ebpb_t;
typedef struct {
uint16_t bytes_per_sector;
uint8_t sectors_per_cluster;
uint16_t reserved_sectors;
uint8_t fat_count;
uint16_t max_dir_entries;
uint16_t total_sector_count;
uint8_t media_descriptor;
uint16_t sectors_per_fat_16;
uint16_t sectors_per_track;
uint16_t head_count;
uint32_t hidden_sector_count;
uint32_t logical_sector_count;
uint32_t sectors_per_fat_32;
uint16_t extended_flags;
uint16_t version;
uint32_t root_cluster;
uint16_t system_information;
uint16_t backup_boot_sector;
uint8_t reserved[12];
uint8_t drive_num;
uint8_t reserved2;
uint8_t extended_signature;
uint32_t volume_id;
uint8_t partition_label[11];
uint8_t filesystem_type[8];
} full_bpb_t;
typedef struct {
uint32_t sig;
uint8_t reserved[480];
uint32_t sig2;
uint32_t free_data_clusters;
uint32_t last_allocated_data_cluster;
uint32_t reserved2;
uint32_t sig3;
} fs_info_sector_t;
typedef struct {
uint8_t sequence_number;
uint16_t filename0[5];
uint8_t attributes;
uint8_t type;
uint8_t checksum;
uint16_t filename1[6];
uint16_t reserved;
uint16_t filename2[2];
} vfat_dentry_t;
typedef struct {
uint8_t filename[8];
uint8_t extension[3];
uint8_t attributes;
uint8_t reserved;
uint8_t create_time_10ms;
uint32_t create_date;
uint16_t access_date;
uint16_t first_cluster_h;
uint32_t modify_cluster;
uint16_t first_cluster_l;
uint32_t file_size;
} dos_dentry_t;
void fat_init();
uint16_t fat_parse_path_to_cluster(char* filename);
void fat_read_cluster(uint16_t cluster, uint8_t* buf);
uint32_t fat_get_chain_value(uint16_t cluster);
#endif

View File

@@ -1,28 +0,0 @@
#include <conio.h>
#include "o65.h"
void o65_print_option(o65_opt_t* opt) {
int i;
cprintf("Option Length: %d\n", opt->olen);
cprintf("Option Type: %x ", opt->type);
switch (opt->type) {
case O65_OPT_FILENAME: cprintf("Filename\n"); break;
case O65_OPT_OS: cprintf("OS\n"); break;
case O65_OPT_ASSEMBLER: cprintf("Assembler\n"); break;
case O65_OPT_AUTHOR: cprintf("Author\n"); break;
case O65_OPT_DATE: cprintf("Creation Date\n"); break;
default: cprintf("Invalid\n"); break;
}
if (opt->type != O65_OPT_OS) {
for (i = 0; i < opt->olen - 2; i++) {
cprintf("%c", opt->data[i]);
}
} else {
cprintf("%x", opt->data[0]);
}
cprintf("\n\n");
}

View File

@@ -1,65 +0,0 @@
#ifndef _O65_H
#define _O65_H
#include <stdint.h>
#define O65_NON_C64 0x0001
#define O65_MAGIC_0 0x6f
#define O65_MAGIC_1 0x36
#define O65_MAGIC_2 0x35
#define O65_OPT_FILENAME 0
#define O65_OPT_OS 1
#define O65_OPT_ASSEMBLER 2
#define O65_OPT_AUTHOR 3
#define O65_OPT_DATE 4
#define O65_OS_OSA65 1
#define O65_OS_LUNIX 2
#define O65_OS_CC65 3
#define O65_OS_OPENCBM 4
#define O65_OS_SUPER6502 5
typedef union {
struct {
int cpu : 1;
int reloc : 1;
int size : 1;
int obj : 1;
int simple : 1;
int chain : 1;
int bsszero : 1;
int cpu2 : 4;
int align : 2;
};
uint16_t _mode;
} o65_mode_t;
typedef struct {
uint16_t c64_marker;
uint8_t magic[3];
uint8_t version;
o65_mode_t mode;
uint16_t tbase;
uint16_t tlen;
uint16_t dbase;
uint16_t dlen;
uint16_t bbase;
uint16_t blen;
uint16_t zbase;
uint16_t zlen;
uint16_t stack;
} o65_header_t;
typedef struct {
uint8_t olen;
uint8_t type;
uint8_t data[1]; //This is actually variable length
} o65_opt_t;
void o65_print_option(o65_opt_t* opt);
#endif

View File

@@ -1,81 +0,0 @@
#include <stdint.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
#include "devices/board_io.h"
#include "devices/uart.h"
#include "devices/sd_card.h"
#include "devices/sd_print.h"
#include "filesystem/fat.h"
#define KERNEL_LOAD_ADDR 0xD000
uint8_t buf[512];
int main() {
// array to hold responses
uint8_t res[5], token;
uint32_t addr = 0x00000000;
uint16_t i;
cputs("Start\r\n");
// initialize sd card
if(SD_init() != SD_SUCCESS)
{
cputs("Error\r\n");
}
else
{
cputs("Success\r\n");
// read sector 0
cputs("\r\nReading sector: 0x");
// ((uint8_t)(addr >> 24));
// cprintf("%x", (uint8_t)(addr >> 16));
// cprintf("%x", (uint8_t)(addr >> 8));
// cprintf("%x", (uint8_t)addr);
res[0] = SD_readSingleBlock(addr, buf, &token);
cputs("\r\nResponse:\r\n");
//SD_printR1(res[0]);
// if no error, print buffer
if((res[0] == 0x00) && (token == SD_START_TOKEN))
SD_printBuf(buf);
//else if error token received, print
else if(!(token & 0xF0))
{
cputs("Error token:\r\n");
//SD_printDataErrToken(token);
}
// update address to 0x00000100
// addr = 0x00000100;
// // fill buffer with 0x55
// for(i = 0; i < 512; i++) buf[i] = 0x55;
// cputs("Writing 0x55 to sector: 0x");
// cprintf("%x", (uint8_t)(addr >> 24));
// cprintf("%x", (uint8_t)(addr >> 16));
// cprintf("%x", (uint8_t)(addr >> 8));
// cprintf("%x", (uint8_t)addr);
// // write data to sector
// res[0] = SD_writeSingleBlock(addr, buf, &token);
// cputs("\r\nResponse:\r\n");
// //SD_printR1(res[0]);
// // if no errors writing
// if(res[0] == 0x00)
// {
// if(token == SD_DATA_ACCEPTED)
// cputs("Write successful\r\n");
// }
}
while(1) ;
}

View File

@@ -1,89 +0,0 @@
#include <stdio.h>
#include "devices/board_io.h"
#include "devices/uart.h"
#include "devices/interrupt.h"
int main(void)
{
int retval = 0;
int i;
printf("\nStarting tests...\n\n");
printf("Testing hex_set_8...\n");
for (i = 0; i < 3; i++) {
if (hex_set_8(i+1, i)) {
printf("Failed to write to idx %d!\n", i);
retval++;
}
if (*(uint8_t*)0x7ff0+i != i+1) {
printf("Incorrect value at idx %d!\n", i);
retval++;
}
}
if (!hex_set_8(0xab, 3)) {
printf("Writing to idx 3 should fail!\n");
retval++;
}
printf("Done!\n\n");
printf("Testing hex_set_16...\n");
if (hex_set_16(0xabcd)){
printf("Failed to write!\n");
}
if (*(uint16_t*)0x7ff0 != 0xabcd) {
printf("Incorrect value!\n", i);
retval++;
}
printf("Done!\n\n");
printf("Testing hex_set_24...\n");
if (hex_set_24(0xabcdef)){
printf("Failed to write!\n");
}
if (*(uint16_t*)0x7ff0 != 0xcdef && *(uint8_t*)0x7ff2 != 0xab) {
printf("Incorrect value!\n", i);
retval++;
}
printf("Done!\n\n");
printf("Testing hex_enable...\n");
hex_enable(0xa5);
if (*(uint8_t*)0x7ff3 != 0xa5) {
printf("Incorrect value!\n", i);
retval++;
}
printf("Done!\n\n");
printf("Testing uart_txb_block...\n");
*(uint8_t*)0x7ff5 = 0;
uart_txb_block(0xa5);
if (*(uint8_t*)0x7ff4 != 0xa5) {
printf("Incorrect value!\n", i);
retval++;
}
printf("Done!\n\n");
printf("Testing uart_status...\n");
*(uint8_t*)0x7ff5 = 0xa5;
if (uart_status() != 0xa5) {
printf("Incorrect value!\n", i);
retval++;
}
printf("Done!\n\n");
printf("Testing irq_get_status...\n");
*(uint8_t*)0x7fff = 0xa5;
if (irq_get_status() != 0xa5) {
printf("Incorrect value!\n", i);
retval++;
}
printf("Done!\n\n");
return retval != 0;
}

Submodule sw/cc65 updated: 9dc33cff22...09e6c21f82

View File

@@ -1 +0,0 @@
hello, world!

View File

@@ -1,46 +1,27 @@
CC=../cc65/bin/cl65
CFLAGS=-T -t super6502 -I. --cpu "65C02"
test: CFLAGS=-T -t sim65c02 -I.
LD=../cc65/bin/cl65
CFLAGS=-T -t none -I. --cpu "65C02"
LDFLAGS=-C link.ld -m $(NAME).map
SIM=../cc65/bin/sim65
SIMARGS=-v -c -x 1000000
FSDIR=../fsdir
NAME=kernel
TEST_BIN=test.bin
BIN=$(NAME).bin
HEX=$(NAME).hex
O65 = $(NAME).o65
FSDIR=../fsdir
LISTS=lists
TESTS=tests
SRCS=$(wildcard *.s) $(wildcard *.c)
SRCS+=$(filter-out $(wildcard tests/*), $(wildcard **/*.s)) $(filter-out $(wildcard tests/*), $(wildcard **/*.c))
SRCS+=$(wildcard **/*.s) $(wildcard **/*.c)
OBJS+=$(patsubst %.s,%.o,$(filter %s,$(SRCS)))
OBJS+=$(patsubst %.c,%.o,$(filter %c,$(SRCS)))
TEST_SRCS=$(wildcard $(TESTS)/*.s) $(wildcard $(TESTS)/*.c)
TEST_OBJS+=$(patsubst %.s,%.o,$(filter %s,$(TEST_SRCS)))
TEST_OBJS+=$(patsubst %.c,%.o,$(filter %c,$(TEST_SRCS)))
TEST_OBJS+=$(filter-out boot.o,$(filter-out main.o,$(filter-out vectors.o,$(OBJS))))
# Make sure the kernel linked to correct address, no relocation!
all: $(O65)
cp $(O65) $(FSDIR)
all: $(BIN)
cp $(BIN) $(FSDIR)
test: $(TEST_BIN)
$(SIM) $(SIMARGS) $(TEST_BIN)
$(TEST_BIN): $(OBJS) $(TEST_OBJS)
$(CC) $(CFLAGS) $(TEST_OBJS) -o $@
$(HEX): $(BIN)
objcopy --input-target=binary --output-target=ihex $(BIN) $(HEX)
$(BIN): $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $@
$(O65): $(OBJS)
$(LD) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $@
%.o: %.c $(LISTS)
$(CC) $(CFLAGS) -l $(LISTS)/$<.list -c $< -o $@
@@ -50,11 +31,7 @@ $(BIN): $(OBJS)
$(LISTS):
mkdir -p $(addprefix $(LISTS)/,$(sort $(dir $(SRCS))))
mkdir $(LISTS)/$(sort $(dir $(TEST_SRCS)))
.PHONY: clean
clean:
rm -rf $(OBJS) $(BIN) $(HEX) $(LISTS) $(NAME).map
rm -rf $(TEST_OBJS) $(TEST_BIN)
rm -rf $(FSDIR)/$(BIN)
rm -rf $(OBJS) $(O65) $(LISTS) $(NAME).map

View File

@@ -8,7 +8,7 @@
.import _main
.export __STARTUP__ : absolute = 1 ; Mark as startup
.import __SDRAM_START__, __SDRAM_SIZE__ ; Linker generated
.import __STACKSTART__, __STACKSIZE__ ; Linker generated
.import copydata, zerobss, initlib, donelib
@@ -17,7 +17,7 @@
; ---------------------------------------------------------------------------
; Place the startup code in a special segment
.segment "STARTUP"
.segment "STARTUP"
; ---------------------------------------------------------------------------
; A little light 6502 housekeeping
@@ -29,10 +29,9 @@ _init: LDX #$FF ; Initialize stack pointer to $01FF
; ---------------------------------------------------------------------------
; Set cc65 argument stack pointer
;LDA #<(__SDRAM_START__ + __SDRAM_SIZE__)
lda #<($200 + $7cf0)
LDA #<(__STACKSTART__ + __STACKSIZE__)
STA sp
LDA #>($200 + $7cf0)
LDA #>(__STACKSTART__ + __STACKSIZE__)
STA sp+1
; ---------------------------------------------------------------------------

View File

@@ -1,16 +0,0 @@
#ifndef _BOARD_IO_H
#define _BOARD_IO_H
#include <stdint.h>
uint8_t hex_set_8(uint8_t val, uint8_t idx);
uint8_t hex_set_16(uint16_t val);
uint8_t hex_set_24(uint32_t val);
void hex_enable(uint8_t mask);
uint8_t sw_read();
void led_set(uint8_t val);
#endif

View File

@@ -1,71 +0,0 @@
.include "io.inc65"
.importzp sp, sreg
.export _hex_set_8
.export _hex_set_16
.export _hex_set_24
.export _hex_enable
.export _sw_read
.export _led_set
.autoimport on
.code
; @in A: idx Stack[0]: val
; @out A: 0 for success, 1 for failure.
; Sets one of the 3 pairs of hex digits.
_hex_set_8:
phx
cmp #$3 ; If idx >= 3 then fail
bcc @1
plx
lda #$1
rts
@1: tax ; Move idx into x
jsr popa ; put val into a
sta SEVEN_SEG,x ; write to val
lda #$0
plx
rts
; @in A/X: val
; @out A: 0 for success, 1 for failure
; Sets the low 2 pairs of hex digits
_hex_set_16:
sta SEVEN_SEG
stx SEVEN_SEG+1
lda #$0
rts
; @in A/X/sreg: val
; @out A: 0 for success, 1 for failure
; Sets the 3 pairs of hex digits for a 24 bit value
_hex_set_24:
sta SEVEN_SEG
stx SEVEN_SEG+1
lda sreg
sta SEVEN_SEG+2
lda #$0
rts
; @in A: mask
; Set the mask for seven seg enables
_hex_enable:
sta SEVEN_SEG+3
rts
; @out A: The Value of the switches
; Reads the current values of the switches.
_sw_read:
lda SW
ldx #$0
rts
; @in A: val
; @out A: 0 for success, 1 for failure
; Sets the LEDs
_led_set:
sta LED
rts

View File

@@ -6,7 +6,7 @@
.export _cputc
.export gotoxy
.export _clrscr
.export _cgetc
;.export _cgetc
.autoimport on
@@ -53,8 +53,8 @@ _clrscr:
pla
rts
_cgetc:
@2: lda _lastchar
beq @2
stz _lastchar
rts
;_cgetc:
;@2: lda _lastchar
; beq @2
; stz _lastchar
; rts

View File

@@ -1,15 +0,0 @@
#ifndef _INTERRUPT_H
#define _INTERRUPT_H
#include <stdint.h>
#define BUTTON (1 << 0)
#define UART (1 << 1)
void irq_int();
void nmi_int();
uint8_t irq_get_status();
void irq_set_status(uint8_t);
#endif

View File

@@ -1,18 +1,13 @@
SEVEN_SEG = $7ff0
UART = $7ff4
UART = $efe6
UART_TXB = UART
UART_RXB = UART
UART_STATUS = UART + 1
LED = $7ff6
LED = $efff
SW = LED
MM_CTRL = $7ff7
MM_DATA = $7fe0
SD_ARG = $7ff8
SD_CMD = $7ffc
SD_DATA = $7ffd
IRQ_STATUS = $7fff
SPI_BAUD = $efd8
SPI_INPUT = $efd9
SPI_OUTPUT = $efda
SPI_CTRL = $efdb
SPI_STATUS = SPI_CTRL

View File

@@ -1,12 +0,0 @@
#ifndef _MAPPER_H
#define _MAPPER_H
#include <stdint.h>
void mapper_enable(uint8_t en);
uint8_t mapper_read(uint8_t addr);
void mapper_write(uint8_t data, uint8_t addr);
#endif

View File

@@ -1,32 +0,0 @@
.include "io.inc65"
.importzp sp, sreg
.export _mapper_enable
.export _mapper_read, _mapper_write
.autoimport on
.code
; void mapper_enable(uint8_t en)
_mapper_enable:
sta MM_CTRL
rts
_mapper_read:
phx
tax
lda MM_DATA,x
ldx #$00
rts
_mapper_write:
phx
tax
jsr popa
sta MM_DATA,x
plx
rts

View File

@@ -1,75 +0,0 @@
#include <stdint.h>
#include <conio.h>
#include "devices/sd_card.h"
void sd_init() {
uint32_t resp;
sd_card_command(0, 0);
sd_card_command(0x000001aa, 8);
sd_card_resp(&resp);
//cprintf("CMD8: %lx\n", resp);
sd_card_command(0, 55);
sd_card_command(0x40180000, 41);
sd_card_resp(&resp);
//cprintf("CMD41: %lx\n", resp);
sd_card_command(0, 55);
sd_card_command(0x40180000, 41);
sd_card_resp(&resp);
//cprintf("CMD41: %lx\n", resp);
sd_card_command(0, 2);
sd_card_resp(&resp);
//cprintf("CMD2: %lx\n", resp);
}
uint16_t sd_get_rca() {
uint32_t resp;
sd_card_command(0, 3);
resp = 0;
sd_card_resp(&resp);
//cprintf("CMD3: %lx\n", resp);
return resp >> 16;
}
uint16_t sd_select_card(uint16_t rca) {
uint32_t resp;
sd_card_command((uint32_t)rca << 16, 7);
sd_card_resp(&resp);
return (uint16_t) resp;
}
uint16_t sd_get_status(uint16_t rca) {
uint32_t resp;
sd_card_command((uint32_t)rca << 16, 13);
sd_card_resp(&resp);
return (uint16_t) resp;
}
void sd_readblock(uint32_t addr, void* buf) {
uint32_t resp;
int i;
sd_card_command(addr, 17);
sd_card_resp(&resp);
//cprintf("CMD17: %lx\n", resp);
sd_card_wait_for_data();
//cprintf("Read data: \n");
for (i = 0; i < 512; i++){
((uint8_t*)buf)[i] = sd_card_read_byte();
}
//cprintf("\n");
}

View File

@@ -1,18 +0,0 @@
#ifndef _SD_CARD_H
#define _SD_CARD_H
#include <stdint.h>
void sd_init();
uint16_t sd_get_rca();
uint16_t sd_select_card(uint16_t rca);
uint16_t sd_get_status(uint16_t rca);
void sd_readblock(uint32_t addr, void* buf);
void sd_card_command(uint32_t arg, uint8_t cmd);
void sd_card_resp(uint32_t* resp);
uint8_t sd_card_read_byte();
void sd_card_wait_for_data();
#endif

View File

@@ -1,66 +0,0 @@
.include "io.inc65"
.importzp sp, sreg, ptr1
.export _sd_card_command
.export _sd_card_resp
.export _sd_card_read_byte
.export _sd_card_wait_for_data
.autoimport on
.code
; Send sd card command.
; command is in A register, the args are on the stack
; I think the order is high byte first?
_sd_card_command:
pha
jsr popeax
sta SD_ARG
stx SD_ARG+1
lda sreg
sta SD_ARG+2
lda sreg+1
sta SD_ARG+3
pla
sta SD_CMD
rts
; void sd_card_resp(uint32_t* resp);
_sd_card_resp:
phy
sta ptr1 ; store pointer
stx ptr1+1
@1: lda SD_CMD ; wait for status flag
and #$01
beq @1
lda SD_ARG
ldy #$0
sta (ptr1),y
lda SD_ARG+1
iny
sta (ptr1),y
lda SD_ARG+2
iny
sta (ptr1),y
lda SD_ARG+3
iny
sta (ptr1),y
ply
rts
_sd_card_read_byte:
lda SD_DATA
ldx #$00
rts
_sd_card_wait_for_data:
pha
@1: lda SD_CMD ; wait for status flag
and #$02
beq @1
pla
rts

View File

@@ -19,8 +19,8 @@ _uart_txb:
_uart_txb_block:
pha
sta UART_TXB ; Write value
@1: lda UART_STATUS ; Wait for status[0] to be 0
bit #$01
@1: lda UART_STATUS ; Wait for status[1] to be 0
bit #$02
bne @1
pla
rts

View File

@@ -1,61 +0,0 @@
#include <stdint.h>
#include <conio.h>
#include <string.h>
#include "filesystem/fat.h"
#include "filesystem/o65.h"
void exec(char* filename) {
o65_header_t* header;
o65_opt_t* o65_opt;
uint8_t* seg_ptr;
uint8_t* code_base;
uint8_t* data_base;
uint16_t code_len;
uint16_t data_len;
uint8_t (*exec)(void);
uint8_t ret;
fat_read(filename, fat_buf);
header = (o65_header_t*)fat_buf;
if (header->c64_marker == O65_NON_C64 &&
header->magic[0] == O65_MAGIC_0 &&
header->magic[1] == O65_MAGIC_1 &&
header->magic[2] == O65_MAGIC_2) {
code_base = (uint8_t*)header->tbase;
data_base = (uint8_t*)header->dbase;
code_len = header->tlen;
data_len = header->dlen;
o65_opt = (o65_opt_t*)(fat_buf + sizeof(o65_header_t));
while (o65_opt->olen)
{
o65_print_option(o65_opt);
o65_opt = (o65_opt_t*)((uint8_t*)o65_opt + o65_opt->olen);
}
seg_ptr = (uint8_t*)o65_opt + 1;
memcpy((uint8_t*)code_base, seg_ptr, code_len);
seg_ptr+=code_len;
memcpy((uint8_t*)data_base, seg_ptr, data_len);
exec = (uint8_t (*)(void))code_base;
ret = 0;
//ret = (*exec)();
cprintf("ret: %x\n", ret);
}
}

View File

@@ -1,6 +0,0 @@
#ifndef _EXEC_H
#define _EXEC_H
void exec(char* filename);
#endif

View File

@@ -1,246 +0,0 @@
#include <conio.h>
#include <string.h>
#include <stdlib.h>
#include "fat.h"
#include "devices/sd_card.h"
uint8_t fat_buf[512];
static uint32_t fat_end_of_chain;
static full_bpb_t bpb;
static uint32_t data_region_start;
void fat_print_pbp_info(full_bpb_t* bpb){
cprintf("Bytes per sector: %d\n", bpb->bytes_per_sector);
cprintf("Sectors per cluster: %d\n", bpb->sectors_per_cluster);
cprintf("Reserved Sectors: %d\n", bpb->reserved_sectors);
cprintf("Fat Count: %d\n", bpb->fat_count);
cprintf("Max Dir Entries: %d\n", bpb->max_dir_entries);
cprintf("Total Sector Count: %d\n", bpb->total_sector_count);
cprintf("Media Descriptor: 0x%x\n", bpb->media_descriptor);
cprintf("Sectors per Fat: %d\n", bpb->sectors_per_fat_16);
cprintf("\n");
cprintf("Sectors per track: %d\n", bpb->sectors_per_track);
cprintf("Head Count: %d\n", bpb->head_count);
cprintf("Hidden Sector Count: %ld\n", bpb->hidden_sector_count);
cprintf("Logical Sector Count: %ld\n", bpb->logical_sector_count);
cprintf("Sectors per Fat: %ld\n", bpb->sectors_per_fat_32);
cprintf("Extended Flags: 0x%x\n", bpb->extended_flags);
cprintf("Version: %d\n", bpb->version);
cprintf("Root Cluster: 0x%lx\n", bpb->root_cluster);
cprintf("System Information: 0x%x\n", bpb->system_information);
cprintf("Backup Boot Sector: 0x%x\n", bpb->backup_boot_sector);
cprintf("\n");
cprintf("Drive Number: %d\n", bpb->drive_num);
cprintf("Extended Signature: 0x%x\n", bpb->extended_signature);
cprintf("Volume ID: 0x%lx\n", bpb->volume_id);
cprintf("Partition Label: %.11s\n", &bpb->partition_label);
cprintf("Partition Label: %.8s\n", &bpb->filesystem_type);
cprintf("\n");
}
void fat_init(){
//int i;
sd_readblock(0, fat_buf);
memcpy(&bpb, &fat_buf[11], sizeof(full_bpb_t));
sd_readblock(1, fat_buf);
sd_readblock(32, fat_buf);
fat_print_pbp_info(&bpb);
data_region_start = bpb.reserved_sectors + bpb.fat_count*bpb.sectors_per_fat_32;
sd_readblock(bpb.reserved_sectors, fat_buf);
//uncomment to view start of FAT
/*
for (i = 0; i < FAT_CLUSTERS_PER_SECTOR; i++) {
cprintf("%lx ", ((uint32_t*)fat_buf)[i]);
}
cprintf("\n\n");
*/
fat_end_of_chain = ((uint32_t*)fat_buf)[1] & FAT_EOC_CLUSTERMASK;
cprintf("End of chain indicator: %lx\n", fat_end_of_chain);
}
void fat_read(char* filename, void* buf) {
vfat_dentry_t* vfat_dentry;
dos_dentry_t* dos_dentry;
uint32_t cluster;
(void)filename; //just ignore filename
sd_readblock(data_region_start, buf);
vfat_dentry = (vfat_dentry_t*)buf;
while(vfat_dentry->sequence_number == 0xe5)
vfat_dentry++;
dos_dentry = (dos_dentry_t*)(vfat_dentry + 1);
cluster = ((uint32_t)dos_dentry->first_cluster_h << 16) + dos_dentry->first_cluster_l;
sd_readblock(data_region_start + (cluster - 2) * 8, buf);
}
//the dentry is a double pointer because we need to increment it.
void fat_parse_vfat_filenamename(vfat_dentry_t** vfat_dentry, char* name, uint32_t cluster) {
uint8_t i;
uint8_t overflows;
uint8_t done;
char* shift_name;
uint8_t sequence_number = (*vfat_dentry)->sequence_number;
overflows = 0;
for (;;){
shift_name = name + 13*((sequence_number & FAT_LFN_ENTRY_MASK) - 1);
done = 0;
for(i = 0; i < 5; i++) {
shift_name[i] = (*vfat_dentry)->filename0[i];
if (!shift_name[i]) {
done = 1;
break;
}
}
if (!done) {
for(i = 0; i < 6; i++) {
shift_name[i+5] = (*vfat_dentry)->filename1[i];
if (!shift_name[i+5]) {
done = 1;
break;
}
}
}
if (!done) {
for(i = 0; i < 2; i++) {
shift_name[i+11] = (*vfat_dentry)->filename2[i];
if (!shift_name[i+11]) {
done = 1;
break;
}
}
}
if ((sequence_number & FAT_LFN_ENTRY_MASK) == 1) {
break;
} else {
do {
(*vfat_dentry)++;
if ((uint8_t*)*vfat_dentry >= fat_buf + sizeof(fat_buf)) {
overflows++;
if (overflows == bpb.sectors_per_cluster) {
cprintf("Too many overflows, go back to fat!\n"); //TODO this
return;
}
sd_readblock(data_region_start + (cluster - 2) * 8 + overflows, fat_buf);
*vfat_dentry = (vfat_dentry_t*)fat_buf;
}
} while((*vfat_dentry)->sequence_number == 0xe5);
sequence_number = (*vfat_dentry)->sequence_number;
}
}
}
uint32_t fat_find_cluster_num(char* name, uint32_t cluster) {
vfat_dentry_t* vfat_dentry;
dos_dentry_t* dos_dentry;
char* vfat_name;
cprintf("Looking for file %s\n", name);
sd_readblock(data_region_start + (cluster - 2) * 8, fat_buf);
vfat_dentry = (vfat_dentry_t*)fat_buf;
vfat_name = (char*)malloc(FAT_MAX_FILE_NAME);
while(vfat_dentry->sequence_number == 0xe5)
vfat_dentry++;
vfat_name[0] = '\0';
while(vfat_dentry->sequence_number) {
fat_parse_vfat_filenamename(&vfat_dentry, vfat_name, cluster);
cprintf("Parsed filename: %s\n", vfat_name);
if (!strcmp(vfat_name, name)) { //TODO this is probably unsafe, use strncmp
cprintf("Found file %s\n", vfat_name);
break;
} else {
vfat_dentry += 2;
while(vfat_dentry->sequence_number == 0xe5)
vfat_dentry++;
}
}
free(vfat_name);
if (!vfat_dentry->sequence_number) {
cprintf("File not found.\n");
return -1;
}
dos_dentry = (dos_dentry_t*) vfat_dentry + 1; //dos entry follows last vfat entry
cluster = ((uint32_t)dos_dentry->first_cluster_h << 16) + dos_dentry->first_cluster_l;
cprintf("Cluster: %ld\n", cluster);
return cluster;
}
uint16_t fat_parse_path_to_cluster(char* filename) {
//basically start at the root folder and search through it
int i;
int len;
uint8_t dirs = 0;
char* spaced_filename;
char* fragment;
uint32_t cluster = 2; //root chain is chain 2
if (filename[0] != '/') {
cprintf("Filename does not begin with '/'\n");
return 0;
}
filename++;
len = strlen(filename);
spaced_filename = (char*)malloc(len+1); //need to account for null byte
for (i = 0; i <= len; i++) {
if (filename[i] == '/') {
spaced_filename[i] = '\0';
dirs++;
} else {
spaced_filename[i] = filename[i];
}
}
fragment = spaced_filename;
cprintf("Dirs: %d\n", dirs);
for (i = 0; i <= dirs; i++) {
cprintf("Fragment: %s\n", fragment);
cluster = fat_find_cluster_num(fragment, cluster);
fragment = spaced_filename + strlen(fragment) + 1;
}
free(spaced_filename);
return cluster;
}

View File

@@ -1,122 +0,0 @@
#ifndef _FAT_H
#define _FAT_H
#include <stdint.h>
extern uint8_t fat_buf[];
#define FAT_MAX_FILE_NAME 255
#define FAT_CLUSTERS_PER_SECTOR 128
#define FAT_CLUSTERMASK 0x0fffffff
#define FAT_EOC_CLUSTERMASK 0x0ffffff8
#define FAT_LAST_LFN_MASK (1 << 6)
#define FAT_LFN_ENTRY_MASK 0x1f
typedef struct {
uint16_t bytes_per_sector;
uint8_t sectors_per_cluster;
uint16_t reserved_sectors;
uint8_t fat_count;
uint16_t max_dir_entries;
uint16_t total_sector_count;
uint8_t media_descriptor;
uint16_t sectors_per_fat;
} dos_2_bpb_t;
typedef struct {
dos_2_bpb_t bpb2;
uint16_t sectors_per_track;
uint16_t head_count;
uint32_t hidden_sector_count;
uint32_t logical_sector_count;
uint32_t sectors_per_fat;
uint16_t extended_flags;
uint16_t version;
uint32_t root_cluster;
uint16_t system_information;
uint16_t backup_boot_sector;
uint8_t reserved[12];
} dos_3_bpb_t;
typedef struct {
dos_3_bpb_t bpb3;
uint8_t drive_num;
uint8_t reserved;
uint8_t extended_signature;
uint32_t volume_id;
uint8_t partition_label[11];
uint8_t filesystem_type[8];
} ebpb_t;
typedef struct {
uint16_t bytes_per_sector;
uint8_t sectors_per_cluster;
uint16_t reserved_sectors;
uint8_t fat_count;
uint16_t max_dir_entries;
uint16_t total_sector_count;
uint8_t media_descriptor;
uint16_t sectors_per_fat_16;
uint16_t sectors_per_track;
uint16_t head_count;
uint32_t hidden_sector_count;
uint32_t logical_sector_count;
uint32_t sectors_per_fat_32;
uint16_t extended_flags;
uint16_t version;
uint32_t root_cluster;
uint16_t system_information;
uint16_t backup_boot_sector;
uint8_t reserved[12];
uint8_t drive_num;
uint8_t reserved2;
uint8_t extended_signature;
uint32_t volume_id;
uint8_t partition_label[11];
uint8_t filesystem_type[8];
} full_bpb_t;
typedef struct {
uint32_t sig;
uint8_t reserved[480];
uint32_t sig2;
uint32_t free_data_clusters;
uint32_t last_allocated_data_cluster;
uint32_t reserved2;
uint32_t sig3;
} fs_info_sector_t;
typedef struct {
uint8_t sequence_number;
uint16_t filename0[5];
uint8_t attributes;
uint8_t type;
uint8_t checksum;
uint16_t filename1[6];
uint16_t reserved;
uint16_t filename2[2];
} vfat_dentry_t;
typedef struct {
uint8_t filename[8];
uint8_t extension[3];
uint8_t attributes;
uint8_t reserved;
uint8_t create_time_10ms;
uint32_t create_date;
uint16_t access_date;
uint16_t first_cluster_h;
uint32_t modify_cluster;
uint16_t first_cluster_l;
uint32_t file_size;
} dos_dentry_t;
void fat_print_pbp_info(full_bpb_t* bpb);
void fat_init();
void fat_read(char* filename, void* buf);
uint16_t fat_parse_path_to_cluster(char* filename);
#endif

View File

@@ -1,28 +0,0 @@
#include <conio.h>
#include "o65.h"
void o65_print_option(o65_opt_t* opt) {
int i;
cprintf("Option Length: %d\n", opt->olen);
cprintf("Option Type: %x ", opt->type);
switch (opt->type) {
case O65_OPT_FILENAME: cprintf("Filename\n"); break;
case O65_OPT_OS: cprintf("OS\n"); break;
case O65_OPT_ASSEMBLER: cprintf("Assembler\n"); break;
case O65_OPT_AUTHOR: cprintf("Author\n"); break;
case O65_OPT_DATE: cprintf("Creation Date\n"); break;
default: cprintf("Invalid\n"); break;
}
if (opt->type != O65_OPT_OS) {
for (i = 0; i < opt->olen - 2; i++) {
cprintf("%c", opt->data[i]);
}
} else {
cprintf("%x", opt->data[0]);
}
cprintf("\n\n");
}

View File

@@ -1,65 +0,0 @@
#ifndef _O65_H
#define _O65_H
#include <stdint.h>
#define O65_NON_C64 0x0001
#define O65_MAGIC_0 0x6f
#define O65_MAGIC_1 0x36
#define O65_MAGIC_2 0x35
#define O65_OPT_FILENAME 0
#define O65_OPT_OS 1
#define O65_OPT_ASSEMBLER 2
#define O65_OPT_AUTHOR 3
#define O65_OPT_DATE 4
#define O65_OS_OSA65 1
#define O65_OS_LUNIX 2
#define O65_OS_CC65 3
#define O65_OS_OPENCBM 4
#define O65_OS_SUPER6502 5
typedef union {
struct {
int cpu : 1;
int reloc : 1;
int size : 1;
int obj : 1;
int simple : 1;
int chain : 1;
int bsszero : 1;
int cpu2 : 4;
int align : 2;
};
uint16_t _mode;
} o65_mode_t;
typedef struct {
uint16_t c64_marker;
uint8_t magic[3];
uint8_t version;
o65_mode_t mode;
uint16_t tbase;
uint16_t tlen;
uint16_t dbase;
uint16_t dlen;
uint16_t bbase;
uint16_t blen;
uint16_t zbase;
uint16_t zlen;
uint16_t stack;
} o65_header_t;
typedef struct {
uint8_t olen;
uint8_t type;
uint8_t data[1]; //This is actually variable length
} o65_opt_t;
void o65_print_option(o65_opt_t* opt);
#endif

View File

@@ -1,24 +0,0 @@
#include <stdint.h>
#include <conio.h>
#include "devices/interrupt.h"
#include "devices/uart.h"
char lastchar;
void handle_irq() {
uint8_t status;
status = irq_get_status();
if (status & BUTTON) {
cputs("Button Interrupt!\n");
irq_set_status(status & ~BUTTON);
}
if (status & UART) {
lastchar = uart_rxb();
irq_set_status(status & ~UART);
}
}

9
sw/kernel/kernel.c Normal file
View File

@@ -0,0 +1,9 @@
#include <conio.h>
int main() {
cprintf("Hello, world!\r\n");
while(1);
return 0;
}

View File

@@ -1,20 +1,33 @@
MEMORY
{
ZP: start = $0, size = $100, type = rw, define = yes;
SDRAM: start = $200, size = $7cf0, type = rw, define = yes;
ROM: start = $D000, size = $3000, type = rw, define = yes, file = %O;
ZP: start = $0, size = $100, type = rw, define = yes;
STACK: start = $200, size = $E00, type = rw, define = yes;
KERNEL: start = $1000, size = $7000, type = rw, define = yes, file = %O;
USER: start = $8000, size = $6000, type = rw, define = yes;
IO: start = $E000, size = $1000, type = rw, define = yes;
ROM: start = $f000, size = $1000, type = rw, define = yes; #rw for vectors
}
SEGMENTS {
ZEROPAGE: load = ZP, type = zp, define = yes;
DATA: load = ROM, type = rw, define = yes, run = SDRAM;
BSS: load = SDRAM, type = bss, define = yes;
HEAP: load = SDRAM, type = bss, optional = yes;
STARTUP: load = ROM, type = ro;
ONCE: load = ROM, type = ro, optional = yes;
CODE: load = ROM, type = ro;
RODATA: load = ROM, type = ro;
VECTORS: load = ROM, type = ro, start = $FFFA;
ZEROPAGE: load = ZP, type = zp, define = yes;
STARTUP: load = KERNEL, type = ro;
ONCE: load = KERNEL, type = ro, optional = yes;
CODE: load = KERNEL, type = ro;
RODATA: load = KERNEL, type = ro;
DATA: load = KERNEL, type = rw, define = yes;
BSS: load = KERNEL, type = rw, define = yes;
HEAP: load = KERNEL, type = rw, define = yes, optional = yes;
}
FILES
{
%O: format = o65;
}
FORMATS
{
o65: os = super, version = 0, type = small,
export = _init;
}
FEATURES {
@@ -29,7 +42,7 @@ FEATURES {
}
SYMBOLS {
# Define the stack size for the application
__STACKSIZE__: value = $0200, type = weak;
__STACKSTART__: type = weak, value = $0800; # 2k stack
__STACKSIZE__: value = $0E00, type = weak;
__STACKSTART__: type = weak, value = $0800;
}

View File

@@ -1,45 +0,0 @@
#include <stdint.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
#include "devices/board_io.h"
#include "devices/uart.h"
#include "devices/mapper.h"
#include "devices/sd_card.h"
#include "filesystem/fat.h"
#include "exec.h"
uint8_t buf[512];
int main() {
uint16_t rca;
char* filename;
clrscr();
cprintf("Hello, world! Modified\n");
sd_init();
rca = sd_get_rca();
cprintf("rca: %x\n", rca);
sd_select_card(rca);
fat_init();
filename = (char*)malloc(FAT_MAX_FILE_NAME);
for(;;) {
cprintf("Filename: ");
cscanf("%s", filename);
cprintf("\n");
fat_parse_path_to_cluster(filename);
}
//exec("/test.o65");
cprintf("Done!\n");
return 0;
}

View File

@@ -1,89 +0,0 @@
#include <stdio.h>
#include "devices/board_io.h"
#include "devices/uart.h"
#include "devices/interrupt.h"
int main(void)
{
int retval = 0;
int i;
printf("\nStarting tests...\n\n");
printf("Testing hex_set_8...\n");
for (i = 0; i < 3; i++) {
if (hex_set_8(i+1, i)) {
printf("Failed to write to idx %d!\n", i);
retval++;
}
if (*(uint8_t*)0x7ff0+i != i+1) {
printf("Incorrect value at idx %d!\n", i);
retval++;
}
}
if (!hex_set_8(0xab, 3)) {
printf("Writing to idx 3 should fail!\n");
retval++;
}
printf("Done!\n\n");
printf("Testing hex_set_16...\n");
if (hex_set_16(0xabcd)){
printf("Failed to write!\n");
}
if (*(uint16_t*)0x7ff0 != 0xabcd) {
printf("Incorrect value!\n", i);
retval++;
}
printf("Done!\n\n");
printf("Testing hex_set_24...\n");
if (hex_set_24(0xabcdef)){
printf("Failed to write!\n");
}
if (*(uint16_t*)0x7ff0 != 0xcdef && *(uint8_t*)0x7ff2 != 0xab) {
printf("Incorrect value!\n", i);
retval++;
}
printf("Done!\n\n");
printf("Testing hex_enable...\n");
hex_enable(0xa5);
if (*(uint8_t*)0x7ff3 != 0xa5) {
printf("Incorrect value!\n", i);
retval++;
}
printf("Done!\n\n");
printf("Testing uart_txb_block...\n");
*(uint8_t*)0x7ff5 = 0;
uart_txb_block(0xa5);
if (*(uint8_t*)0x7ff4 != 0xa5) {
printf("Incorrect value!\n", i);
retval++;
}
printf("Done!\n\n");
printf("Testing uart_status...\n");
*(uint8_t*)0x7ff5 = 0xa5;
if (uart_status() != 0xa5) {
printf("Incorrect value!\n", i);
retval++;
}
printf("Done!\n\n");
printf("Testing irq_get_status...\n");
*(uint8_t*)0x7fff = 0xa5;
if (irq_get_status() != 0xa5) {
printf("Incorrect value!\n", i);
retval++;
}
printf("Done!\n\n");
return retval != 0;
}

View File

@@ -1,14 +0,0 @@
; ---------------------------------------------------------------------------
; vectors.s
; ---------------------------------------------------------------------------
;
; Defines the interrupt vector table.
.import _init
.import _nmi_int, _irq_int
.segment "VECTORS"
.addr _nmi_int ; NMI vector
.addr _init ; Reset vector
.addr _irq_int ; IRQ/BRK vector

View File

@@ -1,8 +1,8 @@
DEVICE=/dev/mmcblk0
TMPMOUNT=/tmp/sd
FSDIR=fsdir
FSDIR=../fsdir
V=
V=-v
echo "$(tput bold setaf 11)Mounting Device$(tput sgr 0)"
mkdir $V -p $TMPMOUNT
@@ -16,4 +16,4 @@ echo
echo "$(tput bold setaf 11)Unmounting Device$(tput sgr 0)"
sudo umount $V $DEVICE
rmdir $V $TMPMOUNT
echo
echo

View File

@@ -1,23 +1,20 @@
#!/bin/bash
BOOTLOADER=bootloader/bootloader.bin
BOOTLOADER=../bios/bootloader.bin
DEVICE=/dev/mmcblk0
TMPBOOTSECT=/tmp/bootsect
TMPMOUNT=/tmp/sd
V=
STATUS="status=none"
V=-v
# STATUS="status=none"
STATUS=
echo "$(tput bold setaf 11)Creating Filesystem$(tput sgr 0)"
sudo mkfs.vfat -F32 $DEVICE -n SUPER6502 $V
sudo mkfs.vfat -I -F32 $DEVICE -n SUPER6502 $V
echo
echo "$(tput bold setaf 11)Modifying Boot Sector$(tput sgr 0)"
sudo dd if=$DEVICE of=$TMPBOOTSECT bs=512 count=1 $STATUS
sudo dd conv=notrunc if=$BOOTLOADER of=$DEVICE bs=512 skip=0 count=1 $STATUS
sudo dd conv=notrunc if=$TMPBOOTSECT of=$DEVICE bs=1 skip=0 count=90 iflag=skip_bytes,count_bytes $STATUS
sudo dd conv=notrunc if=$BOOTLOADER of=$DEVICE bs=1 skip=0 count=3 iflag=skip_bytes,count_bytes $STATUS
echo
sudo dd if=$BOOTLOADER of=$DEVICE bs=1 count=11 $STATUS
sudo dd if=$BOOTLOADER of=$DEVICE bs=1 count=380 seek=71 skip=71 $STATUS
echo "$(tput bold setaf 10)Done!$(tput sgr 0)"

101
sw/script/o65dump.py Executable file
View File

@@ -0,0 +1,101 @@
#!/usr/bin/python
import sys
import io
class O65():
header: dict[str, int] = {}
options: list[(int, int, bytes)] = []
text: bytes
data: bytes
undef_ref_cnt: int
text_reloc: list[(int, int, int)] = []
data_reloc: list[(int, int, int)] = []
exports: list[(str, int, int)] = []
def __init__(self, filename: str) -> None:
with open(filename, "rb") as _file:
self.header["no_c64"] = int.from_bytes(_file.read(2))
self.header["magic"] = int.from_bytes(_file.read(3))
self.header["version"] = int.from_bytes(_file.read(1))
self.header["mode"] = int.from_bytes(_file.read(2), byteorder="little")
self.header["tbase"] = int.from_bytes(_file.read(2), byteorder="little")
self.header["tlen"] = int.from_bytes(_file.read(2), byteorder="little")
self.header["dbase"] = int.from_bytes(_file.read(2), byteorder="little")
self.header["dlen"] = int.from_bytes(_file.read(2), byteorder="little")
self.header["bbase"] = int.from_bytes(_file.read(2), byteorder="little")
self.header["blen"] = int.from_bytes(_file.read(2), byteorder="little")
self.header["zbase"] = int.from_bytes(_file.read(2), byteorder="little")
self.header["zlen"] = int.from_bytes(_file.read(2), byteorder="little")
self.header["stack"] = int.from_bytes(_file.read(2), byteorder="little")
olen = int.from_bytes(_file.read(1))
while olen != 0:
otype = int.from_bytes(_file.read(1))
obytes = _file.read(olen - 2)
self.options.append((olen, otype, obytes))
olen = int.from_bytes(_file.read(1))
self.text = _file.read(self.header["tlen"])
self.data = _file.read(self.header["dlen"])
self.undef_ref_cnt = _file.read(2)
self.text_reloc = self._parse_reloc(_file)
self.data_reloc = self._parse_reloc(_file)
export_count = int.from_bytes(_file.read(2), byteorder="little")
for _ in range(export_count):
name: bytearray = bytearray()
data = 0
while True:
data = _file.read(1)
if data != b"\x00":
name.extend(data)
else:
break
segment = int.from_bytes(_file.read(1))
value = int.from_bytes(_file.read(2), byteorder="little")
self.exports.append((name.decode(), segment, value))
def _parse_reloc(self, fd: io.BufferedReader) -> list[(int, int, int)]:
reloc: list[(int, int, int)] = []
offset = fd.read(1)
while offset != b'\x00':
offset_val = 0
while offset == b'\xff':
offset = fd.read(1)
offset_val += int.from_bytes(offset) - 1
offset_val += int.from_bytes(offset)
typebyte = int.from_bytes(fd.read(1))
lobyte = None
if typebyte & 0x40:
lobyte = int.from_bytes(fd.read(1))
reloc.append((offset_val, typebyte, lobyte))
offset = fd.read(1)
return reloc
def main() -> None:
if len(sys.argv) < 2:
print("Please supply a filename")
return
filename = sys.argv[1]
print(filename)
o65 = O65(filename)
for item, value in o65.header.items():
print(f"{item}:\t{value:x}")
for option in o65.options:
print(f"Type: {option[1]}, Data: {option[2]}")
print(f"Text size: {len(o65.text)}")
print(f"Data size: {len(o65.data)}")
for item in o65.exports:
print(f"Name: {item[0]} Addr: {item[2]:#x}")
if __name__ == "__main__":
main()

View File

@@ -1,4 +1,4 @@
CC=cl65
CC=../cc65/bin/cl65
CFLAGS=-T -t super6502 -I. --cpu "65C02"
test: CFLAGS=-T -t sim65c02 -I.
LDFLAGS=-C link.ld -m $(NAME).map

View File

@@ -10,13 +10,13 @@ FILES {
SEGMENTS {
ZEROPAGE: load = ZP, type = zp, define = yes;
DATA: load = SDRAM, type = rw, define = yes, run = SDRAM;
BSS: load = SDRAM, type = bss, define = yes;
HEAP: load = SDRAM, type = bss, optional = yes;
STARTUP: load = SDRAM, type = ro;
ONCE: load = SDRAM, type = ro, optional = yes;
CODE: load = SDRAM, type = ro;
RODATA: load = SDRAM, type = ro;
DATA: load = SDRAM, type = rw, define = yes, run = SDRAM;
BSS: load = SDRAM, type = bss, define = yes;
HEAP: load = SDRAM, type = bss, optional = yes;
}
FEATURES {