96 Commits

Author SHA1 Message Date
Godzil
8d58ca0f7b Big code cleanup and re-indented, finally ! (Thanks astyle!) 2014-01-22 22:01:00 +00:00
Godzil
7e0186d7a0 Automatically generate the fpga bit .h file 2014-01-16 22:24:54 +00:00
Godzil
1d928e7091 Merge branch 'udev' into develop 2013-10-06 14:52:40 +01:00
Godzil
043eeea399 Automate cfgware.h file generation. Will automatically search the .bit file from sd2sneslite rle it and convert to .h file. 2012-08-23 16:55:50 +02:00
Godzil
c4ef438cac Update openocd interface to match my own interface 2012-08-17 18:32:00 +02:00
Maximilian Rehkopf
82998d7a48 PCB/Rev.E2: Add BOM 2012-08-06 23:33:01 +02:00
Maximilian Rehkopf
32a0a50c54 update changelog for 0.1.4a 2012-07-15 20:21:14 +02:00
Maximilian Rehkopf
b8d3b952ad firmware: bump version no. to 0.1.4a 2012-07-14 21:27:07 +02:00
Maximilian Rehkopf
e97396adc9 menu: fix DMA initialization (sprite glitches in some games) 2012-07-14 21:25:51 +02:00
mrehkopf
a72476ea6c Merge pull request #24 from Godzil/develop
Develop
2012-07-10 03:53:32 -07:00
Maximilian Rehkopf
d47858083a FPGA/Cx4: update user constraints for changed system clock 2012-07-09 18:52:51 +02:00
Maximilian Rehkopf
a7ac2f8900 update changelog 2012-07-09 18:52:03 +02:00
Maximilian Rehkopf
c80bdfbf59 Firmware: do not turn off write LED in case of periodic SRAM saving 2012-07-09 02:28:26 +02:00
Maximilian Rehkopf
a9ea821c0d Firmware: implement MSU1 interface changes 2012-07-09 02:27:53 +02:00
Maximilian Rehkopf
9baa4b7f9f Firmware: move SaveRAM to $E00000 2012-07-09 02:26:50 +02:00
Maximilian Rehkopf
2ef480f751 FPGA/DSPx: buffer register input 2012-07-09 02:23:57 +02:00
Maximilian Rehkopf
6b3a7eb4ae FPGA/SRTC: buffer register/address input 2012-07-09 02:22:57 +02:00
Maximilian Rehkopf
effa2a6972 FPGA/SDDMA: fix clock glitch, adjust RAM write timings 2012-07-09 02:22:07 +02:00
Maximilian Rehkopf
9253cc45b0 FPGA: implement MSU1 "audio error" status bit 2012-07-09 02:20:13 +02:00
Maximilian Rehkopf
9fbe61bad1 FPGA: Use internal clock instead of SNES master clock for $213F RMW timing 2012-07-09 02:18:28 +02:00
Maximilian Rehkopf
968c347986 FPGA/SPI: detect end of byte via MSB toggle instead of constant compare of async input 2012-07-09 02:17:01 +02:00
Maximilian Rehkopf
c231c8b821 FPGA: misc cleanup 2012-07-09 02:15:21 +02:00
Maximilian Rehkopf
60d7a08117 FPGA: Adjust Cx4 timing to new master clock rate 2012-07-09 02:13:44 +02:00
Maximilian Rehkopf
7df6909266 FPGA: rework shared memory access FSM 2012-07-09 02:12:59 +02:00
Maximilian Rehkopf
006ea8c44a FPGA: debug wires 2012-07-09 02:03:59 +02:00
Maximilian Rehkopf
684e2c3b81 FPGA/BSX: fix checksum registers 2012-07-09 02:00:29 +02:00
Maximilian Rehkopf
3af05cef91 FPGA/sd2sneslite: add missing file mcu_cmd.v; remove avr_cmd.v 2012-07-09 01:55:02 +02:00
Maximilian Rehkopf
a083d80ff9 FPGA: update clock speed to 88MHz 2012-07-09 01:54:05 +02:00
Maximilian Rehkopf
8148f5567c FPGA: properly synchronize external signals 2012-07-09 01:48:43 +02:00
Maximilian Rehkopf
1a52da6272 FPGA: Adjust DAC I²S signal timing 2012-07-09 01:41:47 +02:00
Maximilian Rehkopf
e33b2b2bc7 FPGA: simple SNES address input filtering 2012-07-09 01:37:57 +02:00
Maximilian Rehkopf
3530613349 FPGA: prepare new SNES command interface for future use (SNES side) 2012-07-09 01:29:47 +02:00
Maximilian Rehkopf
0d02bfded7 Firmware: adjust to SPI changes 2012-07-09 01:19:44 +02:00
Maximilian Rehkopf
576cedd285 Update embedded FPGA config 2012-07-09 01:17:32 +02:00
Maximilian Rehkopf
e6f77c242b Update changelog for version 0.1.4 2012-07-09 01:16:39 +02:00
Godzil
86d6f04870 Add gitignore file. 2012-07-05 14:42:02 +02:00
Godzil
e2af175f05 Correct baudrate on normal application. 2012-07-05 14:41:29 +02:00
Godzil
583309491c Change baudrate to more standard 115200 2012-07-05 14:41:06 +02:00
Maximilian Rehkopf
40099772f7 menu: comments 2012-07-03 20:44:17 +02:00
Maximilian Rehkopf
247e6591c4 menu: replace AVR with MCU in labels 2012-07-03 20:43:48 +02:00
Maximilian Rehkopf
1b77a6e7fa menu: remove redundant code from DMA macro 2012-07-03 20:43:18 +02:00
Maximilian Rehkopf
eede8b491b menu: properly init P register for gettimt 2012-07-03 16:21:46 +02:00
Maximilian Rehkopf
350b83e06b menu: fix scroll bug when entering directories with long names 2012-07-03 16:20:45 +02:00
Maximilian Rehkopf
943a3d14bb menu: fix order of SNES initialization 2012-07-03 16:18:12 +02:00
Maximilian Rehkopf
5eae77f626 menu: fade in screen on cold boot 2012-07-03 16:14:39 +02:00
Maximilian Rehkopf
14a2136be7 menu: speed up print routine, move tilemap buffers to bank $7E 2012-07-03 16:10:30 +02:00
Maximilian Rehkopf
45b67d0f1a Firmware: Change ROM size detection for broken headers 2012-07-01 03:27:34 +02:00
Maximilian Rehkopf
e23a76d812 Firmware: properly enable offloading before f_lseek 2012-07-01 03:25:37 +02:00
Maximilian Rehkopf
f4b8d57810 Firmware/FatFs: make f_gets break on NUL character as well 2012-07-01 03:24:35 +02:00
Maximilian Rehkopf
1be6885223 Firmware: bump default date 2012-07-01 03:23:27 +02:00
Maximilian Rehkopf
2eeaaefcef Firmware/SD: implement FatFs CTRL_SYNC ioctl (issue #4) 2012-07-01 03:20:27 +02:00
Maximilian Rehkopf
71aef898d2 Firmware: load database using DMA 2012-07-01 03:18:16 +02:00
Maximilian Rehkopf
d9e1680800 Firmware: remove SPI speed switching 2012-07-01 03:15:27 +02:00
Maximilian Rehkopf
57bb6351e7 Firmware: change CPU frequency to 88MHz 2012-07-01 03:12:05 +02:00
Maximilian Rehkopf
023901cab2 Firmware: refactor SNES reset pulse 2012-07-01 03:08:36 +02:00
Maximilian Rehkopf
6038d94d0f Firmware/cli: add mkdir command 2012-07-01 03:03:30 +02:00
Maximilian Rehkopf
aef19a2576 Firmware/cli: check parameters to saveraw command 2012-07-01 03:01:02 +02:00
Maximilian Rehkopf
3db272662c firmware: disregard trailing slash when sorting directory names 2012-06-11 02:00:58 +02:00
Maximilian Rehkopf
91458011aa minor comment cleanup 2012-06-11 02:00:18 +02:00
Maximilian Rehkopf
c062800386 firmware: speedup filesystem footprinting 2012-06-11 01:59:39 +02:00
Maximilian Rehkopf
61c7014f85 firmware: keep directory tables within bank boundaries 2012-06-11 01:59:04 +02:00
Maximilian Rehkopf
64b1b07333 firmware: change filesystem footprint calculation (order of files doesn't matter) 2012-06-11 01:57:06 +02:00
Maximilian Rehkopf
723bf9eb95 firmware: limit number of files per directory 2012-06-11 01:56:09 +02:00
Maximilian Rehkopf
9c84f01fd5 firmware: update embedded FPGA config 2012-06-11 01:54:48 +02:00
Maximilian Rehkopf
a5a02992e5 FPGA/embedded config: slightly tighten timing constraints 2012-06-11 01:52:45 +02:00
Maximilian Rehkopf
0f38935981 menu: fix xscroll bug when entering directories with scrolled names 2012-06-11 01:52:01 +02:00
Maximilian Rehkopf
f44de5ba64 menu/SPC player: fix "Artist" display for "binary format" ID666 tags 2012-06-11 01:50:35 +02:00
Maximilian Rehkopf
12deb9a0c7 firmware: correct number of files/dirs in system information 2012-06-10 20:28:33 +02:00
Maximilian Rehkopf
a1ca5f1dad firmware/SPC: zero echo buffer to avoid artifacts 2012-06-10 20:09:02 +02:00
Maximilian Rehkopf
ae4af50dac firmware: adjust SNES reset pulse 2012-06-10 20:08:31 +02:00
Maximilian Rehkopf
034b39588c FPGA: adjust menu memory mapping to make more room for file database 2012-06-10 20:07:45 +02:00
Maximilian Rehkopf
66f26c18b1 menu: make room for larger file database (adjust addresses) 2012-06-10 20:05:58 +02:00
Maximilian Rehkopf
96e178df2e firmware: make room for larger file database 2012-06-10 20:04:48 +02:00
Maximilian Rehkopf
f28516ea1c firmware: fix sort order (force parent dir at top of list) 2012-06-09 21:55:08 +02:00
Maximilian Rehkopf
242bde5684 firmware: file size adaptive ROM mirroring 2012-06-09 21:52:24 +02:00
Maximilian Rehkopf
8c2f74d8cd firmware: SPC player (necronomfive) 2012-06-09 21:51:15 +02:00
Maximilian Rehkopf
11bf7ffd5b firmware: case-insensitive system directory hiding 2012-06-09 21:50:34 +02:00
Maximilian Rehkopf
b01388b670 firmware: bump version number to 0.1.4 2012-06-09 21:48:53 +02:00
Maximilian Rehkopf
1f9dbe7d4c menu: fix occasional palette corruption (necronomfive) 2012-06-09 21:48:09 +02:00
Maximilian Rehkopf
798e23ec82 menu: show CPU/PPU revisions in system information (necronomfive) 2012-06-09 21:47:40 +02:00
Maximilian Rehkopf
f9c8e62f10 menu: SPC player (necronomfive, blargg) 2012-06-09 21:25:45 +02:00
Maximilian Rehkopf
c07b8f42c2 firmware/test suite: add missing file tests.c 2012-06-09 02:12:48 +02:00
Maximilian Rehkopf
2a1ef40796 FPGA/cx4: adjust Cx4 CPU timing 2012-05-19 18:07:13 +02:00
Maximilian Rehkopf
873bd84cd1 Firmware: set BS region override correctly 2012-05-02 12:13:58 +02:00
Maximilian Rehkopf
36dece67b8 Firmware: add basic BS download page file 2012-05-02 12:12:50 +02:00
Maximilian Rehkopf
de4308e3ba Firmware/BS: load BS download page file 2012-05-02 11:01:07 +02:00
Maximilian Rehkopf
6cff0f66e0 Firmware: auto-detect version number base in firmware image generator 2012-05-02 10:57:19 +02:00
Maximilian Rehkopf
dc478186e5 Firmware: add words of wisdom in README after switching from Ubuntu to Fedora Core ;-) 2012-05-02 10:51:18 +02:00
Maximilian Rehkopf
7109f9e030 FPGA: add SD clock pullup to test configuration 2012-05-02 10:46:27 +02:00
Maximilian Rehkopf
e63658e2ad FPGA: Map mode 21 SRAM to 20:xxxx as well 2012-05-02 10:46:01 +02:00
Maximilian Rehkopf
37a309fd0e FPGA: improve BS support (more date fields, initial download data support) 2012-05-02 10:42:46 +02:00
Maximilian Rehkopf
f5caf21fac FPGA: slightly tighten timing constraints 2012-05-02 10:41:07 +02:00
Maximilian Rehkopf
1b272a7a7d FPGA/Cx4: introduce wait states (fix MMX2 attract mode) 2012-05-02 10:30:22 +02:00
Maximilian Rehkopf
812a796568 PCB: add logo to Rev.E2 2012-05-02 10:24:15 +02:00
Maximilian Rehkopf
0f3138124e add missing files cfg.[ch] and sysinfo.[ch] 2012-04-16 15:22:53 +02:00
ikari
ea82765686 menu: fix xscroll bug when leaving directory 2012-03-03 21:26:01 +01:00
176 changed files with 29522 additions and 23781 deletions

22
.gitignore vendored Normal file
View File

@@ -0,0 +1,22 @@
*.cod
*.hex
*.lst
*.o
*.diff
.DS_Store
*.o65
*.ips
*.bin
*.map
*.o.d
*.log
*.smc
*.sfc
*~
*.old
*.elf
*.img
autoconf.h
utils/rle
utils/derle
*.bit

View File

@@ -38,3 +38,59 @@ v0.1.3
* Some FPGA configuration error detection (mainly useful for hardware diag)
* Fixes:
- FPGA-side SD clock pullup (increases reliability with some cards)
v0.1.4
======
* SPC Player (contributed by necronomfive/blargg)
* System Information screen now shows CPU/PPU revision (contributed by necronomfive)
* Satellaview: basic data transmission packet support (makes some more games boot, thanks to LuigiBlood for assistance and sample data packets)
* Number of supported files increased to 50000 per card / 16380 per directory
* Slight speedup of menu text rendering
* Reduce load time of menu
* Adjust Cx4 timing to be more faithful
(Mega Man now defeats the boss in attract mode in Mega Man X2)
* adapt ROM mirroring size to file size if header information is invalid
(fixes Super Noah's Ark 3D, possibly others)
* MSU1 interface changes suggested by byuu:
- Data offset 0 and audio track 0 are automatically requested on reset.
This causes the busy flags to become 0 shortly after reset/startup.
- $2000 bit 3 is now "audio error", becomes valid after "audio busy" -> 0
set when an error occurred while preparing playback of the requested audio track
* write LED stays on when SRAM content changes constantly
* Fixes:
- fix empty save files on FAT16 / incorrect free cluster count on FAT32
- correct directory sorting (force parent directory at top of list)
- fix text corruption when entering a directory with a scrollable name
- fix files/dirs count in system information
- make 'sd2snes' directory hiding case-insensitive
- improve DAC I²S timing
- fix occasional palette corruption in menu
- fix SD clock glitch on ROM loading (occasional glitches/crashes)
- fix memory write timing on ROM loading (occasional glitches/crashes)
- fix SPI timing (ROMs not loading; System Information not working)
- properly synchronize SNES control signals (occasional glitches/crashes)
- fix floating IRQ output (occasional glitches/slowdowns)
v0.1.4a (bugfix release)
========================
* Fix DMA initialization in the menu (could cause sprite corruption in some games)
v0.1.5
======
* Sort directories by entire file name instead of first 20 characters only
* Correctly map SRAM larger than 8192 bytes (HiROM) / 32768 bytes (LoROM)
(fixes Dezaemon, Ongaku Tsukuuru - Kanadeeru)
* SPC player: fix soft fade-in (first note cut off) on S-APU consoles
(1CHIP / some Jr.)
* More accurate BS-X memory map
* Ignore input from non-standard controllers (Super Scope, Mouse etc.)
* Fixes:
- minor memory access timing tweaks
(should help with occasional glitches on some systems)

BIN
bin/bsxpage.bin Normal file

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
OBJS = header.ips reset.o65 main.o65 font.o65 palette.o65 data.o65 const.o65 logo.o65 logospr.o65 text.o65 dma.o65 menu.o65 pad.o65 time.o65 mainmenu.o65 sysinfo.o65 # gfx.o65 # vars.o65
OBJS = header.ips reset.o65 main.o65 font.o65 palette.o65 data.o65 const.o65 logo.o65 logospr.o65 text.o65 dma.o65 menu.o65 pad.o65 time.o65 mainmenu.o65 sysinfo.o65 spc700.o65 spcplay.o65 # gfx.o65 # vars.o65
all: clean menu.bin map

View File

@@ -2,7 +2,8 @@ version .byt " v0.1",0
zero .word 0
bg2tile .byt $20
space64 .byt $20, $20, $20, $20, $20, $20, $20, $20
space64
.byt $20, $20, $20, $20, $20, $20, $20, $20
.byt $20, $20, $20, $20, $20, $20, $20, $20
.byt $20, $20, $20, $20, $20, $20, $20, $20
.byt $20, $20, $20, $20, $20, $20, $20, $20

View File

@@ -26,7 +26,8 @@ textdmasize .word 0 ; number of bytes to copy each frame
infloop .byt 0,0 ; to be filled w/ 80 FE
printloop_wram .byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
printloop_wram
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
@@ -34,7 +35,8 @@ printloop_wram .byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
loprint_wram .byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
loprint_wram
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
.byt 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

View File

@@ -168,4 +168,24 @@ text_mm_vmode_game .byt "Game video mode", 0
text_mm_sysinfo .byt "System Information", 0
text_statusbar_keys .byt "A:Select B:Back X:Menu", 0
text_last .byt "Run previous ROM: Press Start again to confirm", 0
text_system .byt "CPU Rev.: x PPU1 Rev.: y PPU2 Rev.: z",0
text_spcplay .byt "SPC Music Player", 0
spcplay_win_x .byt 15
spcplay_win_y .byt 15
spcplay_win_w .byt 33
spcplay_win_h .byt 5
text_spcload .byt "Loading SPC data to SPC700...", 0
text_spcstarta .byt "**** Now playing SPC tune ****", 0
text_spcstartb .byt "Name: ",0
text_spcstartc .byt "Song: ",0
text_spcstartd .byt "Artist:",0
spcstart_win_x .byt 10
spcstart_win_y .byt 13
spcstart_win_w .byt 44
spcstart_win_h .byt 9
text_spcid .byt "SNES-SPC700"

View File

@@ -16,7 +16,7 @@ dirend_onscreen .byt 0
dirlog_idx .byt 0,0,0 ; long ptr
direntry_fits_idx
.byt 0,0
longptr .byt 0,0,0 ; general purpose long ptr
;----------parameters for text output----------
print_x .byt 0 ;x coordinate
.byt 0
@@ -26,8 +26,8 @@ print_src .word 0 ;source data address
print_bank .byt 0 ;source data bank
print_pal .word 0 ;palette number for text output
print_temp .word 0 ;work variable
print_count .byt 0 ;how many characters may be printed?
print_count_tmp .byt 0 ;work variable
print_ptr .byt 0,0,0 ;read pointer
print_count .word 0 ;how many characters may be printed?
print_done .word 0 ;how many characters were printed?
print_over .byt 0 ;was the string printed incompletely?
;----------parameters for dma----------
@@ -184,4 +184,17 @@ direntry_xscroll
direntry_xscroll_wait
.word 0
infloop .byt 0,0 ; to be filled w/ 80 FE
tgt_bright
.byt 0
cur_bright
.byt 0
;------------------------
saved_sp
.word 0
warm_signature
.word 0
snes_system_config
.word 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
wram_fadeloop .byt 0

View File

@@ -1,21 +1,4 @@
dma0:
rep #$10 : .xl
sep #$20 : .as
lda dma_mode
sta $4300
lda dma_b_reg
sta $4301
lda dma_a_bank
ldx dma_a_addr
stx $4302
sta $4304
ldx dma_len
stx $4305
lda #$01
sta $420b
rts
setup_hdma:
sep #$20 : .as
rep #$10 : .xl
@@ -67,8 +50,11 @@ setup_hdma:
sty $4352
sta $4354
; lda #$06
; sta $420c ;enable HDMA ch. 1+2
lda #$3a
sta $420c ;enable HDMA ch. 1+3+4+5
jsr waitblank
lda #$3e
sta $420c ;enable HDMA ch. 2 too
lda #$81 ;VBlank NMI + Auto Joypad Read
sta $4200 ;enable V-BLANK NMI
rts

View File

@@ -1,13 +1,22 @@
#define hash #
#define f(x) x
#define imm(a) f(hash)a
#define DMA0(mode, len, a_bank, a_addr, b_reg)\
lda mode \
: sta dma_mode \
php \
: sep imm($20) : .as \
: rep imm($10) : .xl \
: lda mode \
: sta $4300 \
: ldx a_addr \
: lda a_bank \
: stx dma_a_addr \
: sta dma_a_bank \
: stx $4302 \
: sta $4304 \
: ldx len \
: stx dma_len \
: stx $4305 \
: lda b_reg \
: sta dma_b_reg \
: jsr dma0
: sta $4301 \
: lda imm($01) \
: sta $420b \
: plp

View File

@@ -4,13 +4,45 @@
GAME_MAIN:
sep #$20 : .as
lda #$00
sta @AVR_CMD
sta @MCU_CMD ; clear MCU command register
rep #$20 : .al
lda #$0000
sta @AVR_PARAM
sta @AVR_PARAM+2
sta @MCU_PARAM ; clear MCU command parameters
sta @MCU_PARAM+2
sep #$20 : .as
stz $4200 ; inhibit VBlank NMI
rep #$20 : .al
lda @warm_signature ; Was CMD_RESET issued before reset?
cmp #$fa50 ; If yes, then perform warm boot procedure
bne coldboot
lda #$0000
sta @warm_signature
lda @saved_sp ; Restore previous stack pointer
tcs
sep #$20 : .as
jsr killdma ; The following initialization processes must not touch memory
jsr waitblank ; structures used by the main menu !
jsr snes_init
cli
lda #$01
sta $420d ; fast cpu
jsr setup_gfx
jsr colortest
jsr tests
jsr setup_hdma
lda #$0f
sta cur_bright
sta tgt_bright
sta $2100
jmp @set_bank ; Set bios bank, just to be sure
set_bank:
plp ; Restore processor state
rts ; Jump to the routine which called the sub-routine issuing CMD_RESET
coldboot: ; Regular, cold-start init
sep #$20 : .as
jsr killdma
jsr waitblank
jsr snes_init
@@ -18,9 +50,11 @@ GAME_MAIN:
sta $420d ; fast cpu
jsr setup_gfx
jsr colortest
jsr setup_hdma
jsr menu_init
jsr tests
jsr setup_hdma
jsr screen_on
sep #$20 : .as
lda @RTC_STATUS
beq +
@@ -32,50 +66,93 @@ GAME_MAIN:
jmp @infloop ;infinite loop in WRAM
killdma:
stz $420b
stz $420c
stz $4300
stz $4301
stz $4302
stz $4303
stz $4304
stz $4305
stz $4306
stz $4307
stz $4308
stz $4309
stz $430a
stz $430b
stz $4310
stz $4311
stz $4312
stz $4313
stz $4314
stz $4315
stz $4316
stz $4317
stz $4318
stz $4319
stz $431a
stz $431b
stz $4320
stz $4321
stz $4322
stz $4323
stz $4324
stz $4325
stz $4326
stz $4327
stz $4328
stz $4329
stz $432a
stz $432b
stz $4330
stz $4331
stz $4332
stz $4333
stz $4334
stz $4335
stz $4336
stz $4337
stz $4338
stz $4339
stz $433a
stz $433b
stz $4340
stz $4341
stz $4342
stz $4343
stz $4344
stz $4345
stz $4346
stz $4347
stz $4348
stz $4349
stz $434a
stz $434b
stz $4350
stz $4351
stz $4352
stz $4353
stz $4354
stz $4360
stz $4361
stz $4362
stz $4363
stz $4364
stz $4355
stz $4356
stz $4357
stz $4358
stz $4359
stz $435a
stz $435b
stz $420b
stz $420c
rts
waitblank:
php
sep #$30 : .as : .xs
- lda $4212
and #$80
bne -
- lda $4212
and #$80
beq -
plp
rts
colortest:
@@ -91,11 +168,11 @@ setup_gfx:
stz $420b
stz $420c
;clear tilemap buffers
ldx #$0000
ldx #$8000
stx $2181
lda #$01
lda #$00
sta $2183
DMA0(#$08, #0, #^zero, #!zero, #$80)
DMA0(#$08, #$8000, #^zero, #!zero, #$80)
;generate fonts
jsr genfonts
@@ -146,6 +223,7 @@ setup_gfx:
;set palette
stz $2121
DMA0(#$00, #$200, #^palette, #!palette, #$22)
stz $2121
;copy hdma tables so we can work "without" the cartridge
;palette
@@ -198,7 +276,7 @@ setup_gfx:
tests:
sep #$20 : .as ;8-bit accumulator
rep #$10 : .xl ;16-bit index
lda #$03 ;mode 3, mode 5 via HDMA :D
lda #$03 ;mode 3, mode 5 via HDMA
sta $2105
lda #$58 ;Tilemap addr 0xB000
ora #$02 ;SC size 32x64
@@ -224,11 +302,17 @@ tests:
lda #$1f
sta $212e
sta $212f
stz $2121
lda #$0f
sta $2100 ;screen on, full brightness
lda #9
; stz $2121
lda #8
sta bar_yl
stz cur_bright
stz tgt_bright
rts
screen_on:
stz $2100 ;screen on, 0% brightness
lda #$0f
sta tgt_bright
rts
snes_init:
@@ -248,6 +332,7 @@ snes_init:
stz $420a ;
stz $420b ;
stz $420c ;
stz $420d ;
lda #$8f
sta $2100 ;INIDISP: force blank
lda #$03 ; 8x8+16x16; name=0; base=3
@@ -339,7 +424,7 @@ snes_init:
fadeloop:
sep #$30 : .as : .xs
ldx #$0f
ldx cur_bright
and #$00
pha
plb

View File

@@ -6,19 +6,24 @@
/* These must be defined as constants, because they're used
* in calculation that is sent to PPU as parameters */
#define APUIO0 $2140
#define APUIO1 $2141
#define APUIO2 $2142
#define APUIO3 $2143
#define BG1_TILE_BASE $5800
#define BG2_TILE_BASE $5000
#define OAM_TILE_BASE $6000
#define BG1_TILE_BUF $7FB000
#define BG2_TILE_BUF $7FA000
#define BG1_TILE_BUF $7EB000
#define BG2_TILE_BUF $7EA000
#define BG1_TILE_BAK $7F9000
#define BG2_TILE_BAK $7F8000
#define BG1_TILE_BAK $7E9000
#define BG2_TILE_BAK $7E8000
#define AVR_CMD $307000
#define AVR_PARAM $307004
#define MCU_CMD $307000
#define MCU_PARAM $307004
#define RTC_STATUS $307100
#define LAST_STATUS $307101
#define SYSINFO_BLK $307200
@@ -27,3 +32,9 @@
#define ROOT_DIR $C10000
#define CMD_SYSINFO $03
#define CMD_LOADSPC $05
#define CMD_RESET $06
#define SPC_DATA $FD0000
#define SPC_HEADER $FE0000
#define SPC_DSP_REGS $FE0100

View File

@@ -42,7 +42,6 @@ menuloop_s1
lda isr_done
lsr
bcc menuloop_s1
stz isr_done
jsr printtime
jsr menu_updates ;update stuff, check keys etc
@@ -272,6 +271,10 @@ dirent_is_file
lda #$0000
bra dirent_type_cont
+
cmp #$0003 ;SPC -> palette 2
bne +
lda #$0002
bra dirent_type_cont
cmp #$0004 ;IPS -> palette 2 (green)
bne +
lda #$0002
@@ -475,6 +478,8 @@ menu_key_start:
rts
menu_key_b:
stz direntry_xscroll
stz direntry_xscroll_state
rep #$20 : .al
lda dirstart_addr
beq skip_key_b
@@ -500,6 +505,8 @@ select_item:
lda [dirptr_addr], y
cmp #$01
beq sel_is_file
cmp #$03
beq sel_is_spc
cmp #$04
beq sel_is_file
cmp #$80
@@ -517,25 +524,28 @@ sel_is_parent
sel_is_dir
jsr select_dir
bra select_item_cont
sel_is_spc
jsr select_spc
bra select_item_cont
select_file:
; have avr load the rom
; have MCU load the rom
dey
rep #$20 : .al
lda [dirptr_addr], y
and #$00ff
sta @AVR_PARAM+2
sta @MCU_PARAM+2
dey
dey
lda [dirptr_addr], y
sta @AVR_PARAM
sta @MCU_PARAM
sep #$20 : .as
lda #$01
sta @AVR_CMD
select_file_fade:
lda #$00
sta @$4200
sei
lda #$01
sta @MCU_CMD
select_file_fade:
jsl @wram_fadeloop
rts
@@ -595,6 +605,8 @@ select_dir:
sta @dirstart_addr
lda #$0000
sta @menu_sel
sta @direntry_xscroll
sta @direntry_xscroll_state
sep #$20 : .as
lda #$01
sta @menu_dirty
@@ -633,6 +645,27 @@ select_parent:
sta @menu_dirty
rts
select_spc:
dey
rep #$20 : .al
lda [dirptr_addr], y
and #$00ff
sta @MCU_PARAM+2
dey
dey
lda [dirptr_addr], y
sta @MCU_PARAM
sep #$20 : .as
lda #CMD_LOADSPC
sta @MCU_CMD
wait_spc:
lda @MCU_CMD
cmp #$00
bne wait_spc
jsr spcplayer
jsr restore_screen
rts
menu_key_x:
jsr mainmenu
rts
@@ -772,7 +805,7 @@ select_last_file:
and pad1trig+1
beq -
lda #$04
sta @AVR_CMD
sta @MCU_CMD
jmp select_file_fade
+ jsr restore_screen
plp
@@ -848,6 +881,7 @@ scroll_direntry_scrollfast
lda #$28
sta direntry_xscroll_wait
+ lda direntry_xscroll_state
clc
adc direntry_xscroll
sta direntry_xscroll
bne +

View File

@@ -4,7 +4,15 @@ read_pad:
read_pad1
ldx pad1mem ;byetUDLRaxlriiii
lda $4218
ora $421a
and #$000f
bne +
lda $4218
+ sta pad1mem
lda $421a
and #$000f
bne +
lda $421a
+ ora pad1mem
sta pad1mem
and #$0f00
bne read_pad1_count

View File

@@ -84,9 +84,29 @@ math_cont
clc
adc bar_x ; + X start coord
sta $2127 ; window 1 right
lda #$3e ; ch. 1-5
sta @$420c ; trigger HDMA
lda #$01
; lda #$3e ; ch. 1-5
; sta @$420c ; trigger HDMA
lda cur_bright
cmp tgt_bright
beq +
bpl bright_down
bright_up
inc
sta cur_bright
lda $2100
and #$f0
ora cur_bright
sta $2100
bra +
bright_down
dec
sta cur_bright
lda $2100
and #$f0
ora cur_bright
sta $2100
+ lda #$01
sta isr_done
rtl

61
snes/spc700.a65 Normal file
View File

@@ -0,0 +1,61 @@
; All SPC700 routines in SPC700 machine code
; SPC loader & transfer routines by Shay Green <gblargg@gmail.com>
loader ; .org $0002
.byt $F8,$21 ; mov x,@loader_data
.byt $BD ; mov sp,x
.byt $CD,$22 ; mov x,#@loader_data+1
; Push PC and PSW from SPC header
.byt $BF ; mov a,(x)+
.byt $2D ; push a
.byt $BF ; mov a,(x)+
.byt $2D ; push a
.byt $BF ; mov a,(x)+
.byt $2D ; push a
; Set FLG to $60 rather than value from SPC
.byt $E8,$60 ; mov a,#$60
.byt $D4,$6C ; mov FLG+x,a
; Restore DSP registers
.byt $8D,$00 ; mov y,#0
.byt $BF ; next: mov a,(x)+
.byt $CB,$F2 ; mov $F2,y
.byt $C4,$F3 ; mov $F3,a
.byt $FC ; inc y
.byt $10,-8 ; bpl next
.byt $8F,$6C,$F2 ; mov $F2,#FLG ; set for later
; Rerun loader
.byt $5F,$C0,$FF ; jmp $FFC0
;---------------------------------------
transfer ; .org $0002
.byt $CD,$FE ; mov x,#$FE ; transfer 254 pages
; Transfer four-byte chunks
.byt $8D,$3F ; page: mov y,#$3F
.byt $E4,$F4 ; quad: mov a,$F4
.byt $D6,$00,$02 ; mov0: mov !$0200+y,a
.byt $E4,$F5 ; mov a,$F5
.byt $D6,$40,$02 ; mov1: mov !$0240+y,a
.byt $E4,$F6 ; mov a,$F6
.byt $D6,$80,$02 ; mov2: mov !$0280+y,a
.byt $E4,$F7 ; mov a,$F7 ; tell S-CPU we're ready for more
.byt $CB,$F7 ; mov $F7,Y
.byt $D6,$C0,$02 ; mov3: mov !$02C0+y,a
.byt $DC ; dec y
.byt $10,-25 ; bpl quad
; Increment MSBs of addresses
.byt $AB,$0A ; inc mov0+2
.byt $AB,$0F ; inc mov1+2
.byt $AB,$14 ; inc mov2+2
.byt $AB,$1B ; inc mov3+2
.byt $1D ; dec x
.byt $D0,-38 ; bne page
; Rerun loader
.byt $5F,$C0,$FF ; jmp $FFC0

676
snes/spcplay.a65 Normal file
View File

@@ -0,0 +1,676 @@
#include "memmap.i65"
; SPC Player
; SPC700 transfer and IO routines by Shay Green <gblargg@gmail.com>
spcplayer:
php
sep #$30 : .as : .xs
ldx #$0a ; Check if SPC header is present
-
lda @SPC_HEADER,x
cmp @text_spcid,x
beq +
jmp spc_exit
+
dey
bne -
rep #$10 : .xl ; Now draw lots of stuff
stz bar_wl
dec bar_wl
stz bar_xl
dec bar_xl
stz bar_yl
dec bar_yl
jsr backup_screen
lda #^text_spcplay ; Loading window
sta window_tbank
ldx #!text_spcplay
stx window_taddr
lda @spcplay_win_x
sta window_x
lda @spcplay_win_y
sta window_y
lda @spcplay_win_w
sta window_w
lda @spcplay_win_h
sta window_h
jsr draw_window
lda #^text_spcload ; Loading text
ldx #!text_spcload
sta print_bank
stx print_src
stz print_pal
lda #29
sta print_count
lda #17
sta print_y
lda #17
sta print_x
jsr hiprint
stz isr_done
-
lda isr_done ; Wait until text is being printed...
beq -
jsr spc700_load ; Load SPC into SPC700
lda #^text_spcplay
sta window_tbank
ldx #!text_spcplay
stx window_taddr
lda @spcstart_win_x
sta window_x
lda @spcstart_win_y
sta window_y
lda @spcstart_win_w
sta window_w
lda @spcstart_win_h
sta window_h
jsr draw_window
lda #^text_spcstarta
ldx #!text_spcstarta
sta print_bank
stx print_src
lda #$01
sta print_pal
lda #30
sta print_count
lda #15
sta print_y
lda #17
sta print_x
jsr hiprint
lda #^text_spcstartb
ldx #!text_spcstartb
sta print_bank
stx print_src
lda #$01
sta print_pal
lda #07
sta print_count
lda #17
sta print_y
lda #12
sta print_x
jsr hiprint
lda #$fe
ldx #$004e
sta print_bank
stx print_src
stz print_pal
lda #32
sta print_count
lda #17
sta print_y
lda #20
sta print_x
jsr hiprint
lda #^text_spcstartc
ldx #!text_spcstartc
sta print_bank
stx print_src
lda #$01
sta print_pal
lda #07
sta print_count
lda #18
sta print_y
lda #12
sta print_x
jsr hiprint
lda #$fe
ldx #$002e
sta print_bank
stx print_src
stz print_pal
lda #32
sta print_count
lda #18
sta print_y
lda #20
sta print_x
jsr hiprint
lda #^text_spcstartd
ldx #!text_spcstartd
sta print_bank
stx print_src
lda #$01
sta print_pal
lda #07
sta print_count
lda #19
sta print_y
lda #12
sta print_x
jsr hiprint
lda #$fe
ldx #$00b0
sta longptr+2
sta print_bank
stx longptr
ldy #$00
lda [longptr], y
cmp #$41
bpl +
inx
+ stx print_src
stz print_pal
lda #32
sta print_count
lda #19
sta print_y
lda #20
sta print_x
jsr hiprint
spc_playloop:
lda isr_done ; SPC player loop
lsr
bcc spc_playloop
jsr printtime
stz isr_done
jsr read_pad
lda #$80
and pad1trig+1
bne spc_key_b
bra spc_playloop
spc_key_b:
rep #$20 : .al
tsc
sta saved_sp ; Save SP for later re-entry
lda #$fa50 ; Write reset signature
sta @warm_signature
sep #$20 : .as
sei ; Blank screen & issue CMD_RESET command to Microcontroller...
stz $2100 ; ...this is required, because there is no other way to stop S-SMP & S-DSP
lda #CMD_RESET
sta @MCU_CMD
-
bra - ; At this point, the SNES waits for an external reset from the Microcontroller
spc_exit: ; Return from player in case of wrong SPC file data
plp
rts
;---------------------------------------
spc700_load:
php
sep #$20 : .as
rep #$10 : .xl
sei ; Disable NMI & IRQ
stz $4200 ; The SPC player code is really timing sensitive ;)
jsr upload_dsp_regs ; Upload S-DSP registers
jsr upload_high_ram ; Upload 63.5K of SPC700 ram
jsr upload_low_ram ; Upload rest of ram
jsr restore_final ; Restore SPC700 state & start execution
lda #$81 ; VBlank NMI + Auto Joypad Read
sta $4200 ; enable V-BLANK NMI
cli
plp
rts
;---------------------------------------
; Uploads DSP registers and some other setup code
upload_dsp_regs:
; ---- Begin upload
ldy #$0002
jsr spc_begin_upload
; ---- Upload loader
ldx #$0000
-
lda @loader,x
jsr spc_upload_byte
inx
cpy #31 ; size of loader
bne -
; ---- Upload SP, PC & PSW
lda @SPC_HEADER+43
jsr spc_upload_byte
lda @SPC_HEADER+38
jsr spc_upload_byte
lda @SPC_HEADER+37
jsr spc_upload_byte
lda @SPC_HEADER+42
jsr spc_upload_byte
; ---- Upload DSP registers
ldx #$0000
-
; initialize FLG and KON ($6c/$4c) to avoid artifacts
cpx #$4C
bne +
lda #$00
bra upload_skip_load
+
cpx #$6C
bne +
lda #$E0
bra upload_skip_load
+
lda @SPC_DSP_REGS,x
upload_skip_load
jsr spc_upload_byte
inx
cpx #128
bne -
; --- Upload fixed values for $F1-$F3
ldy #$00F1
jsr spc_next_upload
lda #$80 ; stop timers
jsr spc_upload_byte
lda #$6c ; get dspaddr set for later
jsr spc_upload_byte
lda #$60
jsr spc_upload_byte
; ---- Upload $f8-$1ff
ldy #$00F8
jsr spc_next_upload
ldx #$00F8
-
lda @SPC_DATA,x
jsr spc_upload_byte
inx
cpx #$200
bne -
; ---- Execute loader
ldy #$0002
jsr spc_execute
rts
;---------------------------------------
upload_high_ram:
ldy #$0002
jsr spc_begin_upload
; ---- Upload transfer routine
ldx #$0000
-
lda @transfer,x
jsr spc_upload_byte
inx
cpy #43 ; size of transfer routine
bne -
ldx #$023f ; prepare transfer address
; ---- Execute transfer routine
ldy #$0002
sty APUIO2
stz APUIO1
lda APUIO0
inc
inc
sta APUIO0
; Wait for acknowledgement
-
cmp APUIO0
bne -
; ---- Burst transfer of 63.5K using custom routine
outer_transfer_loop:
ldy #$003f ; 3
inner_transfer_loop:
lda @SPC_DATA,x ; 5 |
sta APUIO0 ; 4 |
lda @SPC_DATA+$40,x ; 5 |
sta APUIO1 ; 4 |
lda @SPC_DATA+$80,x ; 5 |
sta APUIO2 ; 4 |
lda @SPC_DATA+$C0,x ; 5 |
sta APUIO3 ; 4 |
tya ; 2 >> 38 cycles
-
cmp APUIO3 ; 4 |
bne - ; 3 |
dex ; 2 |
dey ; 2 |
bpl inner_transfer_loop ; 3 >> 14 cycles
rep #$21 : .al ; 3 |
txa ; 2 |
adc #$140 ; 3 |
tax ; 2 |
sep #$20 : .as ; 3 |
cpx #$003f ; 3 |
bne outer_transfer_loop ; 3 >> 19 cycles
rts
;---------------------------------------
upload_low_ram:
; ---- Upload $0002-$00EF using IPL
ldy #$0002
jsr spc_begin_upload
ldx #$0002
-
lda @SPC_DATA,x
jsr spc_upload_byte
inx
cpx #$00F0
bne -
rts
;---------------------------------------
; Executes final restoration code
restore_final:
jsr start_exec_io ; prepare execution from I/O registers
stz $420d ; SPC700 I/O code requires SLOW timing
; ---- Restore first two bytes of RAM
lda @SPC_DATA
xba
lda #$e8 ; MOV A,#@SPC_DATA
tax
jsr exec_instr
ldx #$00C4 ; MOV $00,A
jsr exec_instr
lda @SPC_DATA+1
xba
lda #$e8 ; MOV A,#@SPC_DATA+1
tax
jsr exec_instr
ldx #$01C4 ; MOV $01,A
jsr exec_instr
; ---- Restore SP
lda @SPC_HEADER+43
sec
sbc #3
xba
lda #$cd ; MOV X,#@SPC_HEADER+43
tax
jsr exec_instr
ldx #$bd ; MOV SP,X
jsr exec_instr
; ---- Restore X
lda @SPC_HEADER+40
xba
lda #$cd ; MOV X,#@SPC_HEADER+40
tax
jsr exec_instr
; ---- Restore Y
lda @SPC_HEADER+41
xba
lda #$8d ; MOV Y,#@SPC_HEADER+41
tax
jsr exec_instr
; ---- Restore DSP FLG register
lda @SPC_DSP_REGS+$6c
xba
lda #$e8 ; MOV A,#@SPC_DSP_REGS+$6c
tax
jsr exec_instr
ldx #$f3C4 ; MOV $f3,A -> $f2 has been set-up before by SPC700 loader
jsr exec_instr
; ---- wait a bit (the newer S-APU takes its time to ramp up the volume)
lda #$10
- pha
jsr waitblank
pla
dec
bne -
; ---- Restore DSP KON register
lda #$4C
xba
lda #$e8 ; MOV A,#$4c
tax
jsr exec_instr
ldx #$f2C4 ; MOV $f2,A
jsr exec_instr
lda @SPC_DSP_REGS+$4C
xba
lda #$e8 ; MOV A,#@SPC_DSP_REGS+$4c
tax
jsr exec_instr
ldx #$f3C4 ; MOV $f3,A
jsr exec_instr
; ---- Restore DSP register address
lda @SPC_DATA+$F2
xba
lda #$e8 ; MOV A,#@SPC_DATA+$F2
tax
jsr exec_instr
ldx #$f2C4 ; MOV dest,A
jsr exec_instr
; ---- Restore CONTROL register
lda @SPC_DATA+$F1
and #$CF ; don't clear input ports
xba
lda #$e8 ; MOV A,#@SPC_DATA+$F1
tax
jsr exec_instr
ldx #$f1C4 ; MOV $F1,A
jsr exec_instr
;---- Restore A
lda @SPC_HEADER+39
xba
lda #$e8 ; MOV A,#@SPC_HEADER+39
tax
jsr exec_instr
;---- Restore PSW and PC
ldx #$7F00 ; NOP; RTI
stx APUIO0
lda #$FC ; Patch loop to execute instruction just written
sta APUIO3
;---- restore IO ports $f4 - $f7
rep #$20 : .al
lda @SPC_DATA+$F4
tax
lda @SPC_DATA+$F6
sta APUIO2
stx APUIO0 ; last to avoid overwriting RETI before run
sep #$20 : .as
lda #$01
sta $420d ; restore FAST CPU operation
rts
;---------------------------------------
spc_begin_upload:
sty APUIO2 ; Set address
ldy #$BBAA ; Wait for SPC
-
cpy APUIO0
bne -
lda #$CC ; Send acknowledgement
sta APUIO1
sta APUIO0
- ; Wait for acknowledgement
cmp APUIO0
bne -
ldy #0 ; Initialize index
rts
;---------------------------------------
spc_upload_byte:
sta APUIO1
tya ; Signal it's ready
sta APUIO0
- ; Wait for acknowledgement
cmp APUIO0
bne -
iny
rts
;---------------------------------------
spc_next_upload:
sty APUIO2
; Send command
; Special case operation has been fully tested.
lda APUIO0
inc
inc
bne +
inc
+
sta APUIO1
sta APUIO0
; Wait for acknowledgement
-
cmp APUIO0
bne -
ldy #0
rts
;---------------------------------------
spc_execute:
sty APUIO2
stz APUIO1
lda APUIO0
inc
inc
sta APUIO0
; Wait for acknowledgement
-
cmp APUIO0
bne -
rts
;---------------------------------------
start_exec_io:
; Set execution address
ldx #$00F5
stx APUIO2
stz APUIO1 ; NOP
ldx #$FE2F ; BRA *-2
; Signal to SPC that we're ready
lda APUIO0
inc
inc
sta APUIO0
; Wait for acknowledgement
-
cmp APUIO0
bne -
; Quickly write branch
stx APUIO2
rts
;---------------------------------------
exec_instr:
; Replace instruction
stx APUIO0
lda #$FC
sta APUIO3 ; 30
; SPC BRA loop takes 4 cycles, so it reads
; the branch offset every 4 SPC cycles (84 master).
; We must handle the case where it read just before
; the write above, and when it reads just after it.
; If it reads just after, we have at least 7 SPC
; cycles (147 master) to change restore the branch
; offset.
; 48 minimum, 90 maximum
ora #0
ora #0
ora #0
nop
nop
nop
; 66 delay, about the middle of the above limits
phd ;4
pld ;5
; Give plenty of extra time if single execution
; isn't needed, as this avoids such tight timing
; requirements.
; phd ;4
; pld ;5
; phd ;4
; pld ;5
; Patch loop to skip first two bytes
lda #$FE ; 16
sta APUIO3 ; 30
; 38 minimum (assuming 66 delay above)
phd ; 4
pld ; 5
; Give plenty of extra time if single execution
; isn't needed, as this avoids such tight timing
; requirements.
phd
pld
phd
pld
rts

View File

@@ -35,11 +35,19 @@ show_sysinfo:
sta window_h
jsr draw_window
stz print_pal
ldx #38
copy_snes_system_text:
lda @text_system,x
sta @snes_system_config,x
dex
bpl copy_snes_system_text
sysinfo_printloop:
sep #$20 : .as
rep #$10 : .xl
lda #CMD_SYSINFO
sta @AVR_CMD
sta @MCU_CMD
lda #^SYSINFO_BLK
ldx #!SYSINFO_BLK
sta print_bank
@@ -51,7 +59,7 @@ sysinfo_printloop:
sta print_x
lda #40
sta print_count
lda #13
lda #12
- pha
jsr hiprint
inc print_y
@@ -64,6 +72,41 @@ sysinfo_printloop:
pla
dec
bne -
ldx #24
lda $213e
and #$0f
clc
adc #$30
sta @snes_system_config,x
ldx #38
lda $213f
and #$0f
clc
adc #$30
sta @snes_system_config,x
ldx #10
lda $4210
and #$0f
clc
adc #$30
sta @snes_system_config,x
lda #^snes_system_config ; System text
ldx #!snes_system_config
sta print_bank
stx print_src
stz print_pal
lda #39
sta print_count
lda #23
sta print_y
lda #12
sta print_x
jsr hiprint
- lda isr_done
lsr
bcc -
@@ -87,5 +130,5 @@ sysinfo_printloop:
+ plp
jsr restore_screen
lda #$00
sta @AVR_CMD
sta @MCU_CMD
rtl

View File

@@ -1,146 +1,95 @@
.text
#include "memmap.i65"
.byt "===HIPRINT==="
; input:
; print_count
; print_x
; print_y
; print_src
; print_bank
; print_pal
;
; output:
; print_done (# of chars printed)
; print_over (char after print_count)
hiprint:
php
sep #$20 : .as
lda print_count
sta print_count_tmp
stz print_over
rep #$30 : .xl : .al
stz print_done
lda print_x
and #$00ff
lsr
bcs print_bg1
ldx #!BG1_TILE_BUF ; for 2nd loop
phx
ldx #!BG2_TILE_BUF ; for 1st loop
phx
bra print_bg_cont
print_bg1
ldx #!BG2_TILE_BUF+2 ; for 2nd loop
phx
ldx #!BG1_TILE_BUF ; for 1st loop da whoop
phx
bra print_bg_cont
print_bg_cont
sta !print_temp
lda !print_y
and #$00ff
asl
asl
asl
asl
asl
clc
adc !print_temp
asl ; double the offset for WRAM addressing
tay ; zonday
plx
phy ; offset from tilemap start
stx !print_temp
clc
adc !print_temp
; we need to transfer to WRAM and from there to VRAM via DMA during VBLANK
; because VRAM can only be accessed during VBLANK and forced blanking.
sta $2181
sep #$20 : .as
lda #$7f ;we really only need bit 0. full bank given for clarity
sta $2183
print_loop
ldx !print_src
lda !print_bank
pha
plb
phx ; source addr
print_loop_inner
lda !0,x
bne +
jmp print_end2
+ asl
sta @$2180
lda @print_pal
asl
asl
adc #$00
ora #$20
sta @$2180
lda @print_done
inc
sta @print_done
inx
lda !0,x
beq print_loop2
inx
lda !0,x
beq print_loop2
lda @print_count_tmp
dec
dec
sta @print_count_tmp
beq print_loop2
bmi print_loop2
bra print_loop_inner
print_loop2
lda @print_count
dec
sta @print_count_tmp
beq print_end2
lda #$00
rep #$10 : .xl
ldx print_src
stx print_ptr
lda print_bank
sta print_ptr+2
phb
lda #$7e
pha
plb
rep #$30 : .al : .xl
ply ; source addr
iny
pla ; offset from tilemap start
plx ; other tilemap addr
stx !print_temp
lda print_pal
and #$00ff
xba
asl
asl
ora #$2000
sta print_temp
lda print_count
and #$00ff
beq hiprint_end
tay
lda print_x
and #$00ff
sta print_x
lda print_y
and #$00ff
asl
asl
asl
asl
asl
asl
clc
adc !print_temp ; tilemap+offset
sta $2181
tyx
adc print_x
and #$fffe
tax
lda print_x
lsr
bcs hiprint_bg1
hiprint_bg2
lda [print_ptr]
and #$00ff
beq hiprint_end
inc print_ptr
asl
ora print_temp
sta !BG2_TILE_BUF, x
dey
beq hiprint_end
hiprint_bg1
lda [print_ptr]
and #$00ff
beq hiprint_end
inc print_ptr
asl
ora print_temp
sta !BG1_TILE_BUF, x
inx
inx
dey
beq hiprint_end
bra hiprint_bg2
hiprint_end
plb
sep #$20 : .as
lda print_bank
pha
plb
print_loop2_inner
lda !0,x
bne +
jmp print_end
+ asl
sta @$2180
lda @print_pal
asl
asl
adc #$00
ora #$20
sta @$2180
lda @print_done
lda [print_ptr]
sta print_over
tya
sec
sbc print_count
eor #$ff
inc
sta @print_done
inx
lda !0,x
beq print_end
lda @print_count_tmp
dec
dec
sta @print_count_tmp
beq print_end
bmi print_end
inx
lda !0,x
beq print_end
bra print_loop2_inner
print_end2 ; clean up the stack (6 bytes)
ply
ply
ply
print_end
lda !0,x
sta @print_over
lda #$00
pha
plb
sta print_done
plp
rts
@@ -290,6 +239,7 @@ draw_window:
sta print_count
jsr hiprint
lda print_done
clc
adc print_x
sta print_x
lda #^window_tr

View File

@@ -499,6 +499,8 @@ time_dec_y1_normal
rts
gettime
php
sep #$20 : .as
lda #$0d
sta $2801
lda $2800
@@ -526,6 +528,7 @@ gettime
sta time_y10
lda $2800
sta time_y100
plp
rts
rendertime
@@ -677,31 +680,31 @@ is_leapyear_400th
settime
lda time_y100
sta @AVR_PARAM
sta @MCU_PARAM
lda time_y10
sta @AVR_PARAM+1
sta @MCU_PARAM+1
lda time_y1
sta @AVR_PARAM+2
sta @MCU_PARAM+2
lda time_mon
sta @AVR_PARAM+3
sta @MCU_PARAM+3
lda time_d10
sta @AVR_PARAM+4
sta @MCU_PARAM+4
lda time_d1
sta @AVR_PARAM+5
sta @MCU_PARAM+5
lda time_h10
sta @AVR_PARAM+6
sta @MCU_PARAM+6
lda time_h1
sta @AVR_PARAM+7
sta @MCU_PARAM+7
lda time_m10
sta @AVR_PARAM+8
sta @MCU_PARAM+8
lda time_m1
sta @AVR_PARAM+9
sta @MCU_PARAM+9
lda time_s10
sta @AVR_PARAM+10
sta @MCU_PARAM+10
lda time_s1
sta @AVR_PARAM+11
sta @MCU_PARAM+11
lda #$02 ; set clock
sta @AVR_CMD
sta @MCU_CMD
rts
printtime:

View File

@@ -55,7 +55,7 @@ TARGET = $(OBJDIR)/sd2snes
# List C source files here. (C dependencies are automatically generated.)
SRC = main.c ff.c ccsbcs.c clock.c uart.c power.c led.c timer.c printf.c spi.c fileops.c rtc.c fpga.c fpga_spi.c snes.c smc.c memory.c filetypes.c faulthandler.c sort.c crc32.c cic.c cli.c xmodem.c irq.c rle.c sdnative.c msu1.c crc16.c sysinfo.c cfg.c
SRC = main.c ff.c ccsbcs.c clock.c uart.c power.c led.c timer.c printf.c spi.c fileops.c rtc.c fpga.c fpga_spi.c snes.c smc.c memory.c filetypes.c faulthandler.c sort.c crc32.c cic.c cli.c xmodem.c irq.c rle.c sdnative.c msu1.c crc16.c sysinfo.c cfg.c tests.c
# usbcontrol.c usb_hid.c usbhw_lpc.c usbinit.c usbstdreq.c
@@ -75,7 +75,7 @@ ASRC = startup.S crc.S
# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
# Use s -mcall-prologues when you really need size...
#OPT = 2
OPT = 2
OPT = s
# Debugging format.
DEBUG = dwarf-2
@@ -124,7 +124,8 @@ NM = $(ARCH)-nm
REMOVE = rm -f
COPY = cp
AWK = awk
RLE = ../utils/rle
BIN2H = utils/bin2h
#---------------- Compiler Options ----------------
# -g*: generate debugging information
@@ -197,7 +198,7 @@ ALL_ASFLAGS = -I. -x assembler-with-cpp $(ASFLAGS) $(CDEFS)
# Default target.
all: build
build: elf bin hex
build: snesboot.h cfgware.h elf bin hex
$(E) " SIZE $(TARGET).elf"
$(Q)$(ELFSIZE)|grep -v debug
cp $(TARGET).bin $(OBJDIR)/firmware.img
@@ -217,19 +218,37 @@ sym: $(TARGET).sym
program: build
utils/lpcchksum $(TARGET).bin
openocd -f openocd-usb.cfg -f lpc1754.cfg -f flash.cfg
openocd -f interface/olimex-arm-usb-ocd.cfg -f lpc1754.cfg -f flash.cfg
debug: build
openocd -f openocd-usb.cfg -f lpc1754.cfg
openocd -f interface/olimex-arm-usb-ocd.cfg -f lpc1754.cfg
reset:
openocd -f openocd-usb.cfg -f lpc1754.cfg -f reset.cfg
openocd -f interface/olimex-arm-usb-ocd.cfg -f lpc1754.cfg -f reset.cfg
# Display size of file.
HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
ELFSIZE = $(SIZE) -A $(TARGET).elf
# Generate cfgware.h
cfgware.h: $(OBJDIR)/fpga_rle.bit
$(E) " BIN2H $@"
$(Q) $(BIN2H) $< $@ cfgware
$(OBJDIR)/fpga_rle.bit: ../verilog/sd2sneslite/main.bit
$(E) " RLE $@"
$(Q) $(RLE) $< $@
#generate snesboot.h
snesboot.h: $(OBJDIR)/snesboot.rle
$(E) " BIN2H $@"
$(Q) $(BIN2H) $< $@ bootrle
$(OBJDIR)/snesboot.rle: ../snes/boot/menu.bin
$(E) " RLE $@"
$(Q) $(RLE) $< $@
# Generate autoconf.h from config
.PRECIOUS : $(OBJDIR)/autoconf.h
@@ -302,6 +321,7 @@ clean_list :
$(Q)$(REMOVE) $(TARGET).sym
$(Q)$(REMOVE) $(TARGET).lss
$(Q)$(REMOVE) $(OBJ)
$(Q)$(REMOVE) cfgware.h
$(Q)$(REMOVE) $(OBJDIR)/autoconf.h
$(Q)$(REMOVE) $(OBJDIR)/*.bin
$(Q)$(REMOVE) $(LST)

View File

@@ -25,6 +25,7 @@ b) Cortex M3 toolchain
- libexpat-dev
- make
- gcc
Package names may differ for your distribution.
Newer gccs complain when compiling binutils, so you may have to add
'--disable-werror' to the compiler options for binutils in the Makefile.
The Makefile will install immediately so make sure you can write to the

View File

@@ -4,14 +4,14 @@
/* The classic macro */
#define BV(x) (1<<(x))
/* CM3 bit-band access macro - no error checks! */
#define BITBAND(addr,bit) \
/* CM3 bit-bang access macro - no error checks! */
#define BITBANG(addr,bit) \
(*((volatile unsigned long *)( \
((unsigned long)&(addr) & 0x01ffffff)*32 + \
(bit)*4 + 0x02000000 + ((unsigned long)&(addr) & 0xfe000000) \
)))
#define BITBAND_OFF(addr,offset,bit) \
#define BITBANG_OFF(addr,offset,bit) \
(*((volatile unsigned long *)( \
(((unsigned long)&(addr) + offset) & 0x01ffffff)*32 + \
(bit)*4 + 0x02000000 + (((unsigned long)&(addr) + offset) & 0xfe000000) \

View File

@@ -31,7 +31,8 @@
#if _CODE_PAGE == 437
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP437(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP437(0x80-0xFF) to Unicode conversion table */
{
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
@@ -53,7 +54,8 @@ const WCHAR Tbl[] = { /* CP437(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 720
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP720(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP720(0x80-0xFF) to Unicode conversion table */
{
0x0000, 0x0000, 0x00E9, 0x00E2, 0x0000, 0x00E0, 0x0000, 0x00E7,
0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0000, 0x0000, 0x0000,
0x0000, 0x0651, 0x0652, 0x00F4, 0x00A4, 0x0640, 0x00FB, 0x00F9,
@@ -75,7 +77,8 @@ const WCHAR Tbl[] = { /* CP720(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 737
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP737(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP737(0x80-0xFF) to Unicode conversion table */
{
0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398,
0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0,
0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9,
@@ -97,7 +100,8 @@ const WCHAR Tbl[] = { /* CP737(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 775
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP775(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP775(0x80-0xFF) to Unicode conversion table */
{
0x0106, 0x00FC, 0x00E9, 0x0101, 0x00E4, 0x0123, 0x00E5, 0x0107,
0x0142, 0x0113, 0x0156, 0x0157, 0x012B, 0x0179, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x014D, 0x00F6, 0x0122, 0x00A2, 0x015A,
@@ -119,7 +123,8 @@ const WCHAR Tbl[] = { /* CP775(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 850
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP850(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP850(0x80-0xFF) to Unicode conversion table */
{
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
@@ -141,7 +146,8 @@ const WCHAR Tbl[] = { /* CP850(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 852
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP852(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP852(0x80-0xFF) to Unicode conversion table */
{
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x016F, 0x0107, 0x00E7,
0x0142, 0x00EB, 0x0150, 0x0151, 0x00EE, 0x0179, 0x00C4, 0x0106,
0x00C9, 0x0139, 0x013A, 0x00F4, 0x00F6, 0x013D, 0x013E, 0x015A,
@@ -163,7 +169,8 @@ const WCHAR Tbl[] = { /* CP852(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 855
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP855(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP855(0x80-0xFF) to Unicode conversion table */
{
0x0452, 0x0402, 0x0453, 0x0403, 0x0451, 0x0401, 0x0454, 0x0404,
0x0455, 0x0405, 0x0456, 0x0406, 0x0457, 0x0407, 0x0458, 0x0408,
0x0459, 0x0409, 0x045A, 0x040A, 0x045B, 0x040B, 0x045C, 0x040C,
@@ -185,7 +192,8 @@ const WCHAR Tbl[] = { /* CP855(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 857
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP857(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP857(0x80-0xFF) to Unicode conversion table */
{
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0131, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
@@ -207,7 +215,8 @@ const WCHAR Tbl[] = { /* CP857(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 858
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP858(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP858(0x80-0xFF) to Unicode conversion table */
{
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
@@ -229,7 +238,8 @@ const WCHAR Tbl[] = { /* CP858(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 862
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP862(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP862(0x80-0xFF) to Unicode conversion table */
{
0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7,
0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7,
@@ -251,7 +261,8 @@ const WCHAR Tbl[] = { /* CP862(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 866
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP866(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP866(0x80-0xFF) to Unicode conversion table */
{
0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
@@ -273,7 +284,8 @@ const WCHAR Tbl[] = { /* CP866(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 874
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP874(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP874(0x80-0xFF) to Unicode conversion table */
{
0x20AC, 0x0000, 0x0000, 0x0000, 0x0000, 0x2026, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
@@ -295,7 +307,8 @@ const WCHAR Tbl[] = { /* CP874(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 1250
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP1250(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP1250(0x80-0xFF) to Unicode conversion table */
{
0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021,
0x0000, 0x2030, 0x0160, 0x2039, 0x015A, 0x0164, 0x017D, 0x0179,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
@@ -317,7 +330,8 @@ const WCHAR Tbl[] = { /* CP1250(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 1251
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP1251(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP1251(0x80-0xFF) to Unicode conversion table */
{
0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021,
0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F,
0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
@@ -339,7 +353,8 @@ const WCHAR Tbl[] = { /* CP1251(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 1252
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP1252(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP1252(0x80-0xFF) to Unicode conversion table */
{
0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x017D, 0x0000,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
@@ -361,7 +376,8 @@ const WCHAR Tbl[] = { /* CP1252(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 1253
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP1253(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP1253(0x80-0xFF) to Unicode conversion table */
{
0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
0x0000, 0x2030, 0x0000, 0x2039, 0x000C, 0x0000, 0x0000, 0x0000,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
@@ -383,7 +399,8 @@ const WCHAR Tbl[] = { /* CP1253(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 1254
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP1254(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP1254(0x80-0xFF) to Unicode conversion table */
{
0x20AC, 0x0000, 0x210A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
@@ -405,7 +422,8 @@ const WCHAR Tbl[] = { /* CP1254(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 1255
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP1255(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP1255(0x80-0xFF) to Unicode conversion table */
{
0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
0x02C6, 0x2030, 0x0000, 0x2039, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
@@ -427,7 +445,8 @@ const WCHAR Tbl[] = { /* CP1255(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 1256
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP1256(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP1256(0x80-0xFF) to Unicode conversion table */
{
0x20AC, 0x067E, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
0x02C6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688,
0x06AF, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
@@ -449,7 +468,8 @@ const WCHAR Tbl[] = { /* CP1256(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 1257
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP1257(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP1257(0x80-0xFF) to Unicode conversion table */
{
0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021,
0x0000, 0x2030, 0x0000, 0x2039, 0x0000, 0x00A8, 0x02C7, 0x00B8,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
@@ -471,7 +491,8 @@ const WCHAR Tbl[] = { /* CP1257(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 1258
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP1258(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP1258(0x80-0xFF) to Unicode conversion table */
{
0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
0x02C6, 0x2030, 0x0000, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
@@ -506,17 +527,28 @@ WCHAR ff_convert ( /* Converted character, Returns zero on error */
WCHAR c;
if (src < 0x80) { /* ASCII */
if ( src < 0x80 ) /* ASCII */
{
c = src;
} else {
if (dir) { /* OEMCP to Unicode */
}
else
{
if ( dir ) /* OEMCP to Unicode */
{
c = ( src >= 0x100 ) ? 0 : Tbl[src - 0x80];
} else { /* Unicode to OEMCP */
for (c = 0; c < 0x80; c++) {
if (src == Tbl[c]) break;
}
else /* Unicode to OEMCP */
{
for ( c = 0; c < 0x80; c++ )
{
if ( src == Tbl[c] )
{
break;
}
}
c = ( c + 0x80 ) & 0xFF;
}
}

View File

@@ -7,12 +7,14 @@
#include "bits.h"
#include "uart.h"
void clock_disconnect() {
void clock_disconnect()
{
disconnectPLL0();
disablePLL0();
}
void clock_init() {
void clock_init()
{
/* set flash access time to 6 clks (safe setting) */
setFlashAccessTime( 6 );
@@ -54,54 +56,67 @@ void clock_init() {
connectPLL0();
}
void setFlashAccessTime(uint8_t clocks) {
void setFlashAccessTime( uint8_t clocks )
{
LPC_SC->FLASHCFG = FLASHTIM( clocks );
}
void setPLL0MultPrediv(uint16_t mult, uint8_t prediv) {
void setPLL0MultPrediv( uint16_t mult, uint8_t prediv )
{
LPC_SC->PLL0CFG = PLL_MULT( mult ) | PLL_PREDIV( prediv );
PLL0feed();
}
void enablePLL0() {
void enablePLL0()
{
LPC_SC->PLL0CON |= PLLE0;
PLL0feed();
}
void disablePLL0() {
void disablePLL0()
{
LPC_SC->PLL0CON &= ~PLLE0;
PLL0feed();
}
void connectPLL0() {
void connectPLL0()
{
while ( !( LPC_SC->PLL0STAT & PLOCK0 ) );
LPC_SC->PLL0CON |= PLLC0;
PLL0feed();
}
void disconnectPLL0() {
void disconnectPLL0()
{
LPC_SC->PLL0CON &= ~PLLC0;
PLL0feed();
}
void setCCLKDiv(uint8_t div) {
void setCCLKDiv( uint8_t div )
{
LPC_SC->CCLKCFG = CCLK_DIV( div );
}
void enableMainOsc() {
void enableMainOsc()
{
LPC_SC->SCS = OSCEN;
while ( !( LPC_SC->SCS & OSCSTAT ) );
}
void disableMainOsc() {
void disableMainOsc()
{
LPC_SC->SCS = 0;
}
void PLL0feed() {
void PLL0feed()
{
LPC_SC->PLL0FEED = 0xaa;
LPC_SC->PLL0FEED = 0x55;
}
void setClkSrc(uint8_t src) {
void setClkSrc( uint8_t src )
{
LPC_SC->CLKSRCSEL = src;
}

View File

@@ -4,7 +4,7 @@
# file to a C header. No copyright claimed.
BEGIN {
print "// autoconf.h generated from " ARGV[1] " at " strftime() "\n" \
print "// autoconf.h generated from " ARGV[1] " at NOW\n" \
"#ifndef AUTOCONF_H\n" \
"#define AUTOCONF_H"
}

View File

@@ -27,12 +27,12 @@
#define IN_AHBRAM __attribute__ ((section(".ahbram")))
#define SD_DT_INT_SETUP() do {\
BITBAND(LPC_GPIOINT->IO2IntEnR, SD_DT_BIT) = 1;\
BITBAND(LPC_GPIOINT->IO2IntEnF, SD_DT_BIT) = 1;\
BITBANG(LPC_GPIOINT->IO2IntEnR, SD_DT_BIT) = 1;\
BITBANG(LPC_GPIOINT->IO2IntEnF, SD_DT_BIT) = 1;\
} while(0)
#define SD_CHANGE_DETECT (BITBAND(LPC_GPIOINT->IO2IntStatR, SD_DT_BIT)\
|BITBAND(LPC_GPIOINT->IO2IntStatF, SD_DT_BIT))
#define SD_CHANGE_DETECT (BITBANG(LPC_GPIOINT->IO2IntStatR, SD_DT_BIT)\
|BITBANG(LPC_GPIOINT->IO2IntStatF, SD_DT_BIT))
#define SD_CHANGE_CLR() do {LPC_GPIOINT->IO2IntClr = BV(SD_DT_BIT);} while(0)
@@ -41,8 +41,8 @@
#define SD_WP_REG LPC_GPIO0
#define SD_WP_BIT 6
#define SDCARD_DETECT (!(BITBAND(SD_DT_REG->FIOPIN, SD_DT_BIT)))
#define SDCARD_WP (BITBAND(SD_WP_REG->FIOPIN, SD_WP_BIT))
#define SDCARD_DETECT (!(BITBANG(SD_DT_REG->FIOPIN, SD_DT_BIT)))
#define SDCARD_WP (BITBANG(SD_WP_REG->FIOPIN, SD_WP_BIT))
#define SD_SUPPLY_VOLTAGE (1L<<21) /* 3.3V - 3.4V */
#define CONFIG_SD_BLOCKTRANSFER 1
#define CONFIG_SD_AUTO_RETRIES 10
@@ -55,7 +55,8 @@
//#define CONFIG_CPU_FREQUENCY 46000000
#define CONFIG_UART_PCLKDIV 1
#define CONFIG_UART_TX_BUF_SHIFT 8
#define CONFIG_UART_BAUDRATE 921600
//#define CONFIG_UART_BAUDRATE 921600
#define CONFIG_UART_BAUDRATE 115200
#define CONFIG_UART_DEADLOCKABLE
#define SSP_CLK_DIVISOR_FAST 2

View File

@@ -32,11 +32,13 @@ uint32_t crc_reflect(uint32_t data, size_t data_len)
uint32_t ret;
ret = data & 0x01;
for ( i = 1; i < data_len; i++ )
{
data >>= 1;
ret = ( ret << 1 ) | ( data & 0x01 );
}
return ret;
}
@@ -56,16 +58,24 @@ uint32_t crc32_update(uint32_t crc, const unsigned char data)
unsigned char c;
c = data;
for (i = 0x01; i & 0xff; i <<= 1) {
for ( i = 0x01; i & 0xff; i <<= 1 )
{
bit = crc & 0x80000000;
if (c & i) {
if ( c & i )
{
bit = !bit;
}
crc <<= 1;
if (bit) {
if ( bit )
{
crc ^= 0x04c11db7;
}
}
return crc & 0xffffffff;
}

View File

@@ -16,7 +16,8 @@
typedef BYTE DSTATUS;
/* Results of Disk Functions */
typedef enum {
typedef enum
{
RES_OK = 0, /* 0: Successful */
RES_ERROR, /* 1: R/W Error */
RES_WRPRT, /* 2: Write Protected */
@@ -35,7 +36,8 @@ typedef enum {
* This is the struct returned in the data buffer when disk_getinfo
* is called with page=0.
*/
typedef struct {
typedef struct
{
uint8_t validbytes;
uint8_t maxpage;
uint8_t disktype;

View File

@@ -2,21 +2,26 @@
#include "config.h"
#include "uart.h"
void HardFault_Handler(void) {
void HardFault_Handler( void )
{
DBG_BL printf( "HFSR: %lx\n", SCB->HFSR );
DBG_UART uart_putc( 'H' );
while ( 1 ) ;
}
void MemManage_Handler(void) {
void MemManage_Handler( void )
{
DBG_BL printf( "MemManage - CFSR: %lx; MMFAR: %lx\n", SCB->CFSR, SCB->MMFAR );
}
void BusFault_Handler(void) {
void BusFault_Handler( void )
{
DBG_BL printf( "BusFault - CFSR: %lx; BFAR: %lx\n", SCB->CFSR, SCB->BFAR );
}
void UsageFault_Handler(void) {
void UsageFault_Handler( void )
{
DBG_BL printf( "UsageFault - CFSR: %lx; BFAR: %lx\n", SCB->CFSR, SCB->BFAR );
}

File diff suppressed because it is too large Load Diff

View File

@@ -229,7 +229,8 @@ extern "C" {
#if _MULTI_PARTITION /* Multiple partition configuration */
#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive# */
#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition# */
typedef struct {
typedef struct
{
BYTE pd; /* Physical drive# */
BYTE pt; /* Partition # (0-3) */
} PARTITION;
@@ -268,7 +269,8 @@ typedef char TCHAR;
/* File system object structure (FATFS) */
typedef struct {
typedef struct
{
BYTE fs_type; /* FAT sub-type (0:Not mounted) */
BYTE drv; /* Physical drive number */
BYTE csize; /* Sectors per cluster (1,2,4...128) */
@@ -304,7 +306,8 @@ typedef struct {
/* File object structure (FIL) */
typedef struct {
typedef struct
{
FATFS *fs; /* Pointer to the owner file system object */
WORD id; /* Owner file system mount ID */
BYTE flag; /* File status flags */
@@ -333,7 +336,8 @@ typedef struct {
/* Directory object structure (DIR) */
typedef struct {
typedef struct
{
FATFS *fs; /* Pointer to the owner file system object */
WORD id; /* Owner file system mount ID */
WORD index; /* Current read/write index number */
@@ -352,7 +356,8 @@ typedef struct {
/* File status structure (FILINFO) */
typedef struct {
typedef struct
{
DWORD fsize; /* File size */
WORD fdate; /* Last modified date */
WORD ftime; /* Last modified time */
@@ -369,7 +374,8 @@ typedef struct {
/* File function return code (FRESULT) */
typedef enum {
typedef enum
{
FR_OK = 0, /* (0) Succeeded */
FR_DISK_ERR, /* (1) A hard error occured in the low level disk I/O layer */
FR_INT_ERR, /* (2) Assertion failed */
@@ -397,7 +403,8 @@ typedef enum {
/* FatFs module application interface */
/* Low Level functions */
FRESULT l_openfilebycluster(FATFS *fs, FIL *fp, const TCHAR *path, DWORD clust, DWORD fsize); /* Open a file by its start cluster using supplied file size */
FRESULT l_openfilebycluster( FATFS *fs, FIL *fp, const TCHAR *path, DWORD clust,
DWORD fsize ); /* Open a file by its start cluster using supplied file size */
/* application level functions */
FRESULT f_mount ( BYTE, FATFS * ); /* Mount/Unmount a logical drive */

View File

@@ -12,36 +12,44 @@ WCHAR ff_convert(WCHAR w, UINT dir) {
int newcard;
void file_init() {
void file_init()
{
file_res = f_mount( 0, &fatfs );
newcard = 0;
}
void file_reinit(void) {
void file_reinit( void )
{
disk_init();
file_init();
}
void file_open_by_filinfo(FILINFO* fno) {
void file_open_by_filinfo( FILINFO *fno )
{
file_res = l_openfilebycluster( &fatfs, &file_handle, ( TCHAR * )"", fno->clust, fno->fsize );
}
void file_open(uint8_t* filename, BYTE flags) {
if (disk_state == DISK_CHANGED) {
void file_open( uint8_t *filename, BYTE flags )
{
if ( disk_state == DISK_CHANGED )
{
file_reinit();
newcard = 1;
}
file_res = f_open( &file_handle, ( TCHAR * )filename, flags );
file_block_off = sizeof( file_buf );
file_block_max = sizeof( file_buf );
file_status = file_res ? FILE_ERR : FILE_OK;
}
void file_close() {
void file_close()
{
file_res = f_close( &file_handle );
}
UINT file_read() {
UINT file_read()
{
UINT bytes_read;
file_res = f_read( &file_handle, file_buf, sizeof( file_buf ), &bytes_read );
return bytes_read;
@@ -56,12 +64,16 @@ UINT file_read() {
return bytes_written;
}*/
UINT file_readblock(void* buf, uint32_t addr, uint16_t size) {
UINT file_readblock( void *buf, uint32_t addr, uint16_t size )
{
UINT bytes_read;
file_res = f_lseek( &file_handle, addr );
if(file_handle.fptr != addr) {
if ( file_handle.fptr != addr )
{
return 0;
}
file_res = f_read( &file_handle, buf, size, &bytes_read );
return bytes_read;
}
@@ -74,11 +86,19 @@ UINT file_readblock(void* buf, uint32_t addr, uint16_t size) {
return bytes_written;
}*/
uint8_t file_getc() {
if(file_block_off == file_block_max) {
uint8_t file_getc()
{
if ( file_block_off == file_block_max )
{
file_block_max = file_read();
if(file_block_max == 0) file_status = FILE_EOF;
if ( file_block_max == 0 )
{
file_status = FILE_EOF;
}
file_block_off = 0;
}
return file_buf[file_block_off++];
}

View File

@@ -31,13 +31,14 @@
enum filestates { FILE_OK = 0, FILE_ERR, FILE_EOF };
BYTE file_buf[512];
FATFS fatfs;
FIL file_handle;
FRESULT file_res;
uint8_t file_lfn[258];
uint16_t file_block_off, file_block_max;
enum filestates file_status;
#define GCC_ALIGN_WORKAROUND __attribute__ ((aligned(4)))
extern BYTE file_buf[512];
extern FATFS fatfs;
extern FIL file_handle;
extern FRESULT file_res;
extern uint8_t file_lfn[258];
extern uint16_t file_block_off, file_block_max;
extern enum filestates file_status;
void file_init( void );
void file_open( uint8_t *filename, BYTE flags );

View File

@@ -14,75 +14,103 @@ uint32_t flash_sig[4];
IAP iap_entry = ( IAP ) IAP_LOCATION;
uint32_t calc_flash_crc(uint32_t start, uint32_t len) {
uint32_t calc_flash_crc( uint32_t start, uint32_t len )
{
DBG_BL printf( "calc_flash_crc(%08lx, %08lx) {\n", start, len );
uint32_t end = start + len;
if(end > 0x20000) {
if ( end > 0x20000 )
{
len = 0x1ffff - start;
end = 0x20000;
}
uint32_t crc = 0xffffffff;
uint32_t s = start;
while(s < end) {
while ( s < end )
{
crc = crc32_update( crc, *( const unsigned char * )( s ) );
s++;
}
crc = crc_finalize( crc );
DBG_BL printf( " crc generated. result=%08lx\n", crc );
DBG_BL printf( "} //calc_flash_crc\n" );
return crc;
}
void test_iap() {
void test_iap()
{
iap_cmd[0] = 54;
iap_entry( iap_cmd, iap_res );
DBG_BL printf( "Part ID=%08lx\n", iap_res[1] );
}
void print_header(sd2snes_fw_header *header) {
void print_header( sd2snes_fw_header *header )
{
DBG_BL printf( " magic = %08lx\n version = %08lx\n size = %08lx\n crc = %08lx\n ~crc = %08lx\n",
header->magic, header->version, header->size,
header->crc, header->crcc );
}
int check_header(sd2snes_fw_header *header, uint32_t crc) {
int check_header( sd2snes_fw_header *header, uint32_t crc )
{
if ( ( header->magic != FW_MAGIC )
|| ( header->size < 0x200 )
|| ( header->size > ( 0x1ffff - FW_START ) )
|| ((header->crc ^ header->crcc) != 0xffffffff)) {
|| ( ( header->crc ^ header->crcc ) != 0xffffffff ) )
{
return ERR_FLASHHD;
}
if(header->crc != crc) {
if ( header->crc != crc )
{
return ERR_FLASHCRC;
}
return ERR_OK;
}
FLASH_RES check_flash() {
FLASH_RES check_flash()
{
sd2snes_fw_header *fw_header = ( sd2snes_fw_header * ) FW_START;
uint32_t flash_addr = FW_START;
if(flash_addr != FW_START) {
DBG_BL printf("address sanity check failed. expected 0x%08lx, got 0x%08lx.\nSomething is terribly wrong.\nBailing out to avoid bootldr self-corruption.\n", FW_START, flash_addr);
if ( flash_addr != FW_START )
{
DBG_BL printf( "address sanity check failed. expected 0x%08lx, got 0x%08lx.\nSomething is terribly wrong.\nBailing out to avoid bootldr self-corruption.\n",
FW_START, flash_addr );
return ERR_HW;
}
DBG_BL printf( "Current flash contents:\n" );
DBG_BL print_header( fw_header );
uint32_t crc = calc_flash_crc( flash_addr + 0x100, ( fw_header->size & 0x1ffff ) );
return check_header( fw_header, crc );
}
IAP_RES iap_wrap(uint32_t *iap_cmd, uint32_t *iap_res) {
IAP_RES iap_wrap( uint32_t *iap_cmd, uint32_t *iap_res )
{
// NVIC_DisableIRQ(RIT_IRQn);
// NVIC_DisableIRQ(UART_IRQ);
for ( volatile int i = 0; i < 2048; i++ );
iap_entry( iap_cmd, iap_res );
for ( volatile int i = 0; i < 2048; i++ );
// NVIC_EnableIRQ(UART_IRQ);
return iap_res[0];
}
IAP_RES iap_prepare_for_write(uint32_t start, uint32_t end) {
if(start < (FW_START / 0x1000)) return INVALID_SECTOR;
IAP_RES iap_prepare_for_write( uint32_t start, uint32_t end )
{
if ( start < ( FW_START / 0x1000 ) )
{
return INVALID_SECTOR;
}
iap_cmd[0] = 50;
iap_cmd[1] = start;
iap_cmd[2] = end;
@@ -90,8 +118,13 @@ IAP_RES iap_prepare_for_write(uint32_t start, uint32_t end) {
return iap_res[0];
}
IAP_RES iap_erase(uint32_t start, uint32_t end) {
if(start < (FW_START / 0x1000)) return INVALID_SECTOR;
IAP_RES iap_erase( uint32_t start, uint32_t end )
{
if ( start < ( FW_START / 0x1000 ) )
{
return INVALID_SECTOR;
}
iap_cmd[0] = 52;
iap_cmd[1] = start;
iap_cmd[2] = end;
@@ -100,7 +133,8 @@ IAP_RES iap_erase(uint32_t start, uint32_t end) {
return iap_res[0];
}
IAP_RES iap_ram2flash(uint32_t tgt, uint8_t *src, int num) {
IAP_RES iap_ram2flash( uint32_t tgt, uint8_t *src, int num )
{
iap_cmd[0] = 51;
iap_cmd[1] = tgt;
iap_cmd[2] = ( uint32_t )src;
@@ -110,43 +144,67 @@ IAP_RES iap_ram2flash(uint32_t tgt, uint8_t *src, int num) {
return iap_res[0];
}
FLASH_RES flash_file(uint8_t *filename) {
FLASH_RES flash_file( uint8_t *filename )
{
sd2snes_fw_header *fw_header = ( sd2snes_fw_header * ) FW_START;
uint32_t flash_addr = FW_START;
uint32_t file_crc = 0xffffffff;
uint16_t count;
sd2snes_fw_header file_header;
UINT bytes_read;
if(flash_addr != FW_START) {
DBG_BL printf("address sanity check failed. expected 0x%08lx, got 0x%08lx.\nSomething is terribly wrong.\nBailing out to avoid bootldr self-corruption.\n", FW_START, flash_addr);
if ( flash_addr != FW_START )
{
DBG_BL printf( "address sanity check failed. expected 0x%08lx, got 0x%08lx.\nSomething is terribly wrong.\nBailing out to avoid bootldr self-corruption.\n",
FW_START, flash_addr );
return ERR_HW;
}
file_open( filename, FA_READ );
if(file_res) {
if ( file_res )
{
DBG_BL printf( "file_open: error %d\n", file_res );
return ERR_FS;
}
DBG_BL printf( "firmware image found. file size: %ld\n", file_handle.fsize );
DBG_BL printf( "reading header...\n" );
f_read( &file_handle, &file_header, 32, &bytes_read );
DBG_BL print_header( &file_header );
if(check_flash() || file_header.version != fw_header->version || file_header.version == FW_MAGIC || fw_header->version == FW_MAGIC) {
if ( check_flash() || file_header.version != fw_header->version || file_header.version == FW_MAGIC
|| fw_header->version == FW_MAGIC )
{
DBG_UART uart_putc( 'F' );
f_read( &file_handle, file_buf, 0xe0, &bytes_read );
for(;;) {
for ( ;; )
{
bytes_read = file_read();
if(file_res || !bytes_read) break;
for(count = 0; count < bytes_read; count++) {
if ( file_res || !bytes_read )
{
break;
}
for ( count = 0; count < bytes_read; count++ )
{
file_crc = crc32_update( file_crc, file_buf[count] );
}
}
file_crc = crc_finalize( file_crc );
DBG_BL printf( "file crc=%08lx\n", file_crc );
if(check_header(&file_header, file_header.crc) != ERR_OK) {
if ( check_header( &file_header, file_header.crc ) != ERR_OK )
{
DBG_BL printf( "Invalid firmware file (header corrupted).\n" );
return ERR_FILEHD;
}
if(file_header.crc != file_crc) {
if ( file_header.crc != file_crc )
{
DBG_BL printf( "Firmware file checksum error.\n" );
return ERR_FILECHK;
}
@@ -156,53 +214,82 @@ FLASH_RES flash_file(uint8_t *filename) {
writeled( 1 );
DBG_BL printf( "erasing flash...\n" );
DBG_UART uart_putc( 'P' );
if((res = iap_prepare_for_write(FW_START / 0x1000, FLASH_SECTORS)) != CMD_SUCCESS) {
if ( ( res = iap_prepare_for_write( FW_START / 0x1000, FLASH_SECTORS ) ) != CMD_SUCCESS )
{
DBG_BL printf( "error %ld while preparing for erase\n", res );
DBG_UART uart_putc( 'X' );
return ERR_FLASHPREP;
};
DBG_UART uart_putc( 'E' );
if((res = iap_erase(FW_START / 0x1000, FLASH_SECTORS)) != CMD_SUCCESS) {
if ( ( res = iap_erase( FW_START / 0x1000, FLASH_SECTORS ) ) != CMD_SUCCESS )
{
DBG_BL printf( "error %ld while erasing\n", res );
DBG_UART uart_putc( 'X' );
return ERR_FLASHERASE;
}
DBG_BL printf( "writing... @%08lx\n", flash_addr );
file_close();
file_open( filename, FA_READ );
uint8_t current_sec;
uint32_t total_read = 0;
for(flash_addr = FW_START; flash_addr < 0x00020000; flash_addr += 0x200) {
for ( flash_addr = FW_START; flash_addr < 0x00020000; flash_addr += 0x200 )
{
total_read += ( bytes_read = file_read() );
if(file_res || !bytes_read) break;
if ( file_res || !bytes_read )
{
break;
}
current_sec = flash_addr & 0x10000 ? ( 16 + ( ( flash_addr >> 15 ) & 1 ) )
: ( flash_addr >> 12 );
DBG_BL printf( "current_sec=%d flash_addr=%08lx\n", current_sec, flash_addr );
DBG_UART uart_putc( '.' );
if(current_sec < (FW_START / 0x1000)) return ERR_FLASH;
if ( current_sec < ( FW_START / 0x1000 ) )
{
return ERR_FLASH;
}
DBG_UART uart_putc( current_sec["0123456789ABCDEFGH"] );
DBG_UART uart_putc( 'p' );
if((res = iap_prepare_for_write(current_sec, current_sec)) != CMD_SUCCESS) {
if ( ( res = iap_prepare_for_write( current_sec, current_sec ) ) != CMD_SUCCESS )
{
DBG_BL printf( "error %ld while preparing sector %d for write\n", res, current_sec );
DBG_UART uart_putc( 'X' );
return ERR_FLASH;
}
DBG_UART uart_putc( 'w' );
if((res = iap_ram2flash(flash_addr, file_buf, 512)) != CMD_SUCCESS) {
DBG_BL printf("error %ld while writing to address %08lx (sector %d)\n", res, flash_addr, current_sec);
if ( ( res = iap_ram2flash( flash_addr, file_buf, 512 ) ) != CMD_SUCCESS )
{
//printf("error %ld while writing to address %08lx (sector %d)\n", res, flash_addr, current_sec);
DBG_UART uart_putc( 'X' );
return ERR_FLASH;
}
}
if(total_read != (file_header.size + 0x100)) {
if ( total_read != ( file_header.size + 0x100 ) )
{
DBG_BL printf( "wrote less data than expected! (%08lx vs. %08lx)\n", total_read, file_header.size );
// DBG_UART uart_putc('X');
return ERR_FILECHK;
}
writeled( 0 );
} else {
}
else
{
DBG_UART uart_putc( 'n' );
DBG_BL printf( "flash content is ok, no version mismatch, no forced upgrade. No need to flash\n" );
}
return ERR_OK;
}

View File

@@ -6,7 +6,8 @@ typedef void (*IAP)(uint32_t*, uint32_t*);
typedef enum {ERR_OK = 0, ERR_HW, ERR_FS, ERR_FILEHD, ERR_FILECHK, ERR_FLASHHD, ERR_FLASHCRC, ERR_FLASHPREP, ERR_FLASHERASE, ERR_FLASH} FLASH_RES;
typedef enum {
typedef enum
{
/* 0*/ CMD_SUCCESS = 0,
/* 1*/ INVALID_COMMAND,
/* 2*/ SRC_ADDR_ERROR,
@@ -23,7 +24,8 @@ typedef enum {
#define FW_MAGIC (0x44534E53)
typedef struct {
typedef struct
{
uint32_t magic;
uint32_t version;
uint32_t size;

View File

@@ -18,23 +18,28 @@ int led_writeledstate = 0;
write red P1.23 PWM1[4]
*/
void rdyled(unsigned int state) {
BITBAND(LPC_GPIO2->FIODIR, 4) = state;
void rdyled( unsigned int state )
{
BITBANG( LPC_GPIO2->FIODIR, 4 ) = state;
led_rdyledstate = state;
}
void readled(unsigned int state) {
BITBAND(LPC_GPIO2->FIODIR, 5) = state;
void readled( unsigned int state )
{
BITBANG( LPC_GPIO2->FIODIR, 5 ) = state;
led_readledstate = state;
}
void writeled(unsigned int state) {
BITBAND(LPC_GPIO1->FIODIR, 23) = state;
void writeled( unsigned int state )
{
BITBANG( LPC_GPIO1->FIODIR, 23 ) = state;
led_writeledstate = state;
}
void led_clkout32(uint32_t val) {
while(1) {
void led_clkout32( uint32_t val )
{
while ( 1 )
{
rdyled( 1 );
delay_ms( 400 );
readled( ( val & BV( 31 ) ) >> 31 );
@@ -44,20 +49,25 @@ void led_clkout32(uint32_t val) {
}
}
void toggle_rdy_led() {
void toggle_rdy_led()
{
rdyled( ~led_rdyledstate );
}
void toggle_read_led() {
void toggle_read_led()
{
readled( ~led_readledstate );
}
void toggle_write_led() {
void toggle_write_led()
{
writeled( ~led_writeledstate );
}
void led_panic() {
while(1) {
void led_panic()
{
while ( 1 )
{
LPC_GPIO2->FIODIR |= BV( 4 ) | BV( 5 );
LPC_GPIO1->FIODIR |= BV( 23 );
delay_ms( 350 );
@@ -67,24 +77,26 @@ void led_panic() {
}
}
void led_std() {
BITBAND(LPC_PINCON->PINSEL4, 9) = 0;
BITBAND(LPC_PINCON->PINSEL4, 8) = 0;
void led_std()
{
BITBANG( LPC_PINCON->PINSEL4, 9 ) = 0;
BITBANG( LPC_PINCON->PINSEL4, 8 ) = 0;
BITBAND(LPC_PINCON->PINSEL4, 11) = 0;
BITBAND(LPC_PINCON->PINSEL4, 10) = 0;
BITBANG( LPC_PINCON->PINSEL4, 11 ) = 0;
BITBANG( LPC_PINCON->PINSEL4, 10 ) = 0;
BITBAND(LPC_PINCON->PINSEL3, 15) = 0;
BITBAND(LPC_PINCON->PINSEL3, 14) = 0;
BITBANG( LPC_PINCON->PINSEL3, 15 ) = 0;
BITBANG( LPC_PINCON->PINSEL3, 14 ) = 0;
BITBAND(LPC_PWM1->PCR, 12) = 0;
BITBAND(LPC_PWM1->PCR, 13) = 0;
BITBAND(LPC_PWM1->PCR, 14) = 0;
BITBANG( LPC_PWM1->PCR, 12 ) = 0;
BITBANG( LPC_PWM1->PCR, 13 ) = 0;
BITBANG( LPC_PWM1->PCR, 14 ) = 0;
}
void led_init() {
void led_init()
{
/* power is already connected by default */
/* set PCLK divider to 8 */
BITBAND(LPC_SC->PCLKSEL1, 21) = 1;
BITBAND(LPC_SC->PCLKSEL1, 20) = 1;
BITBANG( LPC_SC->PCLKSEL1, 21 ) = 1;
BITBANG( LPC_SC->PCLKSEL1, 20 ) = 1;
}

View File

@@ -27,9 +27,9 @@ if { [info exists CPUTAPID ] } {
#delays on reset lines
#if your OpenOCD version rejects "jtag_nsrst_delay" replace it with:
#adapter_nsrst_delay 200
jtag_nsrst_delay 200
jtag_ntrst_delay 200
adapter_nsrst_delay 200
#jtag_nsrst_delay 200
#jtag_ntrst_delay 200
# LPC2000 & LPC1700 -> SRST causes TRST
#reset_config srst_pulls_trst
@@ -56,7 +56,7 @@ flash bank $_FLASHNAME lpc2000 0x0 0x20000 0 0 $_TARGETNAME \
# Run with *real slow* clock by default since the
# boot rom could have been playing with the PLL, so
# we have no idea what clock the target is running at.
jtag_khz 1000
adapter_khz 1000
$_TARGETNAME configure -event reset-init {
# Do not remap 0x0000-0x0020 to anything but the flash (i.e. select

View File

@@ -20,14 +20,24 @@
int i;
BYTE file_buf[512] GCC_ALIGN_WORKAROUND;
FATFS fatfs;
FIL file_handle;
FRESULT file_res;
uint8_t file_lfn[258];
uint16_t file_block_off, file_block_max;
enum filestates file_status;
volatile enum diskstates disk_state;
extern volatile tick_t ticks;
int ( *chain )( void );
int main(void) {
int main( void )
{
SNES_CIC_PAIR_REG->FIODIR = BV( SNES_CIC_PAIR_BIT );
BITBAND(SNES_CIC_PAIR_REG->FIOSET, SNES_CIC_PAIR_BIT) = 1;
BITBANG( SNES_CIC_PAIR_REG->FIOSET, SNES_CIC_PAIR_BIT ) = 1;
/* LPC_GPIO2->FIODIR = BV(0) | BV(1) | BV(2); */
// LPC_GPIO0->FIODIR = BV(16);
@@ -52,8 +62,16 @@ int main(void) {
clock_init();
// LPC_PINCON->PINSEL0 |= BV(20) | BV(21); /* MAT3.0 (FPGA clock) */
sdn_init();
for ( i = 0; i < 20; i++ )
{
uart_putc( '-' );
}
uart_putc( '\n' );
DBG_BL printf( "chksum=%08lx\n", *( uint32_t * )28 );
DBG_BL printf("\n\nsd2snes mk.2 bootloader\nver.: " VER "\ncpu clock: %ld Hz\n", CONFIG_CPU_FREQUENCY);
/*DBG_BL*/ printf( "\n\nsd2snes mk.2 bootloader\nver.: " VER "\ncpu clock: %ld Hz\n", CONFIG_CPU_FREQUENCY );
DBG_BL printf( "PCONP=%lx\n", LPC_SC->PCONP );
/* setup timer (fpga clk) */
LPC_TIM3->CTCR = 0;
@@ -64,24 +82,35 @@ DBG_BL printf("PCONP=%lx\n", LPC_SC->PCONP);
NVIC->ICER[0] = 0xffffffff;
NVIC->ICER[1] = 0xffffffff;
FLASH_RES res = flash_file( ( uint8_t * )"/sd2snes/firmware.img" );
if(res == ERR_FLASHPREP || res == ERR_FLASHERASE || res == ERR_FLASH) {
if ( res == ERR_FLASHPREP || res == ERR_FLASHERASE || res == ERR_FLASH )
{
rdyled( 0 );
writeled( 1 );
}
if(res == ERR_FILEHD || res == ERR_FILECHK) {
if ( res == ERR_FILEHD || res == ERR_FILECHK )
{
rdyled( 0 );
readled( 1 );
}
DBG_BL printf( "flash result = %d\n", res );
if(res != ERR_OK) {
if((res = check_flash()) != ERR_OK) {
if ( res != ERR_OK )
{
if ( ( res = check_flash() ) != ERR_OK )
{
DBG_BL printf( "check_flash() failed with error %d, not booting.\n", res );
while(1) {
while ( 1 )
{
toggle_rdy_led();
delay_ms( 500 );
}
}
}
NVIC_DisableIRQ( RIT_IRQn );
NVIC_DisableIRQ( UART_IRQ );
@@ -97,6 +126,7 @@ DBG_BL printf("PCONP=%lx\n", LPC_SC->PCONP);
uart_putc( "0123456789abcdef"[( ( uint32_t )chain ) & 15] );
uart_putc( '\n' );
chain();
while ( 1 );
}

View File

@@ -5,8 +5,14 @@
#
interface ft2232
ft2232_vid_pid 0x0403 0x6010
ft2232_device_desc "Dual RS232"
ft2232_layout "oocdlink"
ft2232_latency 2
ft2232_vid_pid 0x15ba 0x0003
ft2232_device_desc "Olimex OpenOCD JTAG"
ft2232_layout "olimex-jtag"
#interface ft2232
#ft2232_vid_pid 0x0403 0x6010
#ft2232_device_desc "Dual RS232"
#ft2232_layout "oocdlink"
#ft2232_latency 2
#adapter_khz 10

View File

@@ -15,7 +15,8 @@
* USB [enabled via usb_init]
* PWM1
*/
void power_init() {
void power_init()
{
LPC_SC->PCONP = BV( PCSSP0 )
| BV( PCTIM3 )
| BV( PCRTC )

View File

@@ -62,8 +62,10 @@ static char *outptr;
static int maxlen;
/* printf */
static void outchar(char x) {
if (maxlen) {
static void outchar( char x )
{
if ( maxlen )
{
maxlen--;
outfunc( x );
outlength++;
@@ -71,15 +73,18 @@ static void outchar(char x) {
}
/* sprintf */
static void outstr(char x) {
if (maxlen) {
static void outstr( char x )
{
if ( maxlen )
{
maxlen--;
*outptr++ = x;
outlength++;
}
}
static int internal_nprintf(void (*output_function)(char c), const char *fmt, va_list ap) {
static int internal_nprintf( void ( *output_function )( char c ), const char *fmt, va_list ap )
{
unsigned int width;
unsigned int flags;
unsigned int base = 0;
@@ -87,16 +92,24 @@ static int internal_nprintf(void (*output_function)(char c), const char *fmt, va
outlength = 0;
while (*fmt) {
while (1) {
while ( *fmt )
{
while ( 1 )
{
if ( *fmt == 0 )
{
goto end;
}
if (*fmt == '%') {
if ( *fmt == '%' )
{
fmt++;
if ( *fmt != '%' )
{
break;
}
}
output_function( *fmt++ );
}
@@ -105,9 +118,12 @@ static int internal_nprintf(void (*output_function)(char c), const char *fmt, va
width = 0;
/* read all flags */
do {
if (flags < FLAG_WIDTH) {
switch (*fmt) {
do
{
if ( flags < FLAG_WIDTH )
{
switch ( *fmt )
{
case '0':
flags |= FLAG_ZEROPAD;
continue;
@@ -126,8 +142,10 @@ static int internal_nprintf(void (*output_function)(char c), const char *fmt, va
}
}
if (flags < FLAG_LONG) {
if (*fmt >= '0' && *fmt <= '9') {
if ( flags < FLAG_LONG )
{
if ( *fmt >= '0' && *fmt <= '9' )
{
unsigned char tmp = *fmt - '0';
width = 10 * width + tmp;
flags |= FLAG_WIDTH;
@@ -135,20 +153,26 @@ static int internal_nprintf(void (*output_function)(char c), const char *fmt, va
}
if ( *fmt == 'h' )
{
continue;
}
if (*fmt == 'l') {
if ( *fmt == 'l' )
{
flags |= FLAG_LONG;
continue;
}
}
break;
} while (*fmt++);
}
while ( *fmt++ );
/* Strings */
if (*fmt == 'c' || *fmt == 's') {
switch (*fmt) {
if ( *fmt == 'c' || *fmt == 's' )
{
switch ( *fmt )
{
case 'c':
buffer[0] = va_arg( ap, int );
ptr = buffer;
@@ -163,9 +187,11 @@ static int internal_nprintf(void (*output_function)(char c), const char *fmt, va
}
/* Numbers */
switch (*fmt) {
switch ( *fmt )
{
case 'u':
flags |= FLAG_UNSIGNED;
case 'd':
base = 10;
break;
@@ -179,6 +205,7 @@ static int internal_nprintf(void (*output_function)(char c), const char *fmt, va
output_function( '0' );
output_function( 'x' );
width -= 2;
case 'x':
case 'X':
base = 16;
@@ -188,59 +215,89 @@ static int internal_nprintf(void (*output_function)(char c), const char *fmt, va
unsigned int num;
if (!(flags & FLAG_UNSIGNED)) {
if ( !( flags & FLAG_UNSIGNED ) )
{
int tmp = va_arg( ap, int );
if (tmp < 0) {
if ( tmp < 0 )
{
num = -tmp;
flags |= FLAG_NEGATIVE;
} else
}
else
{
num = tmp;
} else {
}
}
else
{
num = va_arg( ap, unsigned int );
}
/* Convert number into buffer */
ptr = buffer + sizeof( buffer );
*--ptr = 0;
do {
do
{
*--ptr = hexdigits[num % base];
num /= base;
} while (num != 0);
}
while ( num != 0 );
/* Sign */
if (flags & FLAG_NEGATIVE) {
if ( flags & FLAG_NEGATIVE )
{
output_function( '-' );
width--;
} else if (flags & FLAG_FORCESIGN) {
}
else if ( flags & FLAG_FORCESIGN )
{
output_function( '+' );
width--;
} else if (flags & FLAG_BLANK) {
}
else if ( flags & FLAG_BLANK )
{
output_function( ' ' );
width--;
}
output:
/* left padding */
if ((flags & FLAG_WIDTH) && !(flags & FLAG_LEFTADJ)) {
while (strlen(ptr) < width) {
if ( ( flags & FLAG_WIDTH ) && !( flags & FLAG_LEFTADJ ) )
{
while ( strlen( ptr ) < width )
{
if ( flags & FLAG_ZEROPAD )
{
output_function( '0' );
}
else
{
output_function( ' ' );
}
width--;
}
}
/* data */
while (*ptr) {
while ( *ptr )
{
output_function( *ptr++ );
if ( width )
{
width--;
}
}
/* right padding */
if (flags & FLAG_WIDTH) {
while (width) {
if ( flags & FLAG_WIDTH )
{
while ( width )
{
output_function( ' ' );
width--;
}
@@ -253,7 +310,8 @@ static int internal_nprintf(void (*output_function)(char c), const char *fmt, va
return outlength;
}
int printf(const char *format, ...) {
int printf( const char *format, ... )
{
va_list ap;
int res;
@@ -264,7 +322,8 @@ int printf(const char *format, ...) {
return res;
}
int snprintf(char *str, size_t size, const char *format, ...) {
int snprintf( char *str, size_t size, const char *format, ... )
{
va_list ap;
int res;
@@ -273,28 +332,43 @@ int snprintf(char *str, size_t size, const char *format, ...) {
va_start( ap, format );
res = internal_nprintf( outstr, format, ap );
va_end( ap );
if ( res < size )
{
str[res] = 0;
}
return res;
}
/* Required for gcc compatibility */
int puts(const char *str) {
int puts( const char *str )
{
uart_puts( str );
uart_putc( '\n' );
return 0;
}
#undef putchar
int putchar(int c) {
int putchar( int c )
{
uart_putc( c );
return 0;
}
#else
int printf(const char *format, ...) { return 0; }
int snprintf(char *str, size_t size, const char *format, ...) { return 0; }
int puts(const char *str) { return 0; }
int printf( const char *format, ... )
{
return 0;
}
//int snprintf(char *str, size_t size, const char *format, ...) { return 0; }
int puts( const char *str )
{
return 0;
}
#undef putchar
int putchar(int c) { return 0; }
int putchar( int c )
{
return 0;
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,4 @@
/* ___INGO___ */
#include <arm/NXP/LPC17xx/LPC17xx.h>
#include "bits.h"
#include "config.h"
@@ -18,39 +17,42 @@ extern volatile int sd_changed;
volatile tick_t ticks;
volatile int wokefromrit;
void timer_init(void) {
void timer_init( void )
{
/* turn on power to RIT */
BITBAND(LPC_SC->PCONP, PCRIT) = 1;
BITBANG( LPC_SC->PCONP, PCRIT ) = 1;
/* clear RIT mask */
LPC_RIT->RIMASK = 0; /*xffffffff;*/
/* PCLK = CCLK */
BITBAND(LPC_SC->PCLKSEL1, 26) = 1;
BITBAND(LPC_SC->PCLKSEL1, PCLK_TIMER3) = 1;
BITBANG( LPC_SC->PCLKSEL1, 26 ) = 1;
BITBANG( LPC_SC->PCLKSEL1, PCLK_TIMER3 ) = 1;
}
void delay_us(unsigned int time) {
void delay_us( unsigned int time )
{
/* Prepare RIT */
LPC_RIT->RICOUNTER = 0;
LPC_RIT->RICOMPVAL = ( CONFIG_CPU_FREQUENCY / 1000000 ) * time;
LPC_RIT->RICTRL = BV( RITEN ) | BV( RITINT );
/* Wait until RIT signals an interrupt */
while (!(BITBAND(LPC_RIT->RICTRL, RITINT))) ;
while ( !( BITBANG( LPC_RIT->RICTRL, RITINT ) ) ) ;
/* Disable RIT */
LPC_RIT->RICTRL = 0;
}
void delay_ms(unsigned int time) {
void delay_ms( unsigned int time )
{
/* Prepare RIT */
LPC_RIT->RICOUNTER = 0;
LPC_RIT->RICOMPVAL = ( CONFIG_CPU_FREQUENCY / 1000 ) * time;
LPC_RIT->RICTRL = BV( RITEN ) | BV( RITINT );
/* Wait until RIT signals an interrupt */
while (!(BITBAND(LPC_RIT->RICTRL, RITINT))) ;
while ( !( BITBANG( LPC_RIT->RICTRL, RITINT ) ) ) ;
/* Disable RIT */
LPC_RIT->RICTRL = 0;

View File

@@ -13,7 +13,8 @@ extern volatile tick_t ticks;
*
* This inline function returns the current system tick count.
*/
static inline tick_t getticks(void) {
static inline tick_t getticks( void )
{
return ticks;
}

View File

@@ -77,55 +77,72 @@
//static char txbuf[1 << CONFIG_UART_TX_BUF_SHIFT];
static volatile unsigned int read_idx, write_idx;
void uart_putc(char c) {
void uart_putc( char c )
{
if ( c == '\n' )
{
uart_putc( '\r' );
}
while ( !( UART_REGS->LSR & ( 0x20 ) ) );
UART_REGS->THR = c;
}
/* Polling version only */
unsigned char uart_getc(void) {
unsigned char uart_getc( void )
{
/* wait for character */
while (!(BITBAND(UART_REGS->LSR, 0))) ;
while ( !( BITBANG( UART_REGS->LSR, 0 ) ) ) ;
return UART_REGS->RBR;
}
/* Returns true if a char is ready */
unsigned char uart_gotc(void) {
return BITBAND(UART_REGS->LSR, 0);
unsigned char uart_gotc( void )
{
return BITBANG( UART_REGS->LSR, 0 );
}
void uart_init(void) {
void uart_init( void )
{
uint32_t div;
/* Turn on power to UART */
BITBAND(LPC_SC->PCONP, UART_PCONBIT) = 1;
BITBANG( LPC_SC->PCONP, UART_PCONBIT ) = 1;
/* UART clock = CPU clock - this block is reduced at compile-time */
if (CONFIG_UART_PCLKDIV == 1) {
BITBAND(LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 1;
BITBAND(LPC_SC->UART_PCLKREG, UART_PCLKBIT+1) = 0;
} else if (CONFIG_UART_PCLKDIV == 2) {
BITBAND(LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 0;
BITBAND(LPC_SC->UART_PCLKREG, UART_PCLKBIT+1) = 1;
} else if (CONFIG_UART_PCLKDIV == 4) {
BITBAND(LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 0;
BITBAND(LPC_SC->UART_PCLKREG, UART_PCLKBIT+1) = 0;
} else { // Fallback: Divide by 8
BITBAND(LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 1;
BITBAND(LPC_SC->UART_PCLKREG, UART_PCLKBIT+1) = 1;
if ( CONFIG_UART_PCLKDIV == 1 )
{
BITBANG( LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 1;
BITBANG( LPC_SC->UART_PCLKREG, UART_PCLKBIT + 1 ) = 0;
}
else if ( CONFIG_UART_PCLKDIV == 2 )
{
BITBANG( LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 0;
BITBANG( LPC_SC->UART_PCLKREG, UART_PCLKBIT + 1 ) = 1;
}
else if ( CONFIG_UART_PCLKDIV == 4 )
{
BITBANG( LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 0;
BITBANG( LPC_SC->UART_PCLKREG, UART_PCLKBIT + 1 ) = 0;
}
else // Fallback: Divide by 8
{
BITBANG( LPC_SC->UART_PCLKREG, UART_PCLKBIT ) = 1;
BITBANG( LPC_SC->UART_PCLKREG, UART_PCLKBIT + 1 ) = 1;
}
/* set baud rate - no fractional stuff for now */
UART_REGS->LCR = BV( 7 ) | 3; // always 8n1
div = 0x850004; // baud2divisor(CONFIG_UART_BAUDRATE);
div = 0xF80022; //0x850004; // baud2divisor(CONFIG_UART_BAUDRATE);
UART_REGS->DLL = div & 0xff;
UART_REGS->DLM = ( div >> 8 ) & 0xff;
BITBAND(UART_REGS->LCR, 7) = 0;
BITBANG( UART_REGS->LCR, 7 ) = 0;
if (div & 0xff0000) {
if ( div & 0xff0000 )
{
UART_REGS->FDR = ( div >> 16 ) & 0xff;
}
@@ -136,67 +153,101 @@ void uart_init(void) {
}
/* --- generic code below --- */
void uart_puthex(uint8_t num) {
void uart_puthex( uint8_t num )
{
uint8_t tmp;
tmp = ( num & 0xf0 ) >> 4;
if (tmp < 10)
uart_putc('0'+tmp);
else
uart_putc('a'+tmp-10);
tmp = num & 0x0f;
if ( tmp < 10 )
{
uart_putc( '0' + tmp );
}
else
{
uart_putc( 'a' + tmp - 10 );
}
void uart_trace(void *ptr, uint16_t start, uint16_t len) {
tmp = num & 0x0f;
if ( tmp < 10 )
{
uart_putc( '0' + tmp );
}
else
{
uart_putc( 'a' + tmp - 10 );
}
}
void uart_trace( void *ptr, uint16_t start, uint16_t len )
{
uint16_t i;
uint8_t j;
uint8_t ch;
uint8_t *data = ptr;
data += start;
for(i=0;i<len;i+=16) {
for ( i = 0; i < len; i += 16 )
{
uart_puthex( start >> 8 );
uart_puthex( start & 0xff );
uart_putc( '|' );
uart_putc( ' ' );
for(j=0;j<16;j++) {
if(i+j<len) {
for ( j = 0; j < 16; j++ )
{
if ( i + j < len )
{
ch = *( data + j );
uart_puthex( ch );
} else {
}
else
{
uart_putc( ' ' );
uart_putc( ' ' );
}
uart_putc( ' ' );
}
uart_putc( '|' );
for(j=0;j<16;j++) {
if(i+j<len) {
for ( j = 0; j < 16; j++ )
{
if ( i + j < len )
{
ch = *( data++ );
if ( ch < 32 || ch > 0x7e )
{
ch = '.';
}
uart_putc( ch );
} else {
}
else
{
uart_putc( ' ' );
}
}
uart_putc( '|' );
uart_putcrlf();
start += 16;
}
}
void uart_flush(void) {
void uart_flush( void )
{
while ( read_idx != write_idx ) ;
}
void uart_puts(const char *text) {
while (*text) {
void uart_puts( const char *text )
{
while ( *text )
{
uart_putc( *text++ );
}
}

View File

@@ -31,7 +31,8 @@
#if _CODE_PAGE == 437
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP437(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP437(0x80-0xFF) to Unicode conversion table */
{
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
@@ -53,7 +54,8 @@ const WCHAR Tbl[] = { /* CP437(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 720
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP720(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP720(0x80-0xFF) to Unicode conversion table */
{
0x0000, 0x0000, 0x00E9, 0x00E2, 0x0000, 0x00E0, 0x0000, 0x00E7,
0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0000, 0x0000, 0x0000,
0x0000, 0x0651, 0x0652, 0x00F4, 0x00A4, 0x0640, 0x00FB, 0x00F9,
@@ -75,7 +77,8 @@ const WCHAR Tbl[] = { /* CP720(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 737
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP737(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP737(0x80-0xFF) to Unicode conversion table */
{
0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398,
0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0,
0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9,
@@ -97,7 +100,8 @@ const WCHAR Tbl[] = { /* CP737(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 775
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP775(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP775(0x80-0xFF) to Unicode conversion table */
{
0x0106, 0x00FC, 0x00E9, 0x0101, 0x00E4, 0x0123, 0x00E5, 0x0107,
0x0142, 0x0113, 0x0156, 0x0157, 0x012B, 0x0179, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x014D, 0x00F6, 0x0122, 0x00A2, 0x015A,
@@ -119,7 +123,8 @@ const WCHAR Tbl[] = { /* CP775(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 850
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP850(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP850(0x80-0xFF) to Unicode conversion table */
{
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
@@ -141,7 +146,8 @@ const WCHAR Tbl[] = { /* CP850(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 852
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP852(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP852(0x80-0xFF) to Unicode conversion table */
{
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x016F, 0x0107, 0x00E7,
0x0142, 0x00EB, 0x0150, 0x0151, 0x00EE, 0x0179, 0x00C4, 0x0106,
0x00C9, 0x0139, 0x013A, 0x00F4, 0x00F6, 0x013D, 0x013E, 0x015A,
@@ -163,7 +169,8 @@ const WCHAR Tbl[] = { /* CP852(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 855
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP855(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP855(0x80-0xFF) to Unicode conversion table */
{
0x0452, 0x0402, 0x0453, 0x0403, 0x0451, 0x0401, 0x0454, 0x0404,
0x0455, 0x0405, 0x0456, 0x0406, 0x0457, 0x0407, 0x0458, 0x0408,
0x0459, 0x0409, 0x045A, 0x040A, 0x045B, 0x040B, 0x045C, 0x040C,
@@ -185,7 +192,8 @@ const WCHAR Tbl[] = { /* CP855(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 857
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP857(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP857(0x80-0xFF) to Unicode conversion table */
{
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0131, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
@@ -207,7 +215,8 @@ const WCHAR Tbl[] = { /* CP857(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 858
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP858(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP858(0x80-0xFF) to Unicode conversion table */
{
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7,
0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9,
@@ -229,7 +238,8 @@ const WCHAR Tbl[] = { /* CP858(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 862
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP862(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP862(0x80-0xFF) to Unicode conversion table */
{
0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7,
0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7,
@@ -251,7 +261,8 @@ const WCHAR Tbl[] = { /* CP862(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 866
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP866(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP866(0x80-0xFF) to Unicode conversion table */
{
0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417,
0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427,
@@ -273,7 +284,8 @@ const WCHAR Tbl[] = { /* CP866(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 874
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP874(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP874(0x80-0xFF) to Unicode conversion table */
{
0x20AC, 0x0000, 0x0000, 0x0000, 0x0000, 0x2026, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
@@ -295,7 +307,8 @@ const WCHAR Tbl[] = { /* CP874(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 1250
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP1250(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP1250(0x80-0xFF) to Unicode conversion table */
{
0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021,
0x0000, 0x2030, 0x0160, 0x2039, 0x015A, 0x0164, 0x017D, 0x0179,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
@@ -317,7 +330,8 @@ const WCHAR Tbl[] = { /* CP1250(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 1251
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP1251(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP1251(0x80-0xFF) to Unicode conversion table */
{
0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021,
0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F,
0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
@@ -339,7 +353,8 @@ const WCHAR Tbl[] = { /* CP1251(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 1252
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP1252(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP1252(0x80-0xFF) to Unicode conversion table */
{
0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x017D, 0x0000,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
@@ -361,7 +376,8 @@ const WCHAR Tbl[] = { /* CP1252(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 1253
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP1253(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP1253(0x80-0xFF) to Unicode conversion table */
{
0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
0x0000, 0x2030, 0x0000, 0x2039, 0x000C, 0x0000, 0x0000, 0x0000,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
@@ -383,7 +399,8 @@ const WCHAR Tbl[] = { /* CP1253(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 1254
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP1254(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP1254(0x80-0xFF) to Unicode conversion table */
{
0x20AC, 0x0000, 0x210A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
0x02C6, 0x2030, 0x0160, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
@@ -405,7 +422,8 @@ const WCHAR Tbl[] = { /* CP1254(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 1255
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP1255(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP1255(0x80-0xFF) to Unicode conversion table */
{
0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
0x02C6, 0x2030, 0x0000, 0x2039, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
@@ -427,7 +445,8 @@ const WCHAR Tbl[] = { /* CP1255(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 1256
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP1256(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP1256(0x80-0xFF) to Unicode conversion table */
{
0x20AC, 0x067E, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
0x02C6, 0x2030, 0x0679, 0x2039, 0x0152, 0x0686, 0x0698, 0x0688,
0x06AF, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
@@ -449,7 +468,8 @@ const WCHAR Tbl[] = { /* CP1256(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 1257
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP1257(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP1257(0x80-0xFF) to Unicode conversion table */
{
0x20AC, 0x0000, 0x201A, 0x0000, 0x201E, 0x2026, 0x2020, 0x2021,
0x0000, 0x2030, 0x0000, 0x2039, 0x0000, 0x00A8, 0x02C7, 0x00B8,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
@@ -471,7 +491,8 @@ const WCHAR Tbl[] = { /* CP1257(0x80-0xFF) to Unicode conversion table */
#elif _CODE_PAGE == 1258
#define _TBLDEF 1
static
const WCHAR Tbl[] = { /* CP1258(0x80-0xFF) to Unicode conversion table */
const WCHAR Tbl[] = /* CP1258(0x80-0xFF) to Unicode conversion table */
{
0x20AC, 0x0000, 0x201A, 0x0192, 0x201E, 0x2026, 0x2020, 0x2021,
0x02C6, 0x2030, 0x0000, 0x2039, 0x0152, 0x0000, 0x0000, 0x0000,
0x0000, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
@@ -506,17 +527,28 @@ WCHAR ff_convert ( /* Converted character, Returns zero on error */
WCHAR c;
if (src < 0x80) { /* ASCII */
if ( src < 0x80 ) /* ASCII */
{
c = src;
} else {
if (dir) { /* OEMCP to Unicode */
}
else
{
if ( dir ) /* OEMCP to Unicode */
{
c = ( src >= 0x100 ) ? 0 : Tbl[src - 0x80];
} else { /* Unicode to OEMCP */
for (c = 0; c < 0x80; c++) {
if (src == Tbl[c]) break;
}
else /* Unicode to OEMCP */
{
for ( c = 0; c < 0x80; c++ )
{
if ( src == Tbl[c] )
{
break;
}
}
c = ( c + 0x80 ) & 0xFF;
}
}

72
src/cfg.c Normal file
View File

@@ -0,0 +1,72 @@
#include "cfg.h"
#include "config.h"
#include "uart.h"
#include "fileops.h"
cfg_t CFG =
{
.cfg_ver_maj = 1,
.cfg_ver_min = 0,
.last_game_valid = 0,
.vidmode_menu = VIDMODE_AUTO,
.vidmode_game = VIDMODE_AUTO,
.pair_mode_allowed = 0,
.bsx_use_systime = 0,
.bsx_time = 0x0619970301180530LL
};
int cfg_save()
{
int err = 0;
file_open( CFG_FILE, FA_CREATE_ALWAYS | FA_WRITE );
if ( file_writeblock( &CFG, 0, sizeof( CFG ) ) < sizeof( CFG ) )
{
err = file_res;
}
file_close();
return err;
}
int cfg_load()
{
int err = 0;
file_open( CFG_FILE, FA_READ );
if ( file_readblock( &CFG, 0, sizeof( CFG ) ) < sizeof( CFG ) )
{
err = file_res;
}
file_close();
return err;
}
int cfg_save_last_game( uint8_t *fn )
{
int err = 0;
file_open( LAST_FILE, FA_CREATE_ALWAYS | FA_WRITE );
err = f_puts( ( const TCHAR * )fn, &file_handle );
file_close();
return err;
}
int cfg_get_last_game( uint8_t *fn )
{
int err = 0;
file_open( LAST_FILE, FA_READ );
f_gets( ( TCHAR * )fn, 255, &file_handle );
file_close();
return err;
}
void cfg_set_last_game_valid( uint8_t valid )
{
CFG.last_game_valid = valid;
}
uint8_t cfg_is_last_game_valid()
{
return CFG.last_game_valid;
}

41
src/cfg.h Normal file
View File

@@ -0,0 +1,41 @@
#ifndef _CFG_H
#define _CFG_H
#include <stdint.h>
#define CFG_FILE ((const uint8_t*)"/sd2snes/sd2snes.cfg")
#define LAST_FILE ((const uint8_t*)"/sd2snes/lastgame.cfg")
typedef enum
{
VIDMODE_AUTO = 0,
VIDMODE_60,
VIDMODE_50
} cfg_vidmode_t;
typedef struct _cfg_block
{
uint8_t cfg_ver_maj;
uint8_t cfg_ver_min;
uint8_t last_game_valid;
uint8_t vidmode_menu;
uint8_t vidmode_game;
uint8_t pair_mode_allowed;
uint8_t bsx_use_systime;
uint64_t bsx_time;
} cfg_t;
int cfg_save( void );
int cfg_load( void );
int cfg_save_last_game( uint8_t *fn );
int cfg_get_last_game( uint8_t *fn );
cfg_vidmode_t cfg_get_vidmode_menu( void );
cfg_vidmode_t cfg_get_vidmode_game( void );
void cfg_set_last_game_valid( uint8_t );
uint8_t cfg_is_last_game_valid( void );
uint8_t cfg_is_pair_mode_allowed( void );
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -7,54 +7,80 @@
char *cicstatenames[4] = { "CIC_OK", "CIC_FAIL", "CIC_PAIR", "CIC_SCIC" };
char *cicstatefriendly[4] = {"Original or no CIC", "Original CIC(failed)", "SuperCIC enhanced", "SuperCIC detected, not used"};
void print_cic_state() {
void print_cic_state()
{
printf( "CIC state: %s\n", get_cic_statename( get_cic_state() ) );
}
inline char *get_cic_statefriendlyname(enum cicstates state) {
inline char *get_cic_statefriendlyname( enum cicstates state )
{
return cicstatefriendly[state];
}
inline char *get_cic_statename(enum cicstates state) {
inline char *get_cic_statename( enum cicstates state )
{
return cicstatenames[state];
}
enum cicstates get_cic_state() {
enum cicstates get_cic_state()
{
uint32_t count;
uint32_t togglecount = 0;
uint8_t state, state_old;
state_old = BITBAND( SNES_CIC_STATUS_REG->FIOPIN, SNES_CIC_STATUS_BIT );
/* this loop samples at ~10MHz */
for(count=0; count<CIC_SAMPLECOUNT; count++) {
for ( count = 0; count < CIC_SAMPLECOUNT; count++ )
{
state = BITBAND( SNES_CIC_STATUS_REG->FIOPIN, SNES_CIC_STATUS_BIT );
if(state != state_old) {
if ( state != state_old )
{
togglecount++;
}
state_old = state;
}
printf( "%ld\n", togglecount );
/* CIC_TOGGLE_THRESH_PAIR > CIC_TOGGLE_THRESH_SCIC */
if(togglecount > CIC_TOGGLE_THRESH_PAIR) {
if ( togglecount > CIC_TOGGLE_THRESH_PAIR )
{
return CIC_PAIR;
} else if(togglecount > CIC_TOGGLE_THRESH_SCIC) {
}
else if ( togglecount > CIC_TOGGLE_THRESH_SCIC )
{
return CIC_SCIC;
} else if(state) {
}
else if ( state )
{
return CIC_OK;
} else return CIC_FAIL;
}
else
{
return CIC_FAIL;
}
}
void cic_init(int allow_pairmode) {
void cic_init( int allow_pairmode )
{
BITBAND( SNES_CIC_PAIR_REG->FIODIR, SNES_CIC_PAIR_BIT ) = 1;
if(allow_pairmode) {
if ( allow_pairmode )
{
BITBAND( SNES_CIC_PAIR_REG->FIOCLR, SNES_CIC_PAIR_BIT ) = 1;
} else {
}
else
{
BITBAND( SNES_CIC_PAIR_REG->FIOSET, SNES_CIC_PAIR_BIT ) = 1;
}
}
/* prepare GPIOs for pair mode + set initial modes */
void cic_pair(int init_vmode, int init_d4) {
void cic_pair( int init_vmode, int init_d4 )
{
cic_videomode( init_vmode );
cic_d4( init_d4 );
@@ -62,18 +88,26 @@ void cic_pair(int init_vmode, int init_d4) {
BITBAND( SNES_CIC_D1_REG->FIODIR, SNES_CIC_D1_BIT ) = 1;
}
void cic_videomode(int value) {
if(value) {
void cic_videomode( int value )
{
if ( value )
{
BITBAND( SNES_CIC_D0_REG->FIOSET, SNES_CIC_D0_BIT ) = 1;
} else {
}
else
{
BITBAND( SNES_CIC_D0_REG->FIOCLR, SNES_CIC_D0_BIT ) = 1;
}
}
void cic_d4(int value) {
if(value) {
void cic_d4( int value )
{
if ( value )
{
BITBAND( SNES_CIC_D1_REG->FIOSET, SNES_CIC_D1_BIT ) = 1;
} else {
}
else
{
BITBAND( SNES_CIC_D1_REG->FIOCLR, SNES_CIC_D1_BIT ) = 1;
}
}

380
src/cli.c
View File

@@ -42,6 +42,7 @@
#include "fileops.h"
#include "memory.h"
#include "snes.h"
#include "tests.h"
#include "fpga.h"
#include "fpga_spi.h"
#include "cic.h"
@@ -58,35 +59,42 @@ static char *curchar;
/* Word lists */
static char command_words[] =
"cd\0reset\0sreset\0dir\0ls\0test\0resume\0loadrom\0loadraw\0saveraw\0put\0rm\0d4\0vmode\0mapper\0settime\0time\0setfeature\0hexdump\0w8\0w16\0";
enum { CMD_CD = 0, CMD_RESET, CMD_SRESET, CMD_DIR, CMD_LS, CMD_TEST, CMD_RESUME, CMD_LOADROM, CMD_LOADRAW, CMD_SAVERAW, CMD_PUT, CMD_RM, CMD_D4, CMD_VMODE, CMD_MAPPER, CMD_SETTIME, CMD_TIME, CMD_SETFEATURE, CMD_HEXDUMP, CMD_W8, CMD_W16 };
"cd\0reset\0sreset\0dir\0ls\0test\0exit\0loadrom\0loadraw\0saveraw\0put\0rm\0mkdir\0d4\0vmode\0mapper\0settime\0time\0setfeature\0hexdump\0w8\0w16\0memset\0memtest\0";
enum { CMD_CD = 0, CMD_RESET, CMD_SRESET, CMD_DIR, CMD_LS, CMD_TEST, CMD_EXIT, CMD_LOADROM, CMD_LOADRAW, CMD_SAVERAW, CMD_PUT, CMD_RM, CMD_MKDIR, CMD_D4, CMD_VMODE, CMD_MAPPER, CMD_SETTIME, CMD_TIME, CMD_SETFEATURE, CMD_HEXDUMP, CMD_W8, CMD_W16, CMD_MEMSET, CMD_MEMTEST };
/* ------------------------------------------------------------------------- */
/* Parse functions */
/* ------------------------------------------------------------------------- */
/* Skip spaces at curchar */
static uint8_t skip_spaces(void) {
static uint8_t skip_spaces( void )
{
uint8_t res = ( *curchar == ' ' || *curchar == 0 );
while ( *curchar == ' ' )
{
curchar++;
}
return res;
}
/* Parse the string in curchar for an integer with bounds [lower,upper] */
static int32_t parse_unsigned(uint32_t lower, uint32_t upper, uint8_t base) {
static int32_t parse_unsigned( uint32_t lower, uint32_t upper, uint8_t base )
{
char *end;
uint32_t result;
if (strlen(curchar) == 1 && *curchar == '?') {
if ( strlen( curchar ) == 1 && *curchar == '?' )
{
printf( "Number between %ld[0x%lx] and %ld[0x%lx] expected\n", lower, lower, upper, upper );
return -2;
}
result = strtoul( curchar, &end, base );
if ((*end != ' ' && *end != 0) || errno != 0) {
if ( ( *end != ' ' && *end != 0 ) || errno != 0 )
{
printf( "Invalid numeric argument\n" );
return -1;
}
@@ -94,7 +102,8 @@ static int32_t parse_unsigned(uint32_t lower, uint32_t upper, uint8_t base) {
curchar = end;
skip_spaces();
if (result < lower || result > upper) {
if ( result < lower || result > upper )
{
printf( "Numeric argument out of range (%ld..%ld)\n", lower, upper );
return -1;
}
@@ -102,112 +111,157 @@ static int32_t parse_unsigned(uint32_t lower, uint32_t upper, uint8_t base) {
return result;
}
/* Parse the string starting with curchar for a word in wordlist */
static int8_t parse_wordlist(char *wordlist) {
static int8_t parse_wordlist( char *wordlist )
{
uint8_t i, matched;
char *cur, *ptr;
char c;
unsigned char *cur, *ptr;
unsigned char c;
i = 0;
ptr = wordlist;
ptr = ( unsigned char * )wordlist;
// Command list on "?"
if (strlen(curchar) == 1 && *curchar == '?') {
if ( strlen( curchar ) == 1 && *curchar == '?' )
{
printf( "Commands available: \n " );
while (1) {
while ( 1 )
{
c = *ptr++;
if (c == 0) {
if (*ptr == 0) {
if ( c == 0 )
{
if ( *ptr == 0 )
{
printf( "\n" );
return -2;
} else {
}
else
{
printf( "\n " );
}
} else
}
else
{
uart_putc( c );
}
}
}
while (1) {
cur = curchar;
while ( 1 )
{
cur = ( unsigned char * )curchar;
matched = 1;
c = *ptr;
do {
do
{
// If current word list character is \0: No match found
if (c == 0) {
if ( c == 0 )
{
printf( "Unknown word: %s\n(use ? for help)", curchar );
return -1;
}
if (tolower(c) != tolower(*cur)) {
if ( tolower( ( int )c ) != tolower( ( int )*cur ) )
{
// Check for end-of-word
if (cur != curchar && (*cur == ' ' || *cur == 0)) {
if ( cur != ( unsigned char * )curchar && ( *cur == ' ' || *cur == 0 ) )
{
// Partial match found, return that
break;
} else {
}
else
{
matched = 0;
break;
}
}
ptr++;
cur++;
c = *ptr;
} while (c != 0);
}
while ( c != 0 );
if (matched) {
if ( matched )
{
char *tmp = curchar;
curchar = cur;
curchar = ( char * )cur;
// Return match only if whitespace or end-of-string follows
// (avoids mismatching partial words)
if (skip_spaces()) {
if ( skip_spaces() )
{
return i;
} else {
}
else
{
printf( "Unknown word: %s\n(use ? for help)\n", tmp );
return -1;
}
} else {
}
else
{
// Try next word in list
i++;
while ( *ptr++ != 0 ) ;
}
}
}
/* Read a line from serial, uses cmdbuffer as storage */
static char *getline(char *prompt) {
static char *getline( char *prompt )
{
int i = 0;
char c;
printf( "\n%s", prompt );
memset( cmdbuffer, 0, sizeof( cmdbuffer ) );
while (1) {
while ( 1 )
{
c = uart_getc();
if (c == 13)
break;
if (c == 27 || c == 3) {
if ( c == 13 )
{
break;
}
if ( c == 27 || c == 3 )
{
printf( "\\\n%s", prompt );
i = 0;
memset( cmdbuffer, 0, sizeof( cmdbuffer ) );
continue;
}
if (c == 127 || c == 8) {
if (i > 0) {
if ( c == 127 || c == 8 )
{
if ( i > 0 )
{
i--;
uart_putc( 8 ); // backspace
uart_putc( ' ' ); // erase character
uart_putc( 8 ); // backspace
} else
}
else
{
continue;
} else {
if (i < sizeof(cmdbuffer)-1) {
}
}
else
{
if ( i < sizeof( cmdbuffer ) - 1 )
{
cmdbuffer[i++] = c;
uart_putc( c );
}
}
}
cmdbuffer[i] = 0;
return cmdbuffer;
}
@@ -218,7 +272,8 @@ static char *getline(char *prompt) {
/* ------------------------------------------------------------------------- */
/* Reset */
static void cmd_reset(void) {
static void cmd_reset( void )
{
/* force watchdog reset */
LPC_WDT->WDTC = 256; // minimal timeout
LPC_WDT->WDCLKSEL = BV( 31 ); // internal RC, lock register
@@ -228,7 +283,8 @@ static void cmd_reset(void) {
}
/* Show the contents of the current directory */
static void cmd_show_directory(void) {
static void cmd_show_directory( void )
{
FRESULT res;
DIR dh;
FILINFO finfo;
@@ -237,7 +293,9 @@ static void cmd_show_directory(void) {
f_getcwd( ( TCHAR * )file_lfn, 255 );
res = f_opendir( &dh, ( TCHAR * )file_lfn );
if (res != FR_OK) {
if ( res != FR_OK )
{
printf( "f_opendir failed, result %d\n", res );
return;
}
@@ -245,132 +303,203 @@ static void cmd_show_directory(void) {
finfo.lfname = ( TCHAR * )file_lfn;
finfo.lfsize = 255;
do {
do
{
/* Read the next entry */
res = f_readdir( &dh, &finfo );
if (res != FR_OK) {
if ( res != FR_OK )
{
printf( "f_readdir failed, result %d\n", res );
return;
}
/* Abort if none was found */
if ( !finfo.fname[0] )
{
break;
}
/* Skip volume labels */
if ( finfo.fattrib & AM_VOL )
{
continue;
}
/* Select between LFN and 8.3 name */
if ( finfo.lfname[0] )
{
name = ( uint8_t * )finfo.lfname;
else {
}
else
{
name = ( uint8_t * )finfo.fname;
strlwr( ( char * )name );
}
printf("%s",name);
printf( "%s [%s] (%ld)", finfo.lfname, finfo.fname, finfo.fsize );
/* Directory indicator (Unix-style) */
if ( finfo.fattrib & AM_DIR )
{
uart_putc( '/' );
}
printf( "\n" );
} while (finfo.fname[0]);
}
while ( finfo.fname[0] );
}
static void cmd_loadrom(void) {
static void cmd_loadrom( void )
{
uint32_t address = 0;
uint8_t flags = LOADROM_WITH_SRAM | LOADROM_WITH_RESET;
load_rom( ( uint8_t * )curchar, address, flags );
}
static void cmd_loadraw(void) {
static void cmd_loadraw( void )
{
uint32_t address = parse_unsigned( 0, 16777216, 16 );
load_sram( ( uint8_t * )curchar, address );
}
static void cmd_saveraw(void) {
static void cmd_saveraw( void )
{
uint32_t address = parse_unsigned( 0, 16777216, 16 );
uint32_t length = parse_unsigned( 0, 16777216, 16 );
if ( address != -1 && length != -1 )
{
save_sram( ( uint8_t * )curchar, length, address );
}
}
static void cmd_d4(void) {
static void cmd_d4( void )
{
int32_t hz;
if(get_cic_state() != CIC_PAIR) {
if ( get_cic_state() != CIC_PAIR )
{
printf( "not in pair mode\n" );
} else {
}
else
{
hz = parse_unsigned( 50, 60, 10 );
if(hz==50) {
if ( hz == 50 )
{
cic_d4( CIC_PAL );
} else {
}
else
{
cic_d4( CIC_NTSC );
}
printf( "ok\n" );
}
}
static void cmd_vmode(void) {
static void cmd_vmode( void )
{
int32_t hz;
if(get_cic_state() != CIC_PAIR) {
if ( get_cic_state() != CIC_PAIR )
{
printf( "not in pair mode\n" );
} else {
}
else
{
hz = parse_unsigned( 50, 60, 10 );
if(hz==50) {
if ( hz == 50 )
{
cic_videomode( CIC_PAL );
} else {
}
else
{
cic_videomode( CIC_NTSC );
}
printf( "ok\n" );
}
}
void cmd_put(void) {
if(*curchar != 0) {
void cmd_put( void )
{
if ( *curchar != 0 )
{
file_open( ( uint8_t * )curchar, FA_CREATE_ALWAYS | FA_WRITE );
if(file_res) {
if ( file_res )
{
printf( "FAIL: error opening file %s\n", curchar );
} else {
}
else
{
printf( "OK, start xmodem transfer now.\n" );
xmodem_rxfile( &file_handle );
}
file_close();
} else {
}
else
{
printf( "Usage: put <filename>\n" );
}
}
void cmd_rm(void) {
void cmd_rm( void )
{
FRESULT res = f_unlink( curchar );
if(res) printf("Error %d removing %s\n", res, curchar);
if ( res )
{
printf( "Error %d removing %s\n", res, curchar );
}
}
void cmd_mapper(void) {
void cmd_mkdir( void )
{
FRESULT res = f_mkdir( curchar );
if ( res )
{
printf( "Error %d creating directory %s\n", res, curchar );
}
}
void cmd_mapper( void )
{
int32_t mapper;
mapper = parse_unsigned( 0, 7, 10 );
set_mapper( ( uint8_t )mapper & 0x7 );
printf( "mapper set to %ld\n", mapper );
}
void cmd_sreset(void) {
if(*curchar != 0) {
void cmd_sreset( void )
{
if ( *curchar != 0 )
{
int32_t resetstate;
resetstate = parse_unsigned( 0, 1, 10 );
snes_reset( resetstate );
} else {
snes_reset(1);
delay_ms(20);
snes_reset(0);
}
else
{
snes_reset_pulse();
}
}
void cmd_settime(void) {
void cmd_settime( void )
{
struct tm time;
if(strlen(curchar) != 4+2+2 + 2+2+2) {
if ( strlen( curchar ) != 4 + 2 + 2 + 2 + 2 + 2 )
{
printf( "invalid time format (need YYYYMMDDhhmmss)\n" );
} else {
}
else
{
time.tm_sec = atoi( curchar + 4 + 2 + 2 + 2 + 2 );
curchar[4 + 2 + 2 + 2 + 2] = 0;
time.tm_min = atoi( curchar + 4 + 2 + 2 + 2 );
@@ -386,105 +515,148 @@ void cmd_settime(void) {
}
}
void cmd_time(void) {
void cmd_time( void )
{
struct tm time;
read_rtc( &time );
printf( "%04d-%02d-%02d %02d:%02d:%02d\n", time.tm_year, time.tm_mon,
time.tm_mday, time.tm_hour, time.tm_min, time.tm_sec );
}
void cmd_setfeature(void) {
void cmd_setfeature( void )
{
uint8_t feat = parse_unsigned( 0, 255, 16 );
fpga_set_features( feat );
}
void cmd_hexdump(void) {
void cmd_hexdump( void )
{
uint32_t offset = parse_unsigned( 0, 16777215, 16 );
uint32_t len = parse_unsigned( 0, 16777216, 16 );
sram_hexdump( offset, len );
}
void cmd_w8(void) {
void cmd_w8( void )
{
uint32_t offset = parse_unsigned( 0, 16777215, 16 );
uint8_t val = parse_unsigned( 0, 255, 16 );
sram_writebyte( val, offset );
}
void cmd_w16(void) {
void cmd_w16( void )
{
uint32_t offset = parse_unsigned( 0, 16777215, 16 );
uint16_t val = parse_unsigned( 0, 65535, 16 );
sram_writeshort( val, offset );
}
void cmd_memset( void )
{
uint32_t offset = parse_unsigned( 0, 16777215, 16 );
uint32_t len = parse_unsigned( 0, 16777216, 16 );
uint8_t val = parse_unsigned( 0, 255, 16 );
sram_memset( offset, len, val );
}
/* ------------------------------------------------------------------------- */
/* CLI interface functions */
/* ------------------------------------------------------------------------- */
void cli_init(void) {
void cli_init( void )
{
}
void cli_entrycheck() {
if(uart_gotc() && uart_getc() == 27) {
void cli_entrycheck()
{
if ( uart_gotc() && uart_getc() == 27 )
{
printf( "*** BREAK\n" );
cli_loop();
}
}
void cli_loop(void) {
while (1) {
void cli_loop( void )
{
while ( 1 )
{
curchar = getline( ">" );
printf( "\n" );
/* Process medium changes before executing the command */
if (disk_state != DISK_OK && disk_state != DISK_REMOVED) {
if ( disk_state != DISK_OK && disk_state != DISK_REMOVED )
{
FRESULT res;
printf( "Medium changed... " );
res = f_mount( 0, &fatfs );
if (res != FR_OK) {
if ( res != FR_OK )
{
printf( "Failed to mount new medium, result %d\n", res );
} else {
}
else
{
printf( "Ok\n" );
}
}
/* Remove whitespace */
while (*curchar == ' ') curchar++;
while ( *curchar == ' ' )
{
curchar++;
}
while ( strlen( curchar ) > 0 && curchar[strlen( curchar ) - 1] == ' ' )
{
curchar[strlen( curchar ) - 1] = 0;
}
/* Ignore empty lines */
if ( strlen( curchar ) == 0 )
{
continue;
}
/* Parse command */
int8_t command = parse_wordlist( command_words );
if ( command < 0 )
{
continue;
}
FRESULT res;
switch (command) {
switch ( command )
{
case CMD_CD:
#if _FS_RPATH
if (strlen(curchar) == 0) {
if ( strlen( curchar ) == 0 )
{
f_getcwd( ( TCHAR * )file_lfn, 255 );
printf( "%s\n", file_lfn );
break;
}
res = f_chdir( ( const TCHAR * )curchar );
if (res != FR_OK) {
if ( res != FR_OK )
{
printf( "chdir %s failed with result %d\n", curchar, res );
} else {
}
else
{
printf( "Ok.\n" );
}
#else
printf( "cd not supported.\n" );
res;
#endif
break;
case CMD_RESET:
cmd_reset();
break;
@@ -498,7 +670,7 @@ void cli_loop(void) {
cmd_show_directory();
break;
case CMD_RESUME:
case CMD_EXIT:
return;
break;
@@ -518,6 +690,10 @@ void cli_loop(void) {
cmd_rm();
break;
case CMD_MKDIR:
cmd_mkdir();
break;
case CMD_D4:
cmd_d4();
break;
@@ -561,7 +737,15 @@ void cli_loop(void) {
case CMD_W16:
cmd_w16();
break;
}
case CMD_MEMSET:
cmd_memset();
break;
case CMD_MEMTEST:
test_mem();
break;
}
}
}

View File

@@ -7,12 +7,14 @@
#include "bits.h"
#include "uart.h"
void clock_disconnect() {
void clock_disconnect()
{
disconnectPLL0();
disablePLL0();
}
void clock_init() {
void clock_init()
{
/* set flash access time to 5 clks (80<f<=100MHz) */
setFlashAccessTime( 5 );
@@ -27,7 +29,7 @@ void clock_init() {
-> FPGA freq = 11289473.7Hz
First, disable and disconnect PLL0.
*/
// clock_disconnect();
clock_disconnect();
/* PLL is disabled and disconnected. setup PCLK NOW as it cannot be changed
reliably with PLL0 connected.
@@ -48,62 +50,73 @@ void clock_init() {
*/
enableMainOsc();
setClkSrc( CLKSRC_MAINOSC );
// XXX setPLL0MultPrediv(429, 19);
// XXX setPLL0MultPrediv(23, 2);
setPLL0MultPrediv(12, 1);
setPLL0MultPrediv( 22, 1 );
enablePLL0();
setCCLKDiv(3);
setCCLKDiv( 6 );
connectPLL0();
}
void setFlashAccessTime(uint8_t clocks) {
void setFlashAccessTime( uint8_t clocks )
{
LPC_SC->FLASHCFG = FLASHTIM( clocks );
}
void setPLL0MultPrediv(uint16_t mult, uint8_t prediv) {
void setPLL0MultPrediv( uint16_t mult, uint8_t prediv )
{
LPC_SC->PLL0CFG = PLL_MULT( mult ) | PLL_PREDIV( prediv );
PLL0feed();
}
void enablePLL0() {
void enablePLL0()
{
LPC_SC->PLL0CON |= PLLE0;
PLL0feed();
}
void disablePLL0() {
void disablePLL0()
{
LPC_SC->PLL0CON &= ~PLLE0;
PLL0feed();
}
void connectPLL0() {
void connectPLL0()
{
while ( !( LPC_SC->PLL0STAT & PLOCK0 ) );
LPC_SC->PLL0CON |= PLLC0;
PLL0feed();
}
void disconnectPLL0() {
void disconnectPLL0()
{
LPC_SC->PLL0CON &= ~PLLC0;
PLL0feed();
}
void setCCLKDiv(uint8_t div) {
void setCCLKDiv( uint8_t div )
{
LPC_SC->CCLKCFG = CCLK_DIV( div );
}
void enableMainOsc() {
void enableMainOsc()
{
LPC_SC->SCS = OSCEN;
while ( !( LPC_SC->SCS & OSCSTAT ) );
}
void disableMainOsc() {
void disableMainOsc()
{
LPC_SC->SCS = 0;
}
void PLL0feed() {
void PLL0feed()
{
LPC_SC->PLL0FEED = 0xaa;
LPC_SC->PLL0FEED = 0x55;
}
void setClkSrc(uint8_t src) {
void setClkSrc( uint8_t src )
{
LPC_SC->CLKSRCSEL = src;
}

View File

@@ -74,6 +74,4 @@ void disableMainOsc(void);
void PLL0feed( void );
void setClkSrc( uint8_t src );
#endif

View File

@@ -1,4 +1,4 @@
CONFIG_VERSION="0.1.3"
CONFIG_VERSION="0.1.5"
#FWVER=00010300
CONFIG_FWVER=66304
CONFIG_FWVER=0x00010500
CONFIG_MCU_FOSC=12000000

View File

@@ -35,18 +35,15 @@
#define CONFIG_UART_NUM 3
// #define CONFIG_CPU_FREQUENCY 90315789
#define CONFIG_CPU_FREQUENCY 96000000
#define CONFIG_CPU_FREQUENCY 88000000
//#define CONFIG_CPU_FREQUENCY 46000000
#define CONFIG_UART_PCLKDIV 1
#define CONFIG_UART_TX_BUF_SHIFT 8
#define CONFIG_UART_BAUDRATE 921600
//#define CONFIG_UART_BAUDRATE 921600
#define CONFIG_UART_BAUDRATE 115200
#define CONFIG_UART_DEADLOCKABLE
#define SSP_CLK_DIVISOR_FAST 2
#define SSP_CLK_DIVISOR_SLOW 250
#define SSP_CLK_DIVISOR_FPGA_FAST 6
#define SSP_CLK_DIVISOR_FPGA_SLOW 20
#define SSP_CLK_DIVISOR 2
#define SNES_RESET_REG LPC_GPIO1
#define SNES_RESET_BIT 26
@@ -67,7 +64,11 @@
#define FPGA_MCU_RDY_BIT 9
#define QSORT_MAXELEM 2048
#define SORT_STRLEN 256
#define CLTBL_SIZE 100
#define DIR_FILE_MAX 16380
#define SSP_REGS LPC_SSP0
#define SSP_PCLKREG PCLKSEL1
// 1: PCLKSEL0

View File

@@ -20,7 +20,8 @@
/**
* Static table used for the table_driven implementation.
*****************************************************************************/
static const uint16_t crc_table[256] = {
static const uint16_t crc_table[256] =
{
0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,

View File

@@ -22,7 +22,8 @@
/**
* Static table used for the table_driven implementation.
*****************************************************************************/
static const uint32_t crc32_table[256] = {
static const uint32_t crc32_table[256] =
{
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,

View File

@@ -16,7 +16,8 @@
typedef BYTE DSTATUS;
/* Results of Disk Functions */
typedef enum {
typedef enum
{
RES_OK = 0, /* 0: Successful */
RES_ERROR, /* 1: R/W Error */
RES_WRPRT, /* 2: Write Protected */
@@ -35,7 +36,8 @@ typedef enum {
* This is the struct returned in the data buffer when disk_getinfo
* is called with page=0.
*/
typedef struct {
typedef struct
{
uint8_t validbytes;
uint8_t maxpage;
uint8_t disktype;
@@ -55,7 +57,7 @@ DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE);
#if _READONLY == 0
DRESULT disk_write ( BYTE, const BYTE *, DWORD, BYTE );
#endif
#define disk_ioctl(a,b,c) RES_OK
DRESULT disk_ioctl ( BYTE, BYTE, void * );
void disk_init( void );

View File

@@ -1,20 +1,25 @@
#include <arm/NXP/LPC17xx/LPC17xx.h>
#include "uart.h"
void HardFault_Handler(void) {
void HardFault_Handler( void )
{
printf( "HFSR: %lx\n", SCB->HFSR );
while ( 1 ) ;
}
void MemManage_Handler(void) {
void MemManage_Handler( void )
{
printf( "MemManage - CFSR: %lx; MMFAR: %lx\n", SCB->CFSR, SCB->MMFAR );
}
void BusFault_Handler(void) {
void BusFault_Handler( void )
{
printf( "BusFault - CFSR: %lx; BFAR: %lx\n", SCB->CFSR, SCB->BFAR );
}
void UsageFault_Handler(void) {
void UsageFault_Handler( void )
{
printf( "UsageFault - CFSR: %lx; BFAR: %lx\n", SCB->CFSR, SCB->BFAR );
}

3292
src/ff.c

File diff suppressed because it is too large Load Diff

View File

@@ -229,7 +229,8 @@ extern "C" {
#if _MULTI_PARTITION /* Multiple partition configuration */
#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive# */
#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition# */
typedef struct {
typedef struct
{
BYTE pd; /* Physical drive# */
BYTE pt; /* Partition # (0-3) */
} PARTITION;
@@ -268,7 +269,8 @@ typedef char TCHAR;
/* File system object structure (FATFS) */
typedef struct {
typedef struct
{
BYTE fs_type; /* FAT sub-type (0:Not mounted) */
BYTE drv; /* Physical drive number */
BYTE csize; /* Sectors per cluster (1,2,4...128) */
@@ -304,7 +306,8 @@ typedef struct {
/* File object structure (FIL) */
typedef struct {
typedef struct
{
FATFS *fs; /* Pointer to the owner file system object */
WORD id; /* Owner file system mount ID */
BYTE flag; /* File status flags */
@@ -333,7 +336,8 @@ typedef struct {
/* Directory object structure (DIR) */
typedef struct {
typedef struct
{
FATFS *fs; /* Pointer to the owner file system object */
WORD id; /* Owner file system mount ID */
WORD index; /* Current read/write index number */
@@ -352,7 +356,8 @@ typedef struct {
/* File status structure (FILINFO) */
typedef struct {
typedef struct
{
DWORD fsize; /* File size */
WORD fdate; /* Last modified date */
WORD ftime; /* Last modified time */
@@ -369,7 +374,8 @@ typedef struct {
/* File function return code (FRESULT) */
typedef enum {
typedef enum
{
FR_OK = 0, /* (0) Succeeded */
FR_DISK_ERR, /* (1) A hard error occured in the low level disk I/O layer */
FR_INT_ERR, /* (2) Assertion failed */
@@ -397,7 +403,8 @@ typedef enum {
/* FatFs module application interface */
/* Low Level functions */
FRESULT l_openfilebycluster(FATFS *fs, FIL *fp, const TCHAR *path, DWORD clust, DWORD fsize); /* Open a file by its start cluster using supplied file size */
FRESULT l_openfilebycluster( FATFS *fs, FIL *fp, const TCHAR *path, DWORD clust,
DWORD fsize ); /* Open a file by its start cluster using supplied file size */
FRESULT l_opendirbycluster ( FATFS *fs, DIR *dj, const TCHAR *path, DWORD clust );
/* application level functions */

View File

@@ -37,81 +37,113 @@ WCHAR ff_convert(WCHAR w, UINT dir) {
int newcard;
void file_init() {
void file_init()
{
file_res = f_mount( 0, &fatfs );
newcard = 0;
}
void file_reinit(void) {
void file_reinit( void )
{
disk_init();
file_init();
}
FRESULT dir_open_by_filinfo(DIR* dir, FILINFO* fno) {
FRESULT dir_open_by_filinfo( DIR *dir, FILINFO *fno )
{
return l_opendirbycluster( &fatfs, dir, ( TCHAR * )"", fno->clust );
}
void file_open_by_filinfo(FILINFO* fno) {
void file_open_by_filinfo( FILINFO *fno )
{
file_res = l_openfilebycluster( &fatfs, &file_handle, ( TCHAR * )"", fno->clust, fno->fsize );
}
void file_open(const uint8_t* filename, BYTE flags) {
if (disk_state == DISK_CHANGED) {
void file_open( const uint8_t *filename, BYTE flags )
{
if ( disk_state == DISK_CHANGED )
{
file_reinit();
newcard = 1;
}
file_res = f_open( &file_handle, ( TCHAR * )filename, flags );
file_block_off = sizeof( file_buf );
file_block_max = sizeof( file_buf );
file_status = file_res ? FILE_ERR : FILE_OK;
}
void file_close() {
void file_close()
{
file_res = f_close( &file_handle );
}
void file_seek(uint32_t offset) {
void file_seek( uint32_t offset )
{
file_res = f_lseek( &file_handle, ( DWORD )offset );
}
UINT file_read() {
UINT file_read()
{
UINT bytes_read;
file_res = f_read( &file_handle, file_buf, sizeof( file_buf ), &bytes_read );
return bytes_read;
}
UINT file_write() {
UINT file_write()
{
UINT bytes_written;
file_res = f_write( &file_handle, file_buf, sizeof( file_buf ), &bytes_written );
if(bytes_written < sizeof(file_buf)) {
if ( bytes_written < sizeof( file_buf ) )
{
printf( "wrote less than expected - card full?\n" );
}
return bytes_written;
}
UINT file_readblock(void* buf, uint32_t addr, uint16_t size) {
UINT file_readblock( void *buf, uint32_t addr, uint16_t size )
{
UINT bytes_read;
file_res = f_lseek( &file_handle, addr );
if(file_handle.fptr != addr) {
if ( file_handle.fptr != addr )
{
return 0;
}
file_res = f_read( &file_handle, buf, size, &bytes_read );
return bytes_read;
}
UINT file_writeblock(void* buf, uint32_t addr, uint16_t size) {
UINT file_writeblock( void *buf, uint32_t addr, uint16_t size )
{
UINT bytes_written;
file_res = f_lseek( &file_handle, addr );
if(file_res) return 0;
if ( file_res )
{
return 0;
}
file_res = f_write( &file_handle, buf, size, &bytes_written );
return bytes_written;
}
uint8_t file_getc() {
if(file_block_off == file_block_max) {
uint8_t file_getc()
{
if ( file_block_off == file_block_max )
{
file_block_max = file_read();
if(file_block_max == 0) file_status = FILE_EOF;
if ( file_block_max == 0 )
{
file_status = FILE_EOF;
}
file_block_off = 0;
}
return file_buf[file_block_off++];
}

View File

@@ -31,36 +31,47 @@
#include "ff.h"
#include "smc.h"
#include "fileops.h"
#include "crc32.h"
#include "crc.h"
#include "memory.h"
#include "led.h"
#include "sort.h"
uint16_t scan_flat(const char* path) {
uint16_t scan_flat( const char *path )
{
DIR dir;
FRESULT res;
FILINFO fno;
fno.lfname = NULL;
res = f_opendir( &dir, ( TCHAR * )path );
uint16_t numentries = 0;
if (res == FR_OK) {
for (;;) {
if ( res == FR_OK )
{
for ( ;; )
{
res = f_readdir( &dir, &fno );
if(res != FR_OK || fno.fname[0] == 0)break;
if ( res != FR_OK || fno.fname[0] == 0 )
{
break;
}
numentries++;
}
}
return numentries;
}
uint32_t scan_dir(char* path, FILINFO* fno_param, char mkdb, uint32_t this_dir_tgt) {
uint32_t scan_dir( char *path, FILINFO *fno_param, char mkdb, uint32_t this_dir_tgt )
{
DIR dir;
FILINFO fno;
FRESULT res;
uint8_t len;
TCHAR *fn;
static unsigned char depth = 0;
static uint32_t crc;
static uint32_t crc, fncrc;
static uint32_t db_tgt;
static uint32_t next_subdir_tgt;
static uint32_t parent_tgt;
@@ -69,6 +80,7 @@ uint32_t scan_dir(char* path, FILINFO* fno_param, char mkdb, uint32_t this_dir_t
static uint16_t num_files_total = 0;
static uint16_t num_dirs_total = 0;
uint32_t dir_tgt;
uint32_t switched_dir_tgt = 0;
uint16_t numentries;
uint32_t dirsize;
uint8_t pass = 0;
@@ -76,9 +88,12 @@ uint32_t scan_dir(char* path, FILINFO* fno_param, char mkdb, uint32_t this_dir_t
char *size_units[3] = {" ", "k", "M"};
uint32_t entry_fsize;
uint8_t entry_unit_idx;
uint16_t entrycnt;
dir_tgt = this_dir_tgt;
if(depth==0) {
if ( depth == 0 )
{
crc = 0;
db_tgt = SRAM_DB_ADDR + 0x10;
dir_tgt = SRAM_DIR_ADDR;
@@ -91,36 +106,70 @@ uint32_t scan_dir(char* path, FILINFO* fno_param, char mkdb, uint32_t this_dir_t
fno.lfsize = 255;
fno.lfname = ( TCHAR * )file_lfn;
numentries = 0;
for(pass = 0; pass < 2; pass++) {
if(pass) {
num_dirs_total++;
for ( pass = 0; pass < ( mkdb ? 2 : 1 ); pass++ )
{
if ( pass )
{
dirsize = 4 * ( numentries );
if ( ( ( next_subdir_tgt + dirsize + 8 ) & 0xff0000 ) > ( next_subdir_tgt & 0xff0000 ) )
{
printf( "switchdir! old=%lX ", next_subdir_tgt + dirsize + 4 );
next_subdir_tgt &= 0xffff0000;
next_subdir_tgt += 0x00010004;
printf( "new=%lx\n", next_subdir_tgt );
dir_tgt &= 0xffff0000;
dir_tgt += 0x00010004;
}
switched_dir_tgt = dir_tgt;
next_subdir_tgt += dirsize + 4;
if(parent_tgt) next_subdir_tgt += 4;
if(next_subdir_tgt > dir_end) {
if ( parent_tgt )
{
next_subdir_tgt += 4;
}
if ( next_subdir_tgt > dir_end )
{
dir_end = next_subdir_tgt;
}
DBG_FS printf("path=%s depth=%d ptr=%lx entries=%d parent=%lx next subdir @%lx\n", path, depth, db_tgt, numentries, parent_tgt, next_subdir_tgt);
if(mkdb) {
DBG_FS printf( "path=%s depth=%d ptr=%lx entries=%d parent=%lx next subdir @%lx\n", path, depth, db_tgt, numentries,
parent_tgt, next_subdir_tgt );
if ( mkdb )
{
num_dirs_total++;
// printf("d=%d Saving %lx to Address %lx [end]\n", depth, 0L, next_subdir_tgt - 4);
sram_writelong( 0L, next_subdir_tgt - 4 );
}
}
if(fno_param) {
if ( fno_param )
{
res = dir_open_by_filinfo( &dir, fno_param );
} else {
}
else
{
res = f_opendir( &dir, path );
}
if (res == FR_OK) {
if(pass && parent_tgt && mkdb) {
if ( res == FR_OK )
{
if ( pass && parent_tgt && mkdb )
{
/* write backlink to parent dir
switch to next bank if record does not fit in current bank */
if((db_tgt&0xffff) > ((0x10000-(sizeof(next_subdir_tgt)+sizeof(len)+4))&0xffff)) {
if ( ( db_tgt & 0xffff ) > ( ( 0x10000 - ( sizeof( next_subdir_tgt ) + sizeof( len ) + 4 ) ) & 0xffff ) )
{
printf( "switch! old=%lx ", db_tgt );
db_tgt &= 0xffff0000;
db_tgt += 0x00010000;
printf( "new=%lx\n", db_tgt );
}
// printf("writing link to parent, %lx to address %lx [../]\n", parent_tgt-SRAM_MENU_ADDR, db_tgt);
sram_writelong( ( parent_tgt - SRAM_MENU_ADDR ), db_tgt );
sram_writebyte( 0, db_tgt + sizeof( next_subdir_tgt ) );
@@ -129,86 +178,134 @@ uint32_t scan_dir(char* path, FILINFO* fno_param, char mkdb, uint32_t this_dir_t
db_tgt += sizeof( next_subdir_tgt ) + sizeof( len ) + 4;
dir_tgt += 4;
}
len = strlen( ( char * )path );
for (;;) {
/* scan at most DIR_FILE_MAX entries per directory */
for ( entrycnt = 0; entrycnt < DIR_FILE_MAX; entrycnt++ )
{
// toggle_read_led();
res = f_readdir( &dir, &fno );
if (res != FR_OK || fno.fname[0] == 0) {
if(pass) {
if(!numentries) was_empty=1;
if ( res != FR_OK || fno.fname[0] == 0 )
{
if ( pass )
{
/* if(!numentries) was_empty=1;*/
}
break;
}
fn = *fno.lfname ? fno.lfname : fno.fname;
if ((*fn == '.') || !(memcmp(fn, SYS_DIR_NAME, sizeof(SYS_DIR_NAME)))) continue;
if (fno.fattrib & AM_DIR) {
if ( ( *fn == '.' ) || !( strncasecmp( fn, SYS_DIR_NAME, sizeof( SYS_DIR_NAME ) ) ) )
{
continue;
}
if ( fno.fattrib & AM_DIR )
{
depth++;
if(depth < FS_MAX_DEPTH) {
if ( depth < FS_MAX_DEPTH )
{
numentries++;
if(pass) {
if ( pass && mkdb )
{
path[len] = '/';
strncpy( path + len + 1, ( char * )fn, sizeof( fs_path ) - len );
if(mkdb) {
uint16_t pathlen = strlen(path);
// printf("d=%d Saving %lx to Address %lx [dir]\n", depth, db_tgt, dir_tgt);
uint16_t pathlen = 0;
uint32_t old_db_tgt = 0;
if ( mkdb )
{
pathlen = strlen( path );
DBG_FS printf( "d=%d Saving %lx to Address %lx [dir]\n", depth, db_tgt, dir_tgt );
/* save element:
- path name
- pointer to sub dir structure */
if((db_tgt&0xffff) > ((0x10000-(sizeof(next_subdir_tgt) + sizeof(len) + pathlen + 2))&0xffff)) {
if ( ( db_tgt & 0xffff ) > ( ( 0x10000 - ( sizeof( next_subdir_tgt ) + sizeof( len ) + pathlen + 2 ) ) & 0xffff ) )
{
printf( "switch! old=%lx ", db_tgt );
db_tgt &= 0xffff0000;
db_tgt += 0x00010000;
printf( "new=%lx\n", db_tgt );
}
// printf(" Saving dir descriptor to %lx tgt=%lx, path=%s\n", db_tgt, next_subdir_tgt, path);
/* write element pointer to current dir structure */
sram_writelong( ( db_tgt - SRAM_MENU_ADDR ) | ( ( uint32_t )0x80 << 24 ), dir_tgt );
/* save element:
- path name
- pointer to sub dir structure */
sram_writelong((next_subdir_tgt-SRAM_MENU_ADDR), db_tgt);
sram_writebyte(len+1, db_tgt+sizeof(next_subdir_tgt));
sram_writeblock(path, db_tgt+sizeof(next_subdir_tgt)+sizeof(len), pathlen);
sram_writeblock("/\0", db_tgt + sizeof(next_subdir_tgt) + sizeof(len) + pathlen, 2);
- pointer to sub dir structure
moved below */
old_db_tgt = db_tgt;
db_tgt += sizeof( next_subdir_tgt ) + sizeof( len ) + pathlen + 2;
}
parent_tgt = this_dir_tgt;
scan_dir(path, &fno, mkdb, next_subdir_tgt);
/* scan subdir before writing current dir element to account for bank switches */
uint32_t corrected_subdir_tgt = scan_dir( path, &fno, mkdb, next_subdir_tgt );
if ( mkdb )
{
DBG_FS printf( " Saving dir descriptor to %lx tgt=%lx, path=%s\n", old_db_tgt, corrected_subdir_tgt, path );
sram_writelong( ( corrected_subdir_tgt - SRAM_MENU_ADDR ), old_db_tgt );
sram_writebyte( len + 1, old_db_tgt + sizeof( next_subdir_tgt ) );
sram_writeblock( path, old_db_tgt + sizeof( next_subdir_tgt ) + sizeof( len ), pathlen );
sram_writeblock( "/\0", old_db_tgt + sizeof( next_subdir_tgt ) + sizeof( len ) + pathlen, 2 );
}
dir_tgt += 4;
was_empty = 0;
/* was_empty = 0;*/
}
else if ( !mkdb )
{
path[len] = '/';
strncpy( path + len + 1, ( char * )fn, sizeof( fs_path ) - len );
scan_dir( path, &fno, mkdb, next_subdir_tgt );
}
}
depth--;
path[len] = 0;
} else {
}
else
{
SNES_FTYPE type = determine_filetype( ( char * )fn );
if(type != TYPE_UNKNOWN) {
num_files_total++;
if ( type != TYPE_UNKNOWN )
{
numentries++;
if(pass) {
if(mkdb) {
if ( pass )
{
if ( mkdb )
{
num_files_total++;
/* snes_romprops_t romprops; */
path[len] = '/';
strncpy( path + len + 1, ( char * )fn, sizeof( fs_path ) - len );
uint16_t pathlen = strlen( path );
switch(type) {
switch ( type )
{
case TYPE_IPS:
case TYPE_SMC:
/* file_open_by_filinfo(&fno);
if(file_res){
printf("ZOMG NOOOO %d\n", file_res);
}
smc_id(&romprops);
file_close(); */
case TYPE_SPC:
/* write element pointer to current dir structure */
DBG_FS printf( "d=%d Saving %lX to Address %lX [file %s]\n", depth, db_tgt, dir_tgt, path );
if((db_tgt&0xffff) > ((0x10000-(sizeof(len) + pathlen + sizeof(buf)-1 + 1))&0xffff)) {
if ( ( db_tgt & 0xffff ) > ( ( 0x10000 - ( sizeof( len ) + pathlen + sizeof( buf ) - 1 + 1 ) ) & 0xffff ) )
{
printf( "switch! old=%lx ", db_tgt );
db_tgt &= 0xffff0000;
db_tgt += 0x00010000;
printf( "new=%lx\n", db_tgt );
}
sram_writelong( ( db_tgt - SRAM_MENU_ADDR ) | ( ( uint32_t )type << 24 ), dir_tgt );
dir_tgt += 4;
/* save element:
@@ -218,10 +315,13 @@ uint32_t scan_dir(char* path, FILINFO* fno_param, char mkdb, uint32_t this_dir_t
/* sram_writeblock((uint8_t*)&romprops, db_tgt, sizeof(romprops)); */
entry_fsize = fno.fsize;
entry_unit_idx = 0;
while(entry_fsize > 9999) {
while ( entry_fsize > 9999 )
{
entry_fsize >>= 10;
entry_unit_idx++;
}
snprintf( buf, sizeof( buf ), "% 5ld", entry_fsize );
strncat( buf, size_units[entry_unit_idx], 1 );
sram_writeblock( buf, db_tgt, sizeof( buf ) - 1 );
@@ -230,89 +330,131 @@ uint32_t scan_dir(char* path, FILINFO* fno_param, char mkdb, uint32_t this_dir_t
// sram_writelong(fno.fsize, db_tgt + sizeof(len) + pathlen + 1);
db_tgt += sizeof( len ) + pathlen + sizeof( buf ) - 1 + 1;
break;
case TYPE_UNKNOWN:
default:
break;
}
path[len] = 0;
/* printf("%s ", path);
_delay_ms(30); */
}
} else {
}
else
{
TCHAR *fn2 = fn;
while(*fn2 != 0) {
crc += crc32_update(crc, *((unsigned char*)fn2++));
fncrc = 0;
while ( *fn2 != 0 )
{
fncrc += crc_xmodem_update( fncrc, *( ( unsigned char * )fn2++ ) );
}
crc += fncrc;
}
}
}
/* printf("%s/%s\n", path, fn);
_delay_ms(50); */
}
}
} else uart_putc(0x30+res);
else
{
uart_putc( 0x30 + res );
}
}
DBG_FS printf( "db_tgt=%lx dir_end=%lx\n", db_tgt, dir_end );
sram_writelong( db_tgt, SRAM_DB_ADDR + 4 );
sram_writelong( dir_end, SRAM_DB_ADDR + 8 );
sram_writeshort( num_files_total, SRAM_DB_ADDR + 12 );
sram_writeshort( num_dirs_total, SRAM_DB_ADDR + 14 );
if ( depth == 0 )
{
return crc;
}
else
{
return switched_dir_tgt;
}
return was_empty; // tricky!
}
SNES_FTYPE determine_filetype(char* filename) {
SNES_FTYPE determine_filetype( char *filename )
{
char *ext = strrchr( filename, '.' );
if ( ext == NULL )
{
return TYPE_UNKNOWN;
}
if ( ( !strcasecmp( ext + 1, "SMC" ) )
|| ( !strcasecmp( ext + 1, "SFC" ) )
|| ( !strcasecmp( ext + 1, "FIG" ) )
|| ( !strcasecmp( ext + 1, "BS" ) )
) {
)
{
return TYPE_SMC;
}
if( (!strcasecmp(ext+1, "IPS"))
/* if( (!strcasecmp(ext+1, "IPS"))
||(!strcasecmp(ext+1, "UPS"))
) {
return TYPE_IPS;
}
/* later
if(!strcasecmp_P(ext+1, PSTR("SRM"))) {
return TYPE_SRM;
}
if(!strcasecmp_P(ext+1, PSTR("SPC"))) {
return TYPE_SPC;
}*/
if ( !strcasecmp( ext + 1, "SPC" ) )
{
return TYPE_SPC;
}
return TYPE_UNKNOWN;
}
FRESULT get_db_id(uint32_t* id) {
FRESULT get_db_id( uint32_t *id )
{
file_open( ( uint8_t * )"/sd2snes/sd2snes.db", FA_READ );
if(file_res == FR_OK) {
if ( file_res == FR_OK )
{
file_readblock( id, 0, 4 );
/* XXX */// *id=0xdead;
file_close();
} else {
}
else
{
*id = 0xdeadbeef;
}
return file_res;
}
int get_num_dirent(uint32_t addr) {
int get_num_dirent( uint32_t addr )
{
int result = 0;
while(sram_readlong(addr+result*4)) {
while ( sram_readlong( addr + result * 4 ) )
{
result++;
}
return result;
}
void sort_all_dir(uint32_t endaddr) {
void sort_all_dir( uint32_t endaddr )
{
uint32_t entries = 0;
uint32_t current_base = SRAM_DIR_ADDR;
while(current_base<(endaddr)) {
while(sram_readlong(current_base+entries*4)) {
while ( current_base < ( endaddr ) )
{
while ( sram_readlong( current_base + entries * 4 ) )
{
entries++;
}
printf( "sorting dir @%lx, entries: %ld\n", current_base, entries );
sort_dir( current_base, entries );
current_base += 4 * entries + 4;

View File

@@ -36,8 +36,9 @@
#include "ff.h"
#define FS_MAX_DEPTH (10)
#define SYS_DIR_NAME ((const uint8_t*)"sd2snes")
typedef enum {
#define SYS_DIR_NAME ((const char*)"sd2snes")
typedef enum
{
TYPE_UNKNOWN = 0, /* 0 */
TYPE_SMC, /* 1 */
TYPE_SRM, /* 2 */

View File

@@ -52,25 +52,37 @@
#include "rle.h"
#include "cfgware.h"
void fpga_set_prog_b(uint8_t val) {
void fpga_set_prog_b( uint8_t val )
{
if ( val )
{
BITBAND( PROGBREG->FIOSET, PROGBBIT ) = 1;
}
else
{
BITBAND( PROGBREG->FIOCLR, PROGBBIT ) = 1;
}
void fpga_set_cclk(uint8_t val) {
if(val)
BITBAND(CCLKREG->FIOSET, CCLKBIT) = 1;
else
BITBAND(CCLKREG->FIOCLR, CCLKBIT) = 1;
}
int fpga_get_initb() {
void fpga_set_cclk( uint8_t val )
{
if ( val )
{
BITBAND( CCLKREG->FIOSET, CCLKBIT ) = 1;
}
else
{
BITBAND( CCLKREG->FIOCLR, CCLKBIT ) = 1;
}
}
int fpga_get_initb()
{
return BITBAND( INITBREG->FIOPIN, INITBBIT );
}
void fpga_init() {
void fpga_init()
{
/* mainly GPIO directions */
BITBAND( CCLKREG->FIODIR, CCLKBIT ) = 1; /* CCLK */
BITBAND( DONEREG->FIODIR, DONEBIT ) = 0; /* DONE */
@@ -79,119 +91,168 @@ void fpga_init() {
BITBAND( INITBREG->FIODIR, INITBBIT ) = 0; /* INIT_B */
LPC_GPIO2->FIOMASK1 = 0;
SPI_OFFLOAD = 0;
fpga_set_cclk( 0 ); /* initial clk=0 */
}
int fpga_get_done(void) {
int fpga_get_done( void )
{
return BITBAND( DONEREG->FIOPIN, DONEBIT );
}
void fpga_postinit() {
void fpga_postinit()
{
LPC_GPIO2->FIOMASK1 = 0;
}
void fpga_pgm(uint8_t* filename) {
void fpga_pgm( uint8_t *filename )
{
int MAXRETRIES = 10;
int retries = MAXRETRIES;
uint8_t data;
int i;
tick_t timeout;
do {
do
{
i = 0;
timeout = getticks() + 100;
fpga_set_prog_b( 0 );
if(BITBAND(PROGBREG->FIOPIN, PROGBBIT)) {
if ( BITBAND( PROGBREG->FIOPIN, PROGBBIT ) )
{
printf( "PROGB is stuck high!\n" );
led_panic();
}
uart_putc( 'P' );
fpga_set_prog_b( 1 );
while(!fpga_get_initb()){
if(getticks() > timeout) {
while ( !fpga_get_initb() )
{
if ( getticks() > timeout )
{
printf( "no response from FPGA trying to initiate configuration!\n" );
led_panic();
}
};
if(fpga_get_done()) {
if ( fpga_get_done() )
{
printf( "DONE is stuck high!\n" );
led_panic();
}
LPC_GPIO2->FIOMASK1 = ~( BV( 0 ) );
uart_putc( 'p' );
/* open configware file */
file_open( filename, FA_READ );
if(file_res) {
if ( file_res )
{
uart_putc( '?' );
uart_putc( 0x30 + file_res );
return;
}
uart_putc( 'C' );
for (;;) {
for ( ;; )
{
data = rle_file_getc();
i++;
if (file_status || file_res) break; /* error or eof */
if ( file_status || file_res )
{
break; /* error or eof */
}
FPGA_SEND_BYTE_SERIAL( data );
}
uart_putc( 'c' );
file_close();
printf( "fpga_pgm: %d bytes programmed\n", i );
delay_ms( 1 );
} while (!fpga_get_done() && retries--);
if(!fpga_get_done()) {
}
while ( !fpga_get_done() && retries-- );
if ( !fpga_get_done() )
{
printf( "FPGA failed to configure after %d tries.\n", MAXRETRIES );
led_panic();
}
printf( "FPGA configured\n" );
fpga_postinit();
}
void fpga_rompgm() {
void fpga_rompgm()
{
int MAXRETRIES = 10;
int retries = MAXRETRIES;
uint8_t data;
int i;
tick_t timeout;
do {
do
{
i = 0;
timeout = getticks() + 100;
fpga_set_prog_b( 0 );
uart_putc( 'P' );
fpga_set_prog_b( 1 );
while(!fpga_get_initb()){
if(getticks() > timeout) {
while ( !fpga_get_initb() )
{
if ( getticks() > timeout )
{
printf( "no response from FPGA trying to initiate configuration!\n" );
led_panic();
}
};
if(fpga_get_done()) {
if ( fpga_get_done() )
{
printf( "DONE is stuck high!\n" );
led_panic();
}
LPC_GPIO2->FIOMASK1 = ~( BV( 0 ) );
uart_putc( 'p' );
/* open configware file */
rle_mem_init( cfgware, sizeof( cfgware ) );
printf( "sizeof(cfgware) = %d\n", sizeof( cfgware ) );
for (;;) {
for ( ;; )
{
data = rle_mem_getc();
if(rle_state) break;
if ( rle_state )
{
break;
}
i++;
FPGA_SEND_BYTE_SERIAL( data );
}
uart_putc( 'c' );
printf( "fpga_pgm: %d bytes programmed\n", i );
delay_ms( 1 );
} while (!fpga_get_done() && retries--);
if(!fpga_get_done()) {
}
while ( !fpga_get_done() && retries-- );
if ( !fpga_get_done() )
{
printf( "FPGA failed to configure after %d tries.\n", MAXRETRIES );
led_panic();
}
printf( "FPGA configured\n" );
fpga_postinit();
}

View File

@@ -1,6 +1,6 @@
/* sd2snes - SD card based universal cartridge for the SNES
Copyright (C) 2009-2010 Maximilian Rehkopf <otakon@gmx.net>
AVR firmware portion
Copyright (C) 2009-2012 Maximilian Rehkopf <otakon@gmx.net>
uC firmware portion
Inspired by and based on code from sd2iec, written by Ingo Korb et al.
See sdcard.c|h, config.h.
@@ -142,147 +142,151 @@
#include "timer.h"
#include "sdnative.h"
void fpga_spi_init(void) {
spi_init(SPI_SPEED_FAST);
void fpga_spi_init( void )
{
spi_init();
BITBAND( FPGA_MCU_RDY_REG->FIODIR, FPGA_MCU_RDY_BIT ) = 0;
}
void set_msu_addr(uint16_t address) {
void set_msu_addr( uint16_t address )
{
FPGA_SELECT();
FPGA_TX_BYTE(0x02);
FPGA_TX_BYTE( FPGA_CMD_SETADDR | FPGA_TGT_MSUBUF );
FPGA_TX_BYTE( ( address >> 8 ) & 0xff );
FPGA_TX_BYTE( ( address ) & 0xff );
FPGA_DESELECT();
}
void set_dac_addr(uint16_t address) {
void set_dac_addr( uint16_t address )
{
FPGA_SELECT();
FPGA_TX_BYTE(0x01);
FPGA_TX_BYTE( FPGA_CMD_SETADDR | FPGA_TGT_DACBUF );
FPGA_TX_BYTE( ( address >> 8 ) & 0xff );
FPGA_TX_BYTE( ( address ) & 0xff );
FPGA_DESELECT();
}
void set_mcu_addr(uint32_t address) {
void set_mcu_addr( uint32_t address )
{
FPGA_SELECT();
FPGA_TX_BYTE(0x00);
FPGA_TX_BYTE( FPGA_CMD_SETADDR | FPGA_TGT_MEM );
FPGA_TX_BYTE( ( address >> 16 ) & 0xff );
FPGA_TX_BYTE( ( address >> 8 ) & 0xff );
FPGA_TX_BYTE( ( address ) & 0xff );
FPGA_DESELECT();
}
void set_saveram_mask(uint32_t mask) {
void set_saveram_mask( uint32_t mask )
{
FPGA_SELECT();
FPGA_TX_BYTE(0x20);
FPGA_TX_BYTE( FPGA_CMD_SETRAMMASK );
FPGA_TX_BYTE( ( mask >> 16 ) & 0xff );
FPGA_TX_BYTE( ( mask >> 8 ) & 0xff );
FPGA_TX_BYTE( ( mask ) & 0xff );
FPGA_DESELECT();
}
void set_rom_mask(uint32_t mask) {
void set_rom_mask( uint32_t mask )
{
FPGA_SELECT();
FPGA_TX_BYTE(0x10);
FPGA_TX_BYTE( FPGA_CMD_SETROMMASK );
FPGA_TX_BYTE( ( mask >> 16 ) & 0xff );
FPGA_TX_BYTE( ( mask >> 8 ) & 0xff );
FPGA_TX_BYTE( ( mask ) & 0xff );
FPGA_DESELECT();
}
void set_mapper(uint8_t val) {
void set_mapper( uint8_t val )
{
FPGA_SELECT();
FPGA_TX_BYTE(0x30 | (val & 0x0f));
FPGA_TX_BYTE( FPGA_CMD_SETMAPPER( val ) );
FPGA_DESELECT();
}
uint8_t fpga_test() {
uint8_t fpga_test()
{
FPGA_SELECT();
FPGA_TX_BYTE(0xF0); /* TEST */
FPGA_TX_BYTE(0x00); /* dummy */
FPGA_TX_BYTE( FPGA_CMD_TEST );
uint8_t result = FPGA_RX_BYTE();
FPGA_DESELECT();
return result;
}
uint16_t fpga_status() {
uint16_t fpga_status()
{
FPGA_SELECT();
FPGA_TX_BYTE(0xF1); /* STATUS */
FPGA_TX_BYTE(0x00); /* dummy */
FPGA_TX_BYTE( FPGA_CMD_GETSTATUS );
uint16_t result = ( FPGA_RX_BYTE() ) << 8;
result |= FPGA_RX_BYTE();
FPGA_DESELECT();
return result;
}
void fpga_set_sddma_range(uint16_t start, uint16_t end) {
void fpga_set_sddma_range( uint16_t start, uint16_t end )
{
printf( "%s %08X -> %08X\n", __func__, start, end );
FPGA_SELECT();
FPGA_TX_BYTE(0x60); /* DMA_RANGE */
FPGA_TX_BYTE( FPGA_CMD_SDDMA_RANGE );
FPGA_TX_BYTE( start >> 8 );
FPGA_TX_BYTE( start & 0xff );
FPGA_TX_BYTE( end >> 8 );
FPGA_TX_BYTE( end & 0xff );
//if(tgt==1 && (test=FPGA_RX_BYTE()) != 0x41) printf("!!!!!!!!!!!!!!! -%02x- \n", test);
FPGA_DESELECT();
}
void fpga_sddma(uint8_t tgt, uint8_t partial) {
uint32_t test = 0;
uint8_t status = 0;
void fpga_sddma( uint8_t tgt, uint8_t partial )
{
//printf("%s %02X -> %02X\n", __func__, tgt, partial);
//uint32_t test = 0;
//uint8_t status = 0;
BITBAND( SD_CLKREG->FIODIR, SD_CLKPIN ) = 0;
FPGA_SELECT();
FPGA_TX_BYTE(0x40 | (tgt & 0x3) | ((partial & 1) << 2) ); /* DO DMA */
FPGA_TX_BYTE( FPGA_CMD_SDDMA | ( tgt & 3 ) | ( partial ? FPGA_SDDMA_PARTIAL : 0 ) );
FPGA_TX_BYTE( 0x00 ); /* dummy for falling DMA_EN edge */
//if(tgt==1 && (test=FPGA_RX_BYTE()) != 0x41) printf("!!!!!!!!!!!!!!! -%02x- \n", test);
FPGA_DESELECT();
FPGA_SELECT();
FPGA_TX_BYTE(0xF1); /* STATUS */
FPGA_TX_BYTE(0x00); /* dummy */
FPGA_TX_BYTE( FPGA_CMD_GETSTATUS );
DBG_SD printf( "FPGA DMA request sent, wait for completion..." );
while((status=FPGA_RX_BYTE()) & 0x80) {
while ( FPGA_RX_BYTE() & 0x80 )
{
FPGA_RX_BYTE(); /* eat the 2nd status byte */
test++;
}
DBG_SD printf( "...complete\n" );
FPGA_DESELECT();
// if(test<5)printf("loopy: %ld %02x\n", test, status);
BITBAND( SD_CLKREG->FIODIR, SD_CLKPIN ) = 1;
}
void set_dac_vol(uint8_t volume) {
void dac_play()
{
FPGA_SELECT();
FPGA_TX_BYTE(0x50);
FPGA_TX_BYTE(volume);
FPGA_TX_BYTE(0x00); /* latch rise */
FPGA_TX_BYTE(0x00); /* latch fall */
FPGA_DESELECT();
}
void dac_play() {
FPGA_SELECT();
FPGA_TX_BYTE(0xe2);
FPGA_TX_BYTE( FPGA_CMD_DACPLAY );
FPGA_TX_BYTE( 0x00 ); /* latch reset */
FPGA_DESELECT();
}
void dac_pause() {
void dac_pause()
{
FPGA_SELECT();
FPGA_TX_BYTE(0xe1);
FPGA_TX_BYTE( FPGA_CMD_DACPAUSE );
FPGA_TX_BYTE( 0x00 ); /* latch reset */
FPGA_DESELECT();
}
void dac_reset() {
void dac_reset()
{
FPGA_SELECT();
FPGA_TX_BYTE(0xe3);
FPGA_TX_BYTE( FPGA_CMD_DACRESETPTR );
FPGA_TX_BYTE( 0x00 ); /* latch reset */
FPGA_TX_BYTE( 0x00 ); /* latch reset */
FPGA_DESELECT();
}
void msu_reset(uint16_t address) {
void msu_reset( uint16_t address )
{
FPGA_SELECT();
FPGA_TX_BYTE(0xe4);
FPGA_TX_BYTE( FPGA_CMD_MSUSETPTR );
FPGA_TX_BYTE( ( address >> 8 ) & 0xff ); /* address hi */
FPGA_TX_BYTE( address & 0xff ); /* address lo */
FPGA_TX_BYTE( 0x00 ); /* latch reset */
@@ -290,38 +294,30 @@ void msu_reset(uint16_t address) {
FPGA_DESELECT();
}
void set_msu_status(uint8_t set, uint8_t reset) {
void set_msu_status( uint8_t set, uint8_t reset )
{
FPGA_SELECT();
FPGA_TX_BYTE(0xe0);
FPGA_TX_BYTE( FPGA_CMD_MSUSETBITS );
FPGA_TX_BYTE( set );
FPGA_TX_BYTE( reset );
FPGA_TX_BYTE( 0x00 ); /* latch reset */
FPGA_DESELECT();
}
uint8_t get_msu_volume() {
uint16_t get_msu_track()
{
FPGA_SELECT();
FPGA_TX_BYTE(0xF4); /* MSU_VOLUME */
FPGA_TX_BYTE(0x00); /* dummy */
uint8_t result = FPGA_RX_BYTE();
FPGA_DESELECT();
return result;
}
uint16_t get_msu_track() {
FPGA_SELECT();
FPGA_TX_BYTE(0xF3); /* MSU_TRACK */
FPGA_TX_BYTE(0x00); /* dummy */
FPGA_TX_BYTE( FPGA_CMD_MSUGETTRACK );
uint16_t result = ( FPGA_RX_BYTE() ) << 8;
result |= FPGA_RX_BYTE();
FPGA_DESELECT();
return result;
}
uint32_t get_msu_offset() {
uint32_t get_msu_offset()
{
FPGA_SELECT();
FPGA_TX_BYTE(0xF2); /* MSU_OFFSET */
FPGA_TX_BYTE(0x00); /* dummy */
FPGA_TX_BYTE( FPGA_CMD_MSUGETADDR );
uint32_t result = ( FPGA_RX_BYTE() ) << 24;
result |= ( FPGA_RX_BYTE() ) << 16;
result |= ( FPGA_RX_BYTE() ) << 8;
@@ -330,11 +326,11 @@ uint32_t get_msu_offset() {
return result;
}
uint32_t get_snes_sysclk() {
uint32_t get_snes_sysclk()
{
FPGA_SELECT();
FPGA_TX_BYTE(0xFE); /* GET_SYSCLK */
FPGA_TX_BYTE(0x00); /* dummy */
FPGA_TX_BYTE(0x00); /* dummy */
FPGA_TX_BYTE( FPGA_CMD_GETSYSCLK );
FPGA_TX_BYTE( 0x00 ); /* dummy (copy current sysclk count to register) */
uint32_t result = ( FPGA_RX_BYTE() ) << 24;
result |= ( FPGA_RX_BYTE() ) << 16;
result |= ( FPGA_RX_BYTE() ) << 8;
@@ -343,18 +339,20 @@ uint32_t get_snes_sysclk() {
return result;
}
void set_bsx_regs(uint8_t set, uint8_t reset) {
void set_bsx_regs( uint8_t set, uint8_t reset )
{
FPGA_SELECT();
FPGA_TX_BYTE(0xe6);
FPGA_TX_BYTE( FPGA_CMD_BSXSETBITS );
FPGA_TX_BYTE( set );
FPGA_TX_BYTE( reset );
FPGA_TX_BYTE( 0x00 ); /* latch reset */
FPGA_DESELECT();
}
void set_fpga_time(uint64_t time) {
void set_fpga_time( uint64_t time )
{
FPGA_SELECT();
FPGA_TX_BYTE(0xe5);
FPGA_TX_BYTE( FPGA_CMD_RTCSET );
FPGA_TX_BYTE( ( time >> 48 ) & 0xff );
FPGA_TX_BYTE( ( time >> 40 ) & 0xff );
FPGA_TX_BYTE( ( time >> 32 ) & 0xff );
@@ -366,25 +364,28 @@ void set_fpga_time(uint64_t time) {
FPGA_DESELECT();
}
void fpga_reset_srtc_state() {
void fpga_reset_srtc_state()
{
FPGA_SELECT();
FPGA_TX_BYTE(0xe7);
FPGA_TX_BYTE( FPGA_CMD_SRTCRESET );
FPGA_TX_BYTE( 0x00 );
FPGA_TX_BYTE( 0x00 );
FPGA_DESELECT();
}
void fpga_reset_dspx_addr() {
void fpga_reset_dspx_addr()
{
FPGA_SELECT();
FPGA_TX_BYTE(0xe8);
FPGA_TX_BYTE( FPGA_CMD_DSPRESETPTR );
FPGA_TX_BYTE( 0x00 );
FPGA_TX_BYTE( 0x00 );
FPGA_DESELECT();
}
void fpga_write_dspx_pgm(uint32_t data) {
void fpga_write_dspx_pgm( uint32_t data )
{
FPGA_SELECT();
FPGA_TX_BYTE(0xe9);
FPGA_TX_BYTE( FPGA_CMD_DSPWRITEPGM );
FPGA_TX_BYTE( ( data >> 16 ) & 0xff );
FPGA_TX_BYTE( ( data >> 8 ) & 0xff );
FPGA_TX_BYTE( ( data ) & 0xff );
@@ -393,9 +394,10 @@ void fpga_write_dspx_pgm(uint32_t data) {
FPGA_DESELECT();
}
void fpga_write_dspx_dat(uint16_t data) {
void fpga_write_dspx_dat( uint16_t data )
{
FPGA_SELECT();
FPGA_TX_BYTE(0xea);
FPGA_TX_BYTE( FPGA_CMD_DSPWRITEDAT );
FPGA_TX_BYTE( ( data >> 8 ) & 0xff );
FPGA_TX_BYTE( ( data ) & 0xff );
FPGA_TX_BYTE( 0x00 );
@@ -403,25 +405,28 @@ void fpga_write_dspx_dat(uint16_t data) {
FPGA_DESELECT();
}
void fpga_dspx_reset(uint8_t reset) {
void fpga_dspx_reset( uint8_t reset )
{
FPGA_SELECT();
FPGA_TX_BYTE(reset ? 0xeb : 0xec);
FPGA_TX_BYTE( reset ? FPGA_CMD_DSPRESET : FPGA_CMD_DSPUNRESET );
FPGA_TX_BYTE( 0x00 );
FPGA_DESELECT();
}
void fpga_set_features(uint8_t feat) {
void fpga_set_features( uint8_t feat )
{
printf( "set features: %02x\n", feat );
FPGA_SELECT();
FPGA_TX_BYTE(0xed);
FPGA_TX_BYTE( FPGA_CMD_SETFEATURE );
FPGA_TX_BYTE( feat );
FPGA_DESELECT();
}
void fpga_set_213f(uint8_t data) {
void fpga_set_213f( uint8_t data )
{
printf( "set 213f: %d\n", data );
FPGA_SELECT();
FPGA_TX_BYTE(0xee);
FPGA_TX_BYTE( FPGA_CMD_SET213F );
FPGA_TX_BYTE( data );
FPGA_DESELECT();
}

View File

@@ -47,9 +47,6 @@
#define FPGA_TX_BLOCK(x,y) spi_tx_block(x,y)
#define FPGA_RX_BLOCK(x,y) spi_rx_block(x,y)
#define FPGA_SPI_FAST() spi_set_speed(SPI_SPEED_FPGA_FAST)
#define FPGA_SPI_SLOW() spi_set_speed(SPI_SPEED_FPGA_SLOW)
#define FEAT_213F (1 << 4)
#define FEAT_MSU1 (1 << 3)
#define FEAT_SRTC (1 << 2)
@@ -60,6 +57,44 @@
#define FPGA_WAIT_RDY() do {while(BITBAND(SSP_REGS->SR, SSP_BSY)); while(!BITBAND(FPGA_MCU_RDY_REG->FIOPIN, FPGA_MCU_RDY_BIT));} while (0)
/* command parameters */
#define FPGA_MEM_AUTOINC (0x8)
#define FPGA_SDDMA_PARTIAL (0x4)
#define FPGA_TGT_MEM (0x0)
#define FPGA_TGT_DACBUF (0x1)
#define FPGA_TGT_MSUBUF (0x2)
/* commands */
#define FPGA_CMD_SETADDR (0x00)
#define FPGA_CMD_SETROMMASK (0x10)
#define FPGA_CMD_SETRAMMASK (0x20)
#define FPGA_CMD_SETMAPPER(x) (0x30 | (x & 15))
#define FPGA_CMD_SDDMA (0x40)
#define FPGA_CMD_SDDMA_RANGE (0x60)
#define FPGA_CMD_READMEM (0x80)
#define FPGA_CMD_WRITEMEM (0x90)
#define FPGA_CMD_MSUSETBITS (0xe0)
#define FPGA_CMD_DACPAUSE (0xe1)
#define FPGA_CMD_DACPLAY (0xe2)
#define FPGA_CMD_DACRESETPTR (0xe3)
#define FPGA_CMD_MSUSETPTR (0xe4)
#define FPGA_CMD_RTCSET (0xe5)
#define FPGA_CMD_BSXSETBITS (0xe6)
#define FPGA_CMD_SRTCRESET (0xe7)
#define FPGA_CMD_DSPRESETPTR (0xe8)
#define FPGA_CMD_DSPWRITEPGM (0xe9)
#define FPGA_CMD_DSPWRITEDAT (0xea)
#define FPGA_CMD_DSPRESET (0xeb)
#define FPGA_CMD_DSPUNRESET (0xec)
#define FPGA_CMD_SETFEATURE (0xed)
#define FPGA_CMD_SET213F (0xee)
#define FPGA_CMD_TEST (0xf0)
#define FPGA_CMD_GETSTATUS (0xf1)
#define FPGA_CMD_MSUGETADDR (0xf2)
#define FPGA_CMD_MSUGETTRACK (0xf3)
#define FPGA_CMD_GETSYSCLK (0xfe)
#define FPGA_CMD_ECHO (0xff)
void fpga_spi_init( void );
uint8_t fpga_test( void );
uint16_t fpga_status( void );
@@ -68,7 +103,6 @@ void spi_sd(void);
void spi_none( void );
void set_mcu_addr( uint32_t );
void set_dac_addr( uint16_t );
void set_dac_vol(uint8_t);
void dac_play( void );
void dac_pause( void );
void dac_reset( void );
@@ -80,7 +114,6 @@ void set_rom_mask(uint32_t);
void set_mapper( uint8_t val );
void fpga_sddma( uint8_t tgt, uint8_t partial );
void fpga_set_sddma_range( uint16_t start, uint16_t end );
uint8_t get_msu_volume(void);
uint16_t get_msu_track( void );
uint32_t get_msu_offset( void );
uint32_t get_snes_sysclk( void );

View File

@@ -4,9 +4,12 @@
#include "sdnative.h"
#include "uart.h"
void EINT3_IRQHandler(void) {
void EINT3_IRQHandler( void )
{
NVIC_ClearPendingIRQ( EINT3_IRQn );
if(SD_CHANGE_DETECT) {
if ( SD_CHANGE_DETECT )
{
SD_CHANGE_CLR();
sdn_changed();
}

View File

@@ -22,48 +22,68 @@ int led_pwmstate = 0;
write red P1.23 PWM1[4]
*/
void rdyled(unsigned int state) {
if(led_pwmstate) {
void rdyled( unsigned int state )
{
if ( led_pwmstate )
{
rdybright( state ? 15 : 0 );
} else {
}
else
{
BITBAND( LPC_GPIO2->FIODIR, 4 ) = state;
}
led_rdyledstate = state;
}
void readled(unsigned int state) {
if(led_pwmstate) {
void readled( unsigned int state )
{
if ( led_pwmstate )
{
readbright( state ? 15 : 0 );
} else {
}
else
{
BITBAND( LPC_GPIO2->FIODIR, 5 ) = state;
}
led_readledstate = state;
}
void writeled(unsigned int state) {
if(led_pwmstate) {
void writeled( unsigned int state )
{
if ( led_pwmstate )
{
writebright( state ? 15 : 0 );
} else {
}
else
{
BITBAND( LPC_GPIO1->FIODIR, 23 ) = state;
}
led_writeledstate = state;
}
void rdybright(uint8_t bright) {
void rdybright( uint8_t bright )
{
LPC_PWM1->MR5 = led_bright[( bright & 15 )];
BITBAND( LPC_PWM1->LER, 5 ) = 1;
}
void readbright(uint8_t bright) {
void readbright( uint8_t bright )
{
LPC_PWM1->MR6 = led_bright[( bright & 15 )];
BITBAND( LPC_PWM1->LER, 6 ) = 1;
}
void writebright(uint8_t bright) {
void writebright( uint8_t bright )
{
LPC_PWM1->MR4 = led_bright[( bright & 15 )];
BITBAND( LPC_PWM1->LER, 4 ) = 1;
}
void led_clkout32(uint32_t val) {
while(1) {
void led_clkout32( uint32_t val )
{
while ( 1 )
{
rdyled( 1 );
delay_ms( 400 );
readled( ( val & BV( 31 ) ) >> 31 );
@@ -73,21 +93,27 @@ void led_clkout32(uint32_t val) {
}
}
void toggle_rdy_led() {
void toggle_rdy_led()
{
rdyled( ~led_rdyledstate );
}
void toggle_read_led() {
void toggle_read_led()
{
readled( ~led_readledstate );
}
void toggle_write_led() {
void toggle_write_led()
{
writeled( ~led_writeledstate );
}
void led_panic() {
void led_panic()
{
led_std();
while(1) {
while ( 1 )
{
rdyled( 1 );
readled( 1 );
writeled( 1 );
@@ -100,7 +126,8 @@ void led_panic() {
}
}
void led_pwm() {
void led_pwm()
{
/* Rev.C P2.4, P2.5, P1.23 */
BITBAND( LPC_PINCON->PINSEL4, 9 ) = 0;
BITBAND( LPC_PINCON->PINSEL4, 8 ) = 1;
@@ -118,7 +145,8 @@ void led_pwm() {
led_pwmstate = 1;
}
void led_std() {
void led_std()
{
BITBAND( LPC_PINCON->PINSEL4, 9 ) = 0;
BITBAND( LPC_PINCON->PINSEL4, 8 ) = 0;
@@ -135,7 +163,8 @@ void led_std() {
led_pwmstate = 0;
}
void led_init() {
void led_init()
{
/* power is already connected by default */
/* set PCLK divider to 8 */
BITBAND( LPC_SC->PCLKSEL0, 13 ) = 1;

View File

@@ -27,8 +27,8 @@ if { [info exists CPUTAPID ] } {
#delays on reset lines
#if your OpenOCD version rejects "jtag_nsrst_delay" replace it with:
#adapter_nsrst_delay 200
jtag_nsrst_delay 200
adapter_nsrst_delay 200
#jtag_nsrst_delay 200
jtag_ntrst_delay 200
# LPC2000 & LPC1700 -> SRST causes TRST
@@ -39,7 +39,8 @@ jtag newtap $_CHIPNAME cpu -irlen 4 -expected-id $_CPUTAPID
#jtag newtap x3s tap -irlen 6 -ircapture 0x11 -irmask 0x11 -expected-id 0x0141c093
set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME cortex_m3 -chain-position $_TARGETNAME -event reset-init 0
#target create $_TARGETNAME cortex_m3 -chain-position $_TARGETNAME -event reset-init 0
target create $_TARGETNAME cortex_m -chain-position $_TARGETNAME -event reset-init 0
# LPC1754 has 16kB of SRAM In the ARMv7-M "Code" area (at 0x10000000)
# and 16K more on AHB, in the ARMv7-M "SRAM" area, (at 0x2007c000).
@@ -56,7 +57,7 @@ flash bank $_FLASHNAME lpc2000 0x0 0x20000 0 0 $_TARGETNAME \
# Run with *real slow* clock by default since the
# boot rom could have been playing with the PLL, so
# we have no idea what clock the target is running at.
jtag_khz 1000
adapter_khz 1000
$_TARGETNAME configure -event reset-init {
# Do not remap 0x0000-0x0020 to anything but the flash (i.e. select

View File

@@ -48,12 +48,24 @@ extern volatile int reset_changed;
extern volatile cfg_t CFG;
enum system_states {
enum system_states
{
SYS_RTC_STATUS = 0,
SYS_LAST_STATUS = 1
};
int main(void) {
int main( void )
{
uint8_t card_go = 0;
uint32_t saved_dir_id;
uint32_t mem_dir_id;
uint32_t mem_magic;
uint8_t cmd = 0;
uint64_t btime = 0;
uint32_t filesize = 0;
uint8_t snes_reset_prev = 0, snes_reset_now = 0, snes_reset_state = 0;
uint16_t reset_count = 0;
LPC_GPIO2->FIODIR = BV( 4 ) | BV( 5 );
LPC_GPIO1->FIODIR = BV( 23 ) | BV( SNES_CIC_PAIR_BIT );
BITBAND( SNES_CIC_PAIR_REG->FIOSET, SNES_CIC_PAIR_BIT ) = 1;
@@ -68,45 +80,62 @@ int main(void) {
/* pull-down CIC data lines */
LPC_PINCON->PINMODE0 = BV( 0 ) | BV( 1 ) | BV( 2 ) | BV( 3 );
clock_disconnect();
snes_init();
snes_reset(1);
power_init();
timer_init();
uart_init();
fpga_spi_init();
spi_preinit();
led_init();
clock_disconnect(); /* Disable clock */
snes_init(); /* Set SNES Reset */
power_init(); /* Enable power block of LPC */
timer_init(); /* Enable internal timer */
uart_init(); /* Configure UART */
fpga_spi_init(); /* Configure FPGA_SPI IOs */
spi_preinit(); /* Initialise SPI IO */
led_init(); /* Initialise LEDs IO */
/* do this last because the peripheral init()s change PCLK dividers */
clock_init();
/* Output FPGA clock */
LPC_PINCON->PINSEL0 |= BV( 20 ) | BV( 21 ); /* MAT3.0 (FPGA clock) */
led_pwm();
sdn_init();
printf("\n\nsd2snes mk.2\n============\nfw ver.: " CONFIG_VERSION "\ncpu clock: %d Hz\n", CONFIG_CPU_FREQUENCY);
printf("PCONP=%lx\n", LPC_SC->PCONP);
led_pwm(); /* Enabke PWM on LED (even if not used...) */
sdn_init(); /* SD init */
/* Print banner */
printf( "\n\nsd2snes mk.2\n============\nfw ver.: " CONFIG_VERSION "\ncpu clock: %d Hz\n", CONFIG_CPU_FREQUENCY );
/* Init file manager */
file_init();
/* */
cic_init( 0 );
/* setup timer (fpga clk) */
LPC_TIM3->TCR = 2;
LPC_TIM3->CTCR = 0;
LPC_TIM3->PR = 0;
LPC_TIM3->EMR = EMC0TOGGLE;
LPC_TIM3->MCR = MR0R;
LPC_TIM3->MR0 = 1;
LPC_TIM3->TCR = 1;
fpga_init();
fpga_rompgm();
sram_writebyte( 0, SRAM_CMD_ADDR );
while(1) {
if(disk_state == DISK_CHANGED) {
sdn_init();
while ( 1 ) /* Main loop */
{
if ( disk_state == DISK_CHANGED )
{
sdn_init(); /* Reinit SD card */
newcard = 1;
}
load_bootrle( SRAM_MENU_ADDR );
set_saveram_mask(0x1fff);
set_saveram_mask( 0xffff );
set_rom_mask( 0x3fffff );
set_mapper( 0x7 );
snes_reset( 0 );
while(get_cic_state() == CIC_FAIL) {
while ( get_cic_state() == CIC_FAIL )
{
rdyled( 0 );
readled( 0 );
writeled( 0 );
@@ -116,59 +145,86 @@ printf("PCONP=%lx\n", LPC_SC->PCONP);
writeled( 1 );
delay_ms( 500 );
}
/* some sanity checks */
uint8_t card_go = 0;
while(!card_go) {
if(disk_status(0) & (STA_NOINIT|STA_NODISK)) {
/* Wait for valid card inserted */
card_go = 0;
while ( !card_go )
{
if ( disk_status( 0 ) & ( STA_NOINIT | STA_NODISK ) )
{
snes_bootprint( " No SD Card found! \0" );
while ( disk_status( 0 ) & ( STA_NOINIT | STA_NODISK ) );
delay_ms( 200 );
}
file_open( ( uint8_t * )"/sd2snes/menu.bin", FA_READ );
if(file_status != FILE_OK) {
if ( file_status != FILE_OK )
{
snes_bootprint( " /sd2snes/menu.bin not found! \0" );
while ( disk_status( 0 ) == RES_OK );
} else {
}
else
{
/* Card found ! */
card_go = 1;
}
file_close();
}
snes_bootprint( " Loading ... \0" );
if(get_cic_state() == CIC_PAIR) {
if ( get_cic_state() == CIC_PAIR )
{
printf( "PAIR MODE ENGAGED!\n" );
cic_pair( CIC_NTSC, CIC_NTSC );
}
rdyled( 1 );
readled( 0 );
writeled( 0 );
/* Load user config */
cfg_load();
cfg_save();
sram_writebyte( cfg_is_last_game_valid(), SRAM_STATUS_ADDR + SYS_LAST_STATUS );
cfg_get_last_game( file_lfn );
sram_writeblock( strrchr( ( const char * )file_lfn, '/' ) + 1, SRAM_LASTGAME_ADDR, 256 );
*fs_path = 0;
uint32_t saved_dir_id;
get_db_id( &saved_dir_id );
uint32_t mem_dir_id = sram_readlong(SRAM_DIRID);
uint32_t mem_magic = sram_readlong(SRAM_SCRATCHPAD);
mem_dir_id = sram_readlong( SRAM_DIRID );
mem_magic = sram_readlong( SRAM_SCRATCHPAD );
printf( "mem_magic=%lx mem_dir_id=%lx saved_dir_id=%lx\n", mem_magic, mem_dir_id, saved_dir_id );
if((mem_magic != 0x12345678) || (mem_dir_id != saved_dir_id) || (newcard)) {
if ( ( mem_magic != 0x12345678 ) || ( mem_dir_id != saved_dir_id ) || ( newcard ) )
{
newcard = 0;
/* generate fs footprint (interesting files only) */
uint32_t curr_dir_id = scan_dir( fs_path, NULL, 0, 0 );
printf( "curr dir id = %lx\n", curr_dir_id );
/* files changed or no database found? */
if((get_db_id(&saved_dir_id) != FR_OK)
|| saved_dir_id != curr_dir_id) {
if ( ( get_db_id( &saved_dir_id ) != FR_OK ) || saved_dir_id != curr_dir_id )
{
uint32_t endaddr, direndaddr;
/* rebuild database */
printf( "saved dir id = %lx\n", saved_dir_id );
printf( "rebuilding database..." );
snes_bootprint( " rebuilding database ... \0" );
curr_dir_id = scan_dir( fs_path, NULL, 1, 0 );
sram_writeblock( &curr_dir_id, SRAM_DB_ADDR, 4 );
uint32_t endaddr, direndaddr;
sram_readblock( &endaddr, SRAM_DB_ADDR + 4, 4 );
sram_readblock( &direndaddr, SRAM_DB_ADDR + 8, 4 );
printf( "%lx %lx\n", endaddr, direndaddr );
@@ -179,27 +235,35 @@ printf("PCONP=%lx\n", LPC_SC->PCONP);
snes_bootprint( " saving database ... \0" );
save_sram( ( uint8_t * )"/sd2snes/sd2snes.db", endaddr - SRAM_DB_ADDR, SRAM_DB_ADDR );
save_sram( ( uint8_t * )"/sd2snes/sd2snes.dir", direndaddr - ( SRAM_DIR_ADDR ), SRAM_DIR_ADDR );
fpga_pgm( ( uint8_t * )"/sd2snes/fpga_base.bit" );
printf( "done\n" );
} else {
}
else
{
printf( "saved dir id = %lx\n", saved_dir_id );
printf( "different card, consistent db, loading db...\n" );
load_sram((uint8_t*)"/sd2snes/sd2snes.db", SRAM_DB_ADDR);
load_sram((uint8_t*)"/sd2snes/sd2snes.dir", SRAM_DIR_ADDR);
fpga_pgm( ( uint8_t * )"/sd2snes/fpga_base.bit" );
load_sram_offload( ( uint8_t * )"/sd2snes/sd2snes.db", SRAM_DB_ADDR );
load_sram_offload( ( uint8_t * )"/sd2snes/sd2snes.dir", SRAM_DIR_ADDR );
}
sram_writelong( curr_dir_id, SRAM_DIRID );
sram_writelong( 0x12345678, SRAM_SCRATCHPAD );
} else {
snes_bootprint(" same card, loading db... \0");
printf("same card, loading db...\n");
load_sram((uint8_t*)"/sd2snes/sd2snes.db", SRAM_DB_ADDR);
load_sram((uint8_t*)"/sd2snes/sd2snes.dir", SRAM_DIR_ADDR);
}
else
{
snes_bootprint( " same card, loading db... \n" );
fpga_pgm( ( uint8_t * )"/sd2snes/fpga_base.bit" );
load_sram_offload( ( uint8_t * )"/sd2snes/sd2snes.db", SRAM_DB_ADDR );
load_sram_offload( ( uint8_t * )"/sd2snes/sd2snes.dir", SRAM_DIR_ADDR );
}
/* cli_loop(); */
/* load menu */
fpga_pgm((uint8_t*)"/sd2snes/fpga_base.bit");
fpga_dspx_reset( 1 );
uart_putc( '(' );
uart_putcrlf();
load_rom( ( uint8_t * )"/sd2snes/menu.bin", SRAM_MENU_ADDR, 0 );
/* force memory size + mapper */
set_rom_mask( 0x3fffff );
@@ -209,41 +273,59 @@ printf("PCONP=%lx\n", LPC_SC->PCONP);
sram_writebyte( 0, SRAM_CMD_ADDR );
if((rtc_state = rtc_isvalid()) != RTC_OK) {
snes_bootprint( " same card, loading db... \n" );
if ( ( rtc_state = rtc_isvalid() ) != RTC_OK )
{
printf( "RTC invalid!\n" );
sram_writebyte( 0xff, SRAM_STATUS_ADDR + SYS_RTC_STATUS );
set_bcdtime(0x20110401000000LL);
set_fpga_time(0x20110401000000LL);
set_bcdtime( 0x20120701000000LL );
set_fpga_time( 0x20120701000000LL );
invalidate_rtc();
} else {
}
else
{
printf( "RTC valid!\n" );
sram_writebyte( 0x00, SRAM_STATUS_ADDR + SYS_RTC_STATUS );
set_fpga_time( get_bcdtime() );
}
sram_memset( SRAM_SYSINFO_ADDR, 13 * 40, 0x20 );
printf( "SNES GO!\n" );
snes_reset( 1 );
delay_ms(1);
fpga_reset_srtc_state();
delay_ms( SNES_RESET_PULSELEN_MS );
sram_writebyte( 32, SRAM_CMD_ADDR );
snes_reset( 0 );
uint8_t cmd = 0;
uint64_t btime = 0;
uint32_t filesize=0;
sram_writebyte(32, SRAM_CMD_ADDR);
printf("test sram\n");
while(!sram_reliable()) cli_entrycheck();
printf("ok\n");
cmd = 0;
btime = 0;
filesize = 0;
printf( "test sram... " );
while ( !sram_reliable() )
{
cli_entrycheck();
}
printf( "ok\nWaiting command from menu...\n" );
//while(1) {
// delay_ms(1000);
// printf("Estimated SNES master clock: %ld Hz\n", get_snes_sysclk());
//}
//sram_hexdump(SRAM_DB_ADDR, 0x200);
//sram_hexdump(SRAM_MENU_ADDR, 0x400);
while(!cmd) {
while ( !cmd )
{
cmd = menu_main_loop();
printf( "cmd: %d\n", cmd );
uart_putc('-');
switch(cmd) {
switch ( cmd )
{
case SNES_CMD_LOADROM:
get_selected_name( file_lfn );
printf( "Selected name: %s\n", file_lfn );
@@ -251,7 +333,9 @@ printf("PCONP=%lx\n", LPC_SC->PCONP);
cfg_set_last_game_valid( 1 );
cfg_save();
filesize = load_rom( file_lfn, SRAM_ROM_ADDR, LOADROM_WITH_SRAM | LOADROM_WITH_RESET );
printf( "Filesize = %lu\n", filesize );
break;
case SNES_CMD_SETRTC:
/* get time from RAM */
btime = sram_gettime( SRAM_PARAM_ADDR );
@@ -260,72 +344,118 @@ printf("PCONP=%lx\n", LPC_SC->PCONP);
set_fpga_time( btime );
cmd = 0; /* stay in menu loop */
break;
case SNES_CMD_SYSINFO:
/* go to sysinfo loop */
sysinfo_loop();
cmd = 0; /* stay in menu loop */
break;
case SNES_CMD_LOADSPC:
/* load SPC file */
get_selected_name( file_lfn );
printf( "Selected name: %s\n", file_lfn );
filesize = load_spc( file_lfn, SRAM_SPC_DATA_ADDR, SRAM_SPC_HEADER_ADDR );
cmd = 0; /* stay in menu loop */
break;
case SNES_CMD_RESET:
/* process RESET request from SNES */
printf( "RESET requested by SNES\n" );
snes_reset_pulse();
cmd = 0; /* stay in menu loop */
break;
case SNES_CMD_LOADLAST:
cfg_get_last_game( file_lfn );
printf( "Selected name: %s\n", file_lfn );
filesize = load_rom( file_lfn, SRAM_ROM_ADDR, LOADROM_WITH_SRAM | LOADROM_WITH_RESET );
break;
default:
printf( "unknown cmd: %d\n", cmd );
cmd = 0; /* unknown cmd: stay in loop */
break;
}
}
printf( "loaded %lu bytes\n", filesize );
printf( "cmd was %x, going to snes main loop\n", cmd );
if(romprops.has_msu1 && msu1_loop()) {
if ( romprops.has_msu1 )
{
while ( !msu1_loop() );
prepare_reset();
continue;
}
cmd = 0;
uint8_t snes_reset_prev=0, snes_reset_now=0, snes_reset_state=0;
uint16_t reset_count=0;
while(fpga_test() == FPGA_TEST_TOKEN) {
snes_reset_prev = 0;
snes_reset_now = 0;
snes_reset_state = 0;
reset_count = 0;
while ( fpga_test() == FPGA_TEST_TOKEN )
{
cli_entrycheck();
sleep_ms( 250 );
sram_reliable();
printf( "%s ", get_cic_statename( get_cic_state() ) );
if(reset_changed) {
if ( reset_changed )
{
printf( "reset\n" );
reset_changed = 0;
fpga_reset_srtc_state();
}
snes_reset_now = get_snes_reset();
if(snes_reset_now) {
if(!snes_reset_prev) {
if ( snes_reset_now )
{
if ( !snes_reset_prev )
{
printf( "RESET BUTTON DOWN\n" );
snes_reset_state = 1;
reset_count = 0;
}
} else {
if(snes_reset_prev) {
}
else
{
if ( snes_reset_prev )
{
printf( "RESET BUTTON UP\n" );
snes_reset_state = 0;
}
}
if(snes_reset_state) {
if ( snes_reset_state )
{
reset_count++;
} else {
}
else
{
sram_reliable();
snes_main_loop();
}
if(reset_count>4) {
if ( reset_count > 4 )
{
reset_count = 0;
prepare_reset();
break;
}
snes_reset_prev = snes_reset_now;
}
/* fpga test fail: panic */
if(fpga_test() != FPGA_TEST_TOKEN){
if ( fpga_test() != FPGA_TEST_TOKEN )
{
led_panic();
}
/* else reset */
}
}

View File

@@ -49,16 +49,21 @@ char* hex = "0123456789ABCDEF";
extern snes_romprops_t romprops;
void sram_hexdump(uint32_t addr, uint32_t len) {
void sram_hexdump( uint32_t addr, uint32_t len )
{
static uint8_t buf[16];
uint32_t ptr;
for(ptr=0; ptr < len; ptr += 16) {
for ( ptr = 0; ptr < len; ptr += 16 )
{
sram_readblock( ( void * )buf, ptr + addr, 16 );
uart_trace(buf, 0, 16);
uart_trace( buf, 0, 16, addr );
}
}
void sram_writebyte(uint8_t val, uint32_t addr) {
void sram_writebyte( uint8_t val, uint32_t addr )
{
//printf("WriteB %8Xh @%08lXh\n", val, addr);
set_mcu_addr( addr );
FPGA_SELECT();
FPGA_TX_BYTE( 0x98 ); /* WRITE */
@@ -67,17 +72,21 @@ void sram_writebyte(uint8_t val, uint32_t addr) {
FPGA_DESELECT();
}
uint8_t sram_readbyte(uint32_t addr) {
uint8_t sram_readbyte( uint32_t addr )
{
set_mcu_addr( addr );
FPGA_SELECT();
FPGA_TX_BYTE( 0x88 ); /* READ */
FPGA_WAIT_RDY();
uint8_t val = FPGA_RX_BYTE();
FPGA_DESELECT();
//printf(" ReadB %8Xh @%08lXh\n", val, addr);
return val;
}
void sram_writeshort(uint16_t val, uint32_t addr) {
void sram_writeshort( uint16_t val, uint32_t addr )
{
//printf("WriteS %8Xh @%08lXh\n", val, addr);
set_mcu_addr( addr );
FPGA_SELECT();
FPGA_TX_BYTE( 0x98 ); /* WRITE */
@@ -88,7 +97,9 @@ void sram_writeshort(uint16_t val, uint32_t addr) {
FPGA_DESELECT();
}
void sram_writelong(uint32_t val, uint32_t addr) {
void sram_writelong( uint32_t val, uint32_t addr )
{
//printf("WriteL %8lXh @%08lXh\n", val, addr);
set_mcu_addr( addr );
FPGA_SELECT();
FPGA_TX_BYTE( 0x98 ); /* WRITE */
@@ -103,7 +114,8 @@ void sram_writelong(uint32_t val, uint32_t addr) {
FPGA_DESELECT();
}
uint16_t sram_readshort(uint32_t addr) {
uint16_t sram_readshort( uint32_t addr )
{
set_mcu_addr( addr );
FPGA_SELECT();
FPGA_TX_BYTE( 0x88 );
@@ -112,10 +124,12 @@ uint16_t sram_readshort(uint32_t addr) {
FPGA_WAIT_RDY();
val |= ( ( uint32_t )FPGA_RX_BYTE() << 8 );
FPGA_DESELECT();
//printf(" ReadS %8lXh @%08lXh\n", val, addr);
return val;
}
uint32_t sram_readlong(uint32_t addr) {
uint32_t sram_readlong( uint32_t addr )
{
set_mcu_addr( addr );
FPGA_SELECT();
FPGA_TX_BYTE( 0x88 );
@@ -128,15 +142,19 @@ uint32_t sram_readlong(uint32_t addr) {
FPGA_WAIT_RDY();
val |= ( ( uint32_t )FPGA_RX_BYTE() << 24 );
FPGA_DESELECT();
//printf(" ReadL %8lXh @%08lXh\n", val, addr);
return val;
}
void sram_readlongblock(uint32_t* buf, uint32_t addr, uint16_t count) {
void sram_readlongblock( uint32_t *buf, uint32_t addr, uint16_t count )
{
set_mcu_addr( addr );
FPGA_SELECT();
FPGA_TX_BYTE( 0x88 );
uint16_t i = 0;
while(i<count) {
while ( i < count )
{
FPGA_WAIT_RDY();
uint32_t val = ( uint32_t )FPGA_RX_BYTE() << 24;
FPGA_WAIT_RDY();
@@ -147,137 +165,226 @@ void sram_readlongblock(uint32_t* buf, uint32_t addr, uint16_t count) {
val |= FPGA_RX_BYTE();
buf[i++] = val;
}
FPGA_DESELECT();
}
void sram_readblock(void* buf, uint32_t addr, uint16_t size) {
void sram_readblock( void *buf, uint32_t addr, uint16_t size )
{
uint16_t count = size;
uint8_t *tgt = buf;
set_mcu_addr( addr );
FPGA_SELECT();
FPGA_TX_BYTE( 0x88 ); /* READ */
while(count--) {
while ( count-- )
{
FPGA_WAIT_RDY();
*( tgt++ ) = FPGA_RX_BYTE();
}
FPGA_DESELECT();
}
void sram_writeblock(void* buf, uint32_t addr, uint16_t size) {
void sram_readstrn( void *buf, uint32_t addr, uint16_t size )
{
uint16_t count = size;
uint8_t *tgt = buf;
set_mcu_addr( addr );
FPGA_SELECT();
FPGA_TX_BYTE( 0x88 ); /* READ */
while ( count-- )
{
FPGA_WAIT_RDY();
if ( !( *( tgt++ ) = FPGA_RX_BYTE() ) )
{
break;
}
}
FPGA_DESELECT();
}
void sram_writeblock( void *buf, uint32_t addr, uint16_t size )
{
//printf("WriteZ %08lX -> %08lX [%d]\n", addr, addr+size, size);
uint16_t count = size;
uint8_t *src = buf;
set_mcu_addr( addr );
FPGA_SELECT();
FPGA_TX_BYTE( 0x98 ); /* WRITE */
while(count--) {
while ( count-- )
{
FPGA_TX_BYTE( *src++ );
FPGA_WAIT_RDY();
}
FPGA_DESELECT();
}
uint32_t load_rom(uint8_t* filename, uint32_t base_addr, uint8_t flags) {
uint32_t load_rom( uint8_t *filename, uint32_t base_addr, uint8_t flags )
{
UINT bytes_read;
DWORD filesize;
DWORD filesize, read_size = 0;
UINT count = 0;
tick_t ticksstart, ticks_total = 0;
ticksstart = getticks();
printf( "%s\n", filename );
file_open( filename, FA_READ );
if(file_res) {
if ( file_res )
{
uart_putc( '?' );
uart_putc( 0x30 + file_res );
return 0;
}
filesize = file_handle.fsize;
smc_id( &romprops );
file_close();
/* reconfigure FPGA if necessary */
if(romprops.fpga_conf) {
if ( romprops.fpga_conf )
{
printf( "reconfigure FPGA with %s...\n", romprops.fpga_conf );
fpga_pgm( ( uint8_t * )romprops.fpga_conf );
}
set_mcu_addr( base_addr );
file_open( filename, FA_READ );
ff_sd_offload = 1;
sd_offload_tgt = 0;
f_lseek( &file_handle, romprops.offset );
for(;;) {
for ( ;; )
{
ff_sd_offload = 1;
sd_offload_tgt = 0;
bytes_read = file_read();
if (file_res || !bytes_read) break;
if(!(count++ % 512)) {
read_size += bytes_read;
if ( file_res || !bytes_read )
{
break;
}
if ( !( count++ % 512 ) )
{
uart_putc( '.' );
}
}
file_close();
printf( "Read %ld [%08lX] bytes...\n", read_size, read_size );
set_mapper( romprops.mapper_id );
printf( "rom header map: %02x; mapper id: %d\n", romprops.header.map, romprops.mapper_id );
ticks_total = getticks() - ticksstart;
printf( "%u ticks total\n", ticks_total );
if(romprops.mapper_id==3) {
if ( romprops.mapper_id == 3 )
{
printf( "BSX Flash cart image\n" );
printf( "attempting to load BSX BIOS /sd2snes/bsxbios.bin...\n" );
load_sram_offload( ( uint8_t * )"/sd2snes/bsxbios.bin", 0x800000 );
printf( "attempting to load BS data file /sd2snes/bsxpage.bin...\n" );
load_sram_offload( ( uint8_t * )"/sd2snes/bsxpage.bin", 0x900000 );
printf( "Type: %02x\n", romprops.header.destcode );
set_bsx_regs( 0xc0, 0x3f );
uint16_t rombase;
if(romprops.header.ramsize & 1) {
if ( romprops.header.ramsize & 1 )
{
rombase = 0xff00;
// set_bsx_regs(0x36, 0xc9);
} else {
}
else
{
rombase = 0x7f00;
// set_bsx_regs(0x34, 0xcb);
}
sram_writebyte( 0x33, rombase + 0xda );
sram_writebyte( 0x00, rombase + 0xd4 );
sram_writebyte( 0xfc, rombase + 0xd5 );
set_fpga_time( 0x0220110301180530LL );
}
if(romprops.has_dspx || romprops.has_cx4) {
if ( romprops.has_dspx || romprops.has_cx4 )
{
printf( "DSPx game. Loading firmware image %s...\n", romprops.dsp_fw );
load_dspx( romprops.dsp_fw, romprops.fpga_features );
/* fallback to DSP1B firmware if DSP1.bin is not present */
if(file_res && romprops.dsp_fw == DSPFW_1) {
if ( file_res && romprops.dsp_fw == DSPFW_1 )
{
load_dspx( DSPFW_1B, romprops.fpga_features );
}
if(file_res) {
if ( file_res )
{
snes_menu_errmsg( MENU_ERR_NODSP, ( void * )romprops.dsp_fw );
}
}
uint32_t rammask;
uint32_t rommask;
while(filesize > (romprops.romsize_bytes + romprops.offset)) {
while ( filesize > ( romprops.romsize_bytes + romprops.offset ) )
{
romprops.romsize_bytes <<= 1;
}
if(romprops.header.ramsize == 0) {
if ( romprops.header.ramsize == 0 )
{
rammask = 0;
} else {
}
else
{
rammask = romprops.ramsize_bytes - 1;
}
rommask = romprops.romsize_bytes - 1;
printf("ramsize=%x rammask=%lx\nromsize=%x rommask=%lx\n", romprops.header.ramsize, rammask, romprops.header.romsize, rommask);
if ( rommask >= SRAM_SAVE_ADDR )
{
rommask = SRAM_SAVE_ADDR - 1;
}
printf( "ramsize=%x rammask=%lx\nromsize=%x rommask=%lx\n", romprops.header.ramsize, rammask, romprops.header.romsize,
rommask );
set_saveram_mask( rammask );
set_rom_mask( rommask );
readled( 0 );
if(flags & LOADROM_WITH_SRAM) {
if(romprops.ramsize_bytes) {
if ( flags & LOADROM_WITH_SRAM )
{
if ( romprops.ramsize_bytes )
{
strcpy( strrchr( ( char * )filename, ( int )'.' ), ".srm" );
printf( "SRM file: %s\n", filename );
load_sram( filename, SRAM_SAVE_ADDR );
} else {
}
else
{
printf( "No SRAM\n" );
}
}
printf( "check MSU..." );
if(msu1_check(filename)) {
if ( msu1_check( filename ) )
{
romprops.fpga_features |= FEAT_MSU1;
romprops.has_msu1 = 1;
} else {
}
else
{
romprops.has_msu1 = 0;
}
printf( "done\n" );
romprops.fpga_features |= FEAT_SRTC;
@@ -286,80 +393,222 @@ uint32_t load_rom(uint8_t* filename, uint32_t base_addr, uint8_t flags) {
fpga_set_213f( romprops.region );
fpga_set_features( romprops.fpga_features );
if(flags & LOADROM_WITH_RESET) {
if ( flags & LOADROM_WITH_RESET )
{
fpga_dspx_reset( 1 );
snes_reset(1);
delay_ms(10);
snes_reset(0);
snes_reset_pulse();
fpga_dspx_reset( 0 );
}
return ( uint32_t )filesize;
}
uint32_t load_sram_offload(uint8_t* filename, uint32_t base_addr) {
set_mcu_addr(base_addr);
UINT bytes_read;
uint32_t load_spc( uint8_t *filename, uint32_t spc_data_addr, uint32_t spc_header_addr )
{
DWORD filesize;
file_open(filename, FA_READ);
filesize = file_handle.fsize;
if(file_res) return 0;
for(;;) {
ff_sd_offload=1;
sd_offload_tgt=0;
bytes_read = file_read();
if (file_res || !bytes_read) break;
}
file_close();
return (uint32_t)filesize;
}
UINT bytes_read;
uint8_t data;
UINT j;
uint32_t load_sram(uint8_t* filename, uint32_t base_addr) {
set_mcu_addr(base_addr);
UINT bytes_read;
DWORD filesize;
file_open(filename, FA_READ);
filesize = file_handle.fsize;
if(file_res) {
printf("load_sram: could not open %s, res=%d\n", filename, file_res);
printf( "%s\n", filename );
file_open( filename, FA_READ ); /* Open SPC file */
if ( file_res )
{
return 0;
}
for(;;) {
filesize = file_handle.fsize;
if ( filesize < 65920 ) /* At this point, we care about filesize only */
{
file_close(); /* since SNES decides if it is an SPC file */
sram_writebyte( 0, spc_header_addr ); /* If file is too small, destroy previous SPC header */
return 0;
}
set_mcu_addr( spc_data_addr );
f_lseek( &file_handle, 0x100L ); /* Load 64K data segment */
for ( ;; )
{
bytes_read = file_read();
if (file_res || !bytes_read) break;
if ( file_res || !bytes_read )
{
break;
}
FPGA_SELECT();
FPGA_TX_BYTE( 0x98 );
for(int j=0; j<bytes_read; j++) {
for ( j = 0; j < bytes_read; j++ )
{
FPGA_TX_BYTE( file_buf[j] );
FPGA_WAIT_RDY();
}
FPGA_DESELECT();
}
file_close();
file_open( filename, FA_READ ); /* Reopen SPC file to reset file_getc state*/
set_mcu_addr( spc_header_addr );
f_lseek( &file_handle, 0x0L ); /* Load 256 bytes header */
FPGA_SELECT();
FPGA_TX_BYTE( 0x98 );
for ( j = 0; j < 256; j++ )
{
data = file_getc();
FPGA_TX_BYTE( data );
FPGA_WAIT_RDY();
}
FPGA_DESELECT();
file_close();
file_open( filename, FA_READ ); /* Reopen SPC file to reset file_getc state*/
set_mcu_addr( spc_header_addr + 0x100 );
f_lseek( &file_handle, 0x10100L ); /* Load 128 DSP registers */
FPGA_SELECT();
FPGA_TX_BYTE( 0x98 );
for ( j = 0; j < 128; j++ )
{
data = file_getc();
FPGA_TX_BYTE( data );
FPGA_WAIT_RDY();
}
FPGA_DESELECT();
file_close(); /* Done ! */
/* clear echo buffer to avoid artifacts */
uint8_t esa = sram_readbyte( spc_header_addr + 0x100 + 0x6d );
uint8_t edl = sram_readbyte( spc_header_addr + 0x100 + 0x7d );
uint8_t flg = sram_readbyte( spc_header_addr + 0x100 + 0x6c );
if ( !( flg & 0x20 ) && ( edl & 0x0f ) )
{
int echo_start = esa << 8;
int echo_length = ( edl & 0x0f ) << 11;
printf( "clearing echo buffer %04x-%04x...\n", echo_start, echo_start + echo_length - 1 );
sram_memset( spc_data_addr + echo_start, echo_length, 0 );
}
return ( uint32_t )filesize;
}
uint32_t load_sram_offload( uint8_t *filename, uint32_t base_addr )
{
set_mcu_addr( base_addr );
UINT bytes_read;
DWORD filesize;
file_open( filename, FA_READ );
filesize = file_handle.fsize;
if ( file_res )
{
return 0;
}
for ( ;; )
{
ff_sd_offload = 1;
sd_offload_tgt = 0;
bytes_read = file_read();
if ( file_res || !bytes_read )
{
break;
}
}
file_close();
return ( uint32_t )filesize;
}
uint32_t load_sram_rle(uint8_t* filename, uint32_t base_addr) {
uint32_t load_sram( uint8_t *filename, uint32_t base_addr )
{
set_mcu_addr( base_addr );
UINT bytes_read;
DWORD filesize;
file_open( filename, FA_READ );
filesize = file_handle.fsize;
if ( file_res )
{
printf( "load_sram: could not open %s, res=%d\n", filename, file_res );
return 0;
}
for ( ;; )
{
bytes_read = file_read();
if ( file_res || !bytes_read )
{
break;
}
FPGA_SELECT();
FPGA_TX_BYTE( 0x98 );
for ( int j = 0; j < bytes_read; j++ )
{
FPGA_TX_BYTE( file_buf[j] );
FPGA_WAIT_RDY();
}
FPGA_DESELECT();
}
file_close();
return ( uint32_t )filesize;
}
uint32_t load_sram_rle( uint8_t *filename, uint32_t base_addr )
{
uint8_t data;
set_mcu_addr( base_addr );
DWORD filesize;
file_open( filename, FA_READ );
filesize = file_handle.fsize;
if(file_res) return 0;
if ( file_res )
{
return 0;
}
FPGA_SELECT();
FPGA_TX_BYTE( 0x98 );
for(;;) {
for ( ;; )
{
data = rle_file_getc();
if (file_res || file_status) break;
if ( file_res || file_status )
{
break;
}
FPGA_TX_BYTE( data );
FPGA_WAIT_RDY();
}
FPGA_DESELECT();
file_close();
return ( uint32_t )filesize;
}
uint32_t load_bootrle(uint32_t base_addr) {
uint32_t load_bootrle( uint32_t base_addr )
{
uint8_t data;
set_mcu_addr( base_addr );
DWORD filesize = 0;
@@ -367,47 +616,67 @@ uint32_t load_bootrle(uint32_t base_addr) {
FPGA_SELECT();
FPGA_TX_BYTE( 0x98 );
for(;;) {
for ( ;; )
{
data = rle_mem_getc();
if(rle_state) break;
if ( rle_state )
{
break;
}
FPGA_TX_BYTE( data );
FPGA_WAIT_RDY();
filesize++;
}
FPGA_DESELECT();
return ( uint32_t )filesize;
}
void save_sram(uint8_t* filename, uint32_t sram_size, uint32_t base_addr) {
void save_sram( uint8_t *filename, uint32_t sram_size, uint32_t base_addr )
{
uint32_t count = 0;
uint32_t num = 0;
//uint32_t num = 0;
FPGA_DESELECT();
file_open( filename, FA_CREATE_ALWAYS | FA_WRITE );
if(file_res) {
if ( file_res )
{
uart_putc( 0x30 + file_res );
}
while(count<sram_size) {
while ( count < sram_size )
{
set_mcu_addr( base_addr + count );
FPGA_SELECT();
FPGA_TX_BYTE( 0x88 ); /* read */
for(int j=0; j<sizeof(file_buf); j++) {
for ( int j = 0; j < sizeof( file_buf ); j++ )
{
FPGA_WAIT_RDY();
file_buf[j] = FPGA_RX_BYTE();
count++;
}
FPGA_DESELECT();
num = file_write();
if(file_res) {
/*num = */file_write();
if ( file_res )
{
uart_putc( 0x30 + file_res );
}
}
file_close();
}
uint32_t calc_sram_crc(uint32_t base_addr, uint32_t size) {
uint32_t calc_sram_crc( uint32_t base_addr, uint32_t size )
{
uint8_t data;
uint32_t count;
uint32_t crc;
@@ -416,23 +685,31 @@ uint32_t calc_sram_crc(uint32_t base_addr, uint32_t size) {
set_mcu_addr( base_addr );
FPGA_SELECT();
FPGA_TX_BYTE( 0x88 );
for(count=0; count<size; count++) {
for ( count = 0; count < size; count++ )
{
FPGA_WAIT_RDY();
data = FPGA_RX_BYTE();
if(get_snes_reset()) {
if ( get_snes_reset() )
{
crc_valid = 0;
break;
}
crc += crc32_update( crc, data );
}
FPGA_DESELECT();
return crc;
}
uint8_t sram_reliable() {
uint8_t sram_reliable()
{
uint16_t score = 0;
uint32_t val;
uint8_t result = 0;
/*while(score<SRAM_RELIABILITY_SCORE) {
if(sram_readlong(SRAM_SCRATCHPAD)==val) {
score++;
@@ -441,68 +718,90 @@ uint8_t sram_reliable() {
score=0;
}
} */
for(uint16_t i = 0; i < SRAM_RELIABILITY_SCORE; i++) {
for ( uint16_t i = 0; i < SRAM_RELIABILITY_SCORE; i++ )
{
val = sram_readlong( SRAM_SCRATCHPAD );
if(val==0x12345678) {
if ( val == 0x12345678 )
{
score++;
} else {
printf("i=%d val=%08lX\n", i, val);
} //else {
//printf("i=%d val=%08lX\n", i, val);
//}
}
}
if(score<SRAM_RELIABILITY_SCORE) {
if ( score < SRAM_RELIABILITY_SCORE )
{
result = 0;
/* dprintf("score=%d\n", score); */
} else {
}
else
{
result = 1;
}
rdyled( result );
return result;
}
void sram_memset(uint32_t base_addr, uint32_t len, uint8_t val) {
void sram_memset( uint32_t base_addr, uint32_t len, uint8_t val )
{
set_mcu_addr( base_addr );
FPGA_SELECT();
FPGA_TX_BYTE( 0x98 );
for(uint32_t i=0; i<len; i++) {
for ( uint32_t i = 0; i < len; i++ )
{
FPGA_TX_BYTE( val );
FPGA_WAIT_RDY();
}
FPGA_DESELECT();
}
uint64_t sram_gettime(uint32_t base_addr) {
uint64_t sram_gettime( uint32_t base_addr )
{
set_mcu_addr( base_addr );
FPGA_SELECT();
FPGA_TX_BYTE( 0x88 );
uint8_t data;
uint64_t result = 0LL;
/* 1st nibble is the century - 10 (binary)
4th nibble is the month (binary)
all other fields are BCD */
for(int i=0; i<12; i++) {
for ( int i = 0; i < 12; i++ )
{
FPGA_WAIT_RDY();
data = FPGA_RX_BYTE();
data &= 0xf;
switch(i) {
switch ( i )
{
case 0:
result = ( result << 4 ) | ( ( data / 10 ) + 1 );
result = ( result << 4 ) | ( data % 10 );
break;
case 3:
result = ( result << 4 ) | ( ( data / 10 ) );
result = ( result << 4 ) | ( data % 10 );
break;
default:
result = ( result << 4 ) | data;
}
}
FPGA_DESELECT();
return result & 0x00ffffffffffffffLL;
}
void load_dspx(const uint8_t *filename, uint8_t coretype) {
void load_dspx( const uint8_t *filename, uint8_t coretype )
{
UINT bytes_read;
DWORD filesize;
//DWORD filesize;
uint16_t word_cnt;
uint8_t wordsize_cnt = 0;
uint16_t sector_remaining = 0;
@@ -512,39 +811,53 @@ void load_dspx(const uint8_t *filename, uint8_t coretype) {
uint32_t pgmdata = 0;
uint16_t datdata = 0;
if(coretype & FEAT_ST0010) {
if ( coretype & FEAT_ST0010 )
{
datsize = 1536;
pgmsize = 2048;
} else if (coretype & FEAT_DSPX) {
}
else if ( coretype & FEAT_DSPX )
{
datsize = 1024;
pgmsize = 2048;
} else if (coretype & FEAT_CX4) {
}
else if ( coretype & FEAT_CX4 )
{
datsize = 0;
pgmsize = 1024; /* Cx4 data ROM */
} else {
}
else
{
printf( "load_dspx: unknown core (%02x)!\n", coretype );
}
file_open( ( uint8_t * )filename, FA_READ );
filesize = file_handle.fsize;
if(file_res) {
/*filesize = file_handle.fsize;*/
if ( file_res )
{
printf( "Could not read %s: error %d\n", filename, file_res );
return;
}
fpga_reset_dspx_addr();
for(word_cnt = 0; word_cnt < pgmsize;) {
if(!sector_remaining) {
for ( word_cnt = 0; word_cnt < pgmsize; )
{
if ( !sector_remaining )
{
bytes_read = file_read();
sector_remaining = bytes_read;
sector_cnt = 0;
}
pgmdata = ( pgmdata << 8 ) | file_buf[sector_cnt];
sector_cnt++;
wordsize_cnt++;
sector_remaining--;
if(wordsize_cnt == 3){
if ( wordsize_cnt == 3 )
{
wordsize_cnt = 0;
word_cnt++;
fpga_write_dspx_pgm( pgmdata );
@@ -552,22 +865,29 @@ void load_dspx(const uint8_t *filename, uint8_t coretype) {
}
wordsize_cnt = 0;
if(coretype & FEAT_ST0010) {
if ( coretype & FEAT_ST0010 )
{
file_seek( 0xc000 );
sector_remaining = 0;
}
for(word_cnt = 0; word_cnt < datsize;) {
if(!sector_remaining) {
for ( word_cnt = 0; word_cnt < datsize; )
{
if ( !sector_remaining )
{
bytes_read = file_read();
sector_remaining = bytes_read;
sector_cnt = 0;
}
datdata = ( datdata << 8 ) | file_buf[sector_cnt];
sector_cnt++;
wordsize_cnt++;
sector_remaining--;
if(wordsize_cnt == 2){
if ( wordsize_cnt == 2 )
{
wordsize_cnt = 0;
word_cnt++;
fpga_write_dspx_dat( datdata );

View File

@@ -30,26 +30,55 @@
#include <arm/NXP/LPC17xx/LPC17xx.h>
#include "smc.h"
#define SRAM_ROM_ADDR (0x000000L)
#define SRAM_SAVE_ADDR (0xE00000L)
#define MASK_BITS (0x000000)
#if 0
#define SRAM_ROM_ADDR ((0x000000L) & ~MASK_BITS)
#define SRAM_SAVE_ADDR ((0x400000L) & ~MASK_BITS)
#define SRAM_MENU_ADDR (0xE00000L)
#define SRAM_DB_ADDR (0xE40000L)
#define SRAM_DIR_ADDR (0xE10000L)
#define SRAM_CMD_ADDR (0xFF1000L)
#define SRAM_PARAM_ADDR (0xFF1004L)
#define SRAM_STATUS_ADDR (0xFF1100L)
#define SRAM_SYSINFO_ADDR (0xFF1200L)
#define SRAM_LASTGAME_ADDR (0xFF1420L)
#define SRAM_MENU_SAVE_ADDR (0xFF0000L)
#define SRAM_SCRATCHPAD (0xFFFF00L)
#define SRAM_DIRID (0xFFFFF0L)
#define SRAM_MENU_ADDR ((0x7A0000L) & ~MASK_BITS)
#define SRAM_DIR_ADDR ((0x410000L) & ~MASK_BITS)
#define SRAM_DB_ADDR ((0x420000L) & ~MASK_BITS)
#define SRAM_SPC_DATA_ADDR ((0x430000L) & ~MASK_BITS)
#define SRAM_SPC_HEADER_ADDR ((0x440000L) & ~MASK_BITS)
#define SRAM_MENU_SAVE_ADDR ((0x7F0000L) & ~MASK_BITS)
#define SRAM_CMD_ADDR ((0x7F1000L) & ~MASK_BITS)
#define SRAM_PARAM_ADDR ((0x7F1004L) & ~MASK_BITS)
#define SRAM_STATUS_ADDR ((0x7F1100L) & ~MASK_BITS)
#define SRAM_SYSINFO_ADDR ((0x7F1200L) & ~MASK_BITS)
#define SRAM_LASTGAME_ADDR ((0x7F1420L) & ~MASK_BITS)
#define SRAM_SCRATCHPAD ((0x7FFF00L) & ~MASK_BITS)
#define SRAM_DIRID ((0x7FFFF0L) & ~MASK_BITS)
#define SRAM_RELIABILITY_SCORE (0x100)
#else
#define SRAM_ROM_ADDR ((0x000000L) & ~MASK_BITS)
#define SRAM_SAVE_ADDR ((0x600000L) & ~MASK_BITS)
#define SRAM_MENU_ADDR ((0x500000L) & ~MASK_BITS)
#define SRAM_DIR_ADDR ((0x510000L) & ~MASK_BITS)
#define SRAM_DB_ADDR ((0x580000L) & ~MASK_BITS)
#define SRAM_SPC_DATA_ADDR ((0x7D0000L) & ~MASK_BITS)
#define SRAM_SPC_HEADER_ADDR ((0x7E0000L) & ~MASK_BITS)
#define SRAM_MENU_SAVE_ADDR ((0x7F0000L) & ~MASK_BITS)
#define SRAM_CMD_ADDR ((0x7F1000L) & ~MASK_BITS)
#define SRAM_PARAM_ADDR ((0x7F1004L) & ~MASK_BITS)
#define SRAM_STATUS_ADDR ((0x7F1100L) & ~MASK_BITS)
#define SRAM_SYSINFO_ADDR ((0x7F1200L) & ~MASK_BITS)
#define SRAM_LASTGAME_ADDR ((0x7F1420L) & ~MASK_BITS)
#define SRAM_SCRATCHPAD ((0x7FFF00L) & ~MASK_BITS)
#define SRAM_DIRID ((0x7FFFF0L) & ~MASK_BITS)
#define SRAM_RELIABILITY_SCORE (0x100)
#endif
#define LOADROM_WITH_SRAM (1)
#define LOADROM_WITH_RESET (2)
uint32_t load_rom( uint8_t *filename, uint32_t base_addr, uint8_t flags );
uint32_t load_spc( uint8_t *filename, uint32_t spc_data_addr, uint32_t spc_header_addr );
uint32_t load_sram( uint8_t *filename, uint32_t base_addr );
uint32_t load_sram_offload( uint8_t *filename, uint32_t base_addr );
uint32_t load_sram_rle( uint8_t *filename, uint32_t base_addr );
@@ -70,5 +99,5 @@ uint32_t calc_sram_crc(uint32_t base_addr, uint32_t size);
uint8_t sram_reliable( void );
void sram_memset( uint32_t base_addr, uint32_t len, uint8_t val );
uint64_t sram_gettime( uint32_t base_addr );
void sram_readstrn( void *buf, uint32_t addr, uint16_t size );
#endif

View File

@@ -13,134 +13,39 @@
#include "smc.h"
FIL msufile;
FRESULT msu_res;
DWORD msu_cltbl[CLTBL_SIZE] IN_AHBRAM;
DWORD pcm_cltbl[CLTBL_SIZE] IN_AHBRAM;
UINT msu_audio_bytes_read = 1024;
UINT msu_data_bytes_read = 1;
extern snes_romprops_t romprops;
int msu1_check_reset(void) {
static tick_t rising_ticks;
static uint8_t resbutton=0, resbutton_prev=0;
resbutton = get_snes_reset();
if(resbutton && !resbutton_prev) { /* push */
rising_ticks = getticks();
} else if(resbutton && resbutton_prev) { /* hold */
if(getticks() > rising_ticks + 99) {
return 1;
}
}
resbutton_prev = resbutton;
return 0;
}
int msu1_check(uint8_t* filename) {
/* open MSU file */
strcpy((char*)file_buf, (char*)filename);
strcpy(strrchr((char*)file_buf, (int)'.'), ".msu");
printf("MSU datafile: %s\n", file_buf);
if(f_open(&msufile, (const TCHAR*)file_buf, FA_READ) != FR_OK) {
printf("MSU datafile not found\n");
return 0;
}
msufile.cltbl = msu_cltbl;
msu_cltbl[0] = CLTBL_SIZE;
if(f_lseek(&msufile, CREATE_LINKMAP)) {
printf("Error creating FF linkmap for MSU file!\n");
}
romprops.fpga_features |= FEAT_MSU1;
return 1;
}
int msu1_loop() {
/* it is assumed that the MSU file is already opened by calling msu1_check(). */
UINT bytes_read = 1024;
UINT bytes_read2 = 1;
FRESULT res;
set_dac_vol(0x00);
while(fpga_status() & 0x4000);
uint16_t fpga_status_prev = fpga_status();
uint16_t fpga_status_now = fpga_status();
uint16_t dac_addr = 0;
uint16_t msu_addr = 0;
uint8_t msu_repeat = 0;
uint16_t msu_track = 0;
uint32_t msu_offset = 0;
uint32_t msu_loop_point = 0;
uint32_t msu_page1_start = 0x0000;
uint32_t msu_page2_start = 0x2000;
uint32_t msu_page_size = 0x2000;
uint16_t fpga_status_prev;
uint16_t fpga_status_now;
set_msu_addr(0x0);
msu_reset(0x0);
ff_sd_offload=1;
sd_offload_tgt=2;
f_lseek(&msufile, 0L);
ff_sd_offload=1;
sd_offload_tgt=2;
f_read(&msufile, file_buf, 16384, &bytes_read2);
set_dac_addr(dac_addr);
dac_pause();
dac_reset();
/* audio_start, data_start, 0, audio_ctrl[1:0], ctrl_start */
while(1){
cli_entrycheck();
fpga_status_now = fpga_status();
/* Data buffer refill */
if((fpga_status_now & 0x2000) != (fpga_status_prev & 0x2000)) {
DBG_MSU1 printf("data\n");
uint8_t pageno = 0;
if(fpga_status_now & 0x2000) {
msu_addr = 0x0;
msu_page1_start = msu_page2_start + msu_page_size;
pageno = 1;
} else {
msu_addr = 0x2000;
msu_page2_start = msu_page1_start + msu_page_size;
pageno = 2;
}
set_msu_addr(msu_addr);
sd_offload_tgt=2;
ff_sd_offload=1;
res = f_read(&msufile, file_buf, 8192, &bytes_read2);
DBG_MSU1 printf("data buffer refilled. res=%d page1=%08lx page2=%08lx\n", res, msu_page1_start, msu_page2_start);
}
/* Audio buffer refill */
if((fpga_status_now & 0x4000) != (fpga_status_prev & 0x4000)) {
if(fpga_status_now & 0x4000) {
dac_addr = 0;
} else {
dac_addr = MSU_DAC_BUFSIZE/2;
}
set_dac_addr(dac_addr);
sd_offload_tgt=1;
ff_sd_offload=1;
f_read(&file_handle, file_buf, MSU_DAC_BUFSIZE/2, &bytes_read);
}
if(fpga_status_now & 0x0020) {
char suffix[11];
/* get trackno */
msu_track = get_msu_track();
DBG_MSU1 printf("Audio requested! Track=%d\n", msu_track);
enum msu_reset_state { MSU_RESET_NONE = 0, MSU_RESET_SHORT, MSU_RESET_LONG };
void prepare_audio_track( uint16_t msu_track )
{
/* open file, fill buffer */
char suffix[11];
f_close( &file_handle );
snprintf( suffix, sizeof( suffix ), "-%d.pcm", msu_track );
strcpy( ( char * )file_buf, ( char * )file_lfn );
strcpy( strrchr( ( char * )file_buf, ( int )'.' ), suffix );
DBG_MSU1 printf( "filename: %s\n", file_buf );
f_open(&file_handle, (const TCHAR*)file_buf, FA_READ);
if ( f_open( &file_handle, ( const TCHAR * )file_buf, FA_READ ) == FR_OK )
{
file_handle.cltbl = pcm_cltbl;
pcm_cltbl[0] = CLTBL_SIZE;
f_lseek( &file_handle, CREATE_LINKMAP );
f_lseek( &file_handle, 4L );
f_read(&file_handle, &msu_loop_point, 4, &bytes_read);
f_read( &file_handle, &msu_loop_point, 4, &msu_audio_bytes_read );
DBG_MSU1 printf( "loop point: %ld samples\n", msu_loop_point );
ff_sd_offload = 1;
sd_offload_tgt = 1;
@@ -150,20 +55,27 @@ int msu1_loop() {
dac_reset();
ff_sd_offload = 1;
sd_offload_tgt = 1;
f_read(&file_handle, file_buf, MSU_DAC_BUFSIZE, &bytes_read);
f_read( &file_handle, file_buf, MSU_DAC_BUFSIZE, &msu_audio_bytes_read );
/* clear busy bit */
set_msu_status(0x00, 0x20); /* set no bits, reset bit 5 */
set_msu_status( 0x00, 0x28 ); /* set no bits, reset audio_busy + audio_error */
}
else
{
f_close( &file_handle );
set_msu_status( 0x08, 0x20 ); /* reset audio_busy, set audio_error */
}
}
if(fpga_status_now & 0x0010) {
/* get address */
msu_offset=get_msu_offset();
DBG_MSU1 printf("Data requested! Offset=%08lx page1=%08lx page2=%08lx\n", msu_offset, msu_page1_start, msu_page2_start);
void prepare_data( uint32_t msu_offset )
{
DBG_MSU1 printf( "Data requested! Offset=%08lx page1=%08lx page2=%08lx\n", msu_offset, msu_page1_start,
msu_page2_start );
if ( ( ( msu_offset < msu_page1_start )
|| ( msu_offset >= msu_page1_start + msu_page_size ) )
&& ( ( msu_offset < msu_page2_start )
|| (msu_offset >= msu_page2_start + msu_page_size))) {
|| ( msu_offset >= msu_page2_start + msu_page_size ) ) )
{
DBG_MSU1 printf( "offset %08lx out of range (%08lx-%08lx, %08lx-%08lx), reload\n", msu_offset, msu_page1_start,
msu_page1_start + msu_page_size - 1, msu_page2_start, msu_page2_start + msu_page_size - 1 );
/* "cache miss" */
@@ -171,44 +83,57 @@ int msu1_loop() {
set_msu_addr( 0x0 );
sd_offload_tgt = 2;
ff_sd_offload = 1;
res = f_lseek(&msufile, msu_offset);
DBG_MSU1 printf("seek to %08lx, res = %d\n", msu_offset, res);
msu_res = f_lseek( &msufile, msu_offset );
DBG_MSU1 printf( "seek to %08lx, res = %d\n", msu_offset, msu_res );
sd_offload_tgt = 2;
ff_sd_offload = 1;
res = f_read(&msufile, file_buf, 16384, &bytes_read2);
DBG_MSU1 printf("read res = %d\n", res);
DBG_MSU1 printf("read %d bytes\n", bytes_read2);
msu_res = f_read( &msufile, file_buf, 16384, &msu_data_bytes_read );
DBG_MSU1 printf( "read res = %d\n", msu_res );
DBG_MSU1 printf( "read %d bytes\n", msu_data_bytes_read );
msu_reset( 0x0 );
msu_page1_start = msu_offset;
msu_page2_start = msu_offset + msu_page_size;
} else {
if (msu_offset >= msu_page1_start && msu_offset <= msu_page1_start + msu_page_size) {
}
else
{
if ( msu_offset >= msu_page1_start && msu_offset <= msu_page1_start + msu_page_size )
{
msu_reset( 0x0000 + msu_offset - msu_page1_start );
DBG_MSU1 printf( "inside page1, new offset: %08lx\n", 0x0000 + msu_offset - msu_page1_start );
if(!(msu_page2_start == msu_page1_start + msu_page_size)) {
if ( !( msu_page2_start == msu_page1_start + msu_page_size ) )
{
set_msu_addr( 0x2000 );
sd_offload_tgt = 2;
ff_sd_offload = 1;
f_read(&msufile, file_buf, 8192, &bytes_read2);
f_read( &msufile, file_buf, 8192, &msu_data_bytes_read );
DBG_MSU1 printf( "next page dirty (was: %08lx), loaded page2 (start now: ", msu_page2_start );
msu_page2_start = msu_page1_start + msu_page_size;
DBG_MSU1 printf( "%08lx)\n", msu_page2_start );
}
} else if (msu_offset >= msu_page2_start && msu_offset <= msu_page2_start + msu_page_size) {
}
else if ( msu_offset >= msu_page2_start && msu_offset <= msu_page2_start + msu_page_size )
{
DBG_MSU1 printf( "inside page2, new offset: %08lx\n", 0x2000 + msu_offset - msu_page2_start );
msu_reset( 0x2000 + msu_offset - msu_page2_start );
if(!(msu_page1_start == msu_page2_start + msu_page_size)) {
if ( !( msu_page1_start == msu_page2_start + msu_page_size ) )
{
set_msu_addr( 0x0 );
sd_offload_tgt = 2;
ff_sd_offload = 1;
f_read(&msufile, file_buf, 8192, &bytes_read2);
f_read( &msufile, file_buf, 8192, &msu_data_bytes_read );
DBG_MSU1 printf( "next page dirty (was: %08lx), loaded page1 (start now: ", msu_page1_start );
msu_page1_start = msu_page2_start + msu_page_size;
DBG_MSU1 printf( "%08lx)\n", msu_page1_start );
}
} else printf("!!!WATWATWAT!!!\n");
}
else
{
printf( "!!!WATWATWAT!!!\n" );
}
}
/* clear bank bit to mask bank reset artifact */
fpga_status_now &= ~0x2000;
fpga_status_prev &= ~0x2000;
@@ -216,22 +141,191 @@ int msu1_loop() {
set_msu_status( 0x00, 0x10 );
}
if(fpga_status_now & 0x0001) {
if(fpga_status_now & 0x0004) {
int msu1_check_reset( void )
{
static tick_t rising_ticks;
static uint8_t resbutton = 0, resbutton_prev = 0;
int result = MSU_RESET_NONE;
resbutton = get_snes_reset();
if ( resbutton && !resbutton_prev ) /* push */
{
rising_ticks = getticks();
}
else if ( resbutton && resbutton_prev ) /* hold */
{
if ( getticks() > rising_ticks + 99 )
{
result = MSU_RESET_LONG;
}
}
else if ( !resbutton && resbutton_prev ) /* release */
{
if ( getticks() < rising_ticks + 99 )
{
result = MSU_RESET_SHORT;
}
}
else
{
result = MSU_RESET_NONE;
}
resbutton_prev = resbutton;
return result;
}
int msu1_check( uint8_t *filename )
{
/* open MSU file */
strcpy( ( char * )file_buf, ( char * )filename );
strcpy( strrchr( ( char * )file_buf, ( int )'.' ), ".msu" );
printf( "MSU datafile: %s\n", file_buf );
if ( f_open( &msufile, ( const TCHAR * )file_buf, FA_READ ) != FR_OK )
{
printf( "MSU datafile not found\n" );
return 0;
}
msufile.cltbl = msu_cltbl;
msu_cltbl[0] = CLTBL_SIZE;
if ( f_lseek( &msufile, CREATE_LINKMAP ) )
{
printf( "Error creating FF linkmap for MSU file!\n" );
}
romprops.fpga_features |= FEAT_MSU1;
return 1;
}
int msu1_loop()
{
/* it is assumed that the MSU file is already opened by calling msu1_check(). */
while ( fpga_status() & 0x4000 );
uint16_t dac_addr = 0;
uint16_t msu_addr = 0;
uint8_t msu_repeat = 0;
uint16_t msu_track = 0;
uint32_t msu_offset = 0;
fpga_status_prev = fpga_status();
fpga_status_now = fpga_status();
int msu_res;
/* set_msu_addr(0x0);
msu_reset(0x0);
ff_sd_offload=1;
sd_offload_tgt=2;
f_lseek(&msufile, 0L);
ff_sd_offload=1;
sd_offload_tgt=2;
f_read(&msufile, file_buf, 16384, &msu_data_bytes_read);
*/
set_dac_addr( dac_addr );
dac_pause();
dac_reset();
set_msu_addr( 0x0 );
msu_reset( 0x0 );
ff_sd_offload = 1;
sd_offload_tgt = 2;
f_lseek( &msufile, 0L );
ff_sd_offload = 1;
sd_offload_tgt = 2;
f_read( &msufile, file_buf, 16384, &msu_data_bytes_read );
prepare_audio_track( 0 );
prepare_data( 0 );
/* audio_start, data_start, 0, audio_ctrl[1:0], ctrl_start */
while ( ( msu_res = msu1_check_reset() ) == MSU_RESET_NONE )
{
cli_entrycheck();
fpga_status_now = fpga_status();
/* Data buffer refill */
if ( ( fpga_status_now & 0x2000 ) != ( fpga_status_prev & 0x2000 ) )
{
DBG_MSU1 printf( "data\n" );
if ( fpga_status_now & 0x2000 )
{
msu_addr = 0x0;
msu_page1_start = msu_page2_start + msu_page_size;
}
else
{
msu_addr = 0x2000;
msu_page2_start = msu_page1_start + msu_page_size;
}
set_msu_addr( msu_addr );
sd_offload_tgt = 2;
ff_sd_offload = 1;
msu_res = f_read( &msufile, file_buf, 8192, &msu_data_bytes_read );
DBG_MSU1 printf( "data buffer refilled. res=%d page1=%08lx page2=%08lx\n", msu_res, msu_page1_start, msu_page2_start );
}
/* Audio buffer refill */
if ( ( fpga_status_now & 0x4000 ) != ( fpga_status_prev & 0x4000 ) )
{
if ( fpga_status_now & 0x4000 )
{
dac_addr = 0;
}
else
{
dac_addr = MSU_DAC_BUFSIZE / 2;
}
set_dac_addr( dac_addr );
sd_offload_tgt = 1;
ff_sd_offload = 1;
f_read( &file_handle, file_buf, MSU_DAC_BUFSIZE / 2, &msu_audio_bytes_read );
}
if ( fpga_status_now & 0x0020 )
{
/* get trackno */
msu_track = get_msu_track();
DBG_MSU1 printf( "Audio requested! Track=%d\n", msu_track );
prepare_audio_track( msu_track );
}
if ( fpga_status_now & 0x0010 )
{
/* get address */
msu_offset = get_msu_offset();
prepare_data( msu_offset );
}
if ( fpga_status_now & 0x0001 )
{
if ( fpga_status_now & 0x0004 )
{
msu_repeat = 1;
set_msu_status( 0x04, 0x01 ); /* set bit 2, reset bit 0 */
DBG_MSU1 printf( "Repeat set!\n" );
} else {
}
else
{
msu_repeat = 0;
set_msu_status( 0x00, 0x05 ); /* set no bits, reset bit 0+2 */
DBG_MSU1 printf( "Repeat clear!\n" );
}
if(fpga_status_now & 0x0002) {
if ( fpga_status_now & 0x0002 )
{
DBG_MSU1 printf( "PLAY!\n" );
set_msu_status( 0x02, 0x01 ); /* set bit 0, reset bit 1 */
dac_play();
} else {
}
else
{
DBG_MSU1 printf( "PAUSE!\n" );
set_msu_status( 0x00, 0x03 ); /* set no bits, reset bit 1+0 */
dac_pause();
@@ -241,28 +335,42 @@ int msu1_loop() {
fpga_status_prev = fpga_status_now;
/* handle loop / end */
if(bytes_read < MSU_DAC_BUFSIZE / 2) {
if ( msu_audio_bytes_read < MSU_DAC_BUFSIZE / 2 )
{
ff_sd_offload = 0;
sd_offload = 0;
if(msu_repeat) {
if ( msu_repeat )
{
DBG_MSU1 printf( "loop\n" );
ff_sd_offload = 1;
sd_offload_tgt = 1;
f_lseek( &file_handle, 8L + msu_loop_point * 4 );
ff_sd_offload = 1;
sd_offload_tgt = 1;
f_read(&file_handle, file_buf, (MSU_DAC_BUFSIZE / 2) - bytes_read, &bytes_read);
} else {
f_read( &file_handle, file_buf, ( MSU_DAC_BUFSIZE / 2 ) - msu_audio_bytes_read, &msu_audio_bytes_read );
}
else
{
set_msu_status( 0x00, 0x02 ); /* clear play bit */
dac_pause();
}
bytes_read = MSU_DAC_BUFSIZE;
msu_audio_bytes_read = MSU_DAC_BUFSIZE;
}
if(msu1_check_reset()) {
f_close(&msufile);
}
f_close( &file_handle );
DBG_MSU1 printf( "Reset " );
if ( msu_res == MSU_RESET_LONG )
{
f_close( &msufile );
DBG_MSU1 printf( "to menu\n" );
return 1;
}
}
DBG_MSU1 printf( "game\n" );
return 0;
}
/* END OF MSU1 STUFF */

View File

@@ -4,9 +4,16 @@
# http://www.hs-augsburg.de/~hhoegl/proj/usbjtag/usbjtag.html
#
interface ft2232
ft2232_vid_pid 0x0403 0x6010
ft2232_device_desc "Dual RS232"
ft2232_layout "oocdlink"
ft2232_latency 2
#interface ft2232
interface ftdi
#ft2232_vid_pid 0x15ba 0x0003
#ft2232_device_desc "Olimex OpenOCD JTAG"
#ft2232_layout "olimex-jtag"
#interface ft2232
#ft2232_vid_pid 0x0403 0x6010
#ft2232_device_desc "Dual RS232"
#ft2232_layout "oocdlink"
#ft2232_latency 2
#adapter_khz 10

View File

@@ -15,12 +15,12 @@
* USB [enabled via usb_init]
* PWM1
*/
void power_init() {
void power_init()
{
LPC_SC->PCONP = BV( PCSSP0 )
| BV( PCTIM3 )
| BV( PCRTC )
| BV( PCGPIO )
| BV( PCPWM1 )
// | BV(PCUSB)
;
| BV( PCUSB );
}

View File

@@ -61,8 +61,10 @@ static char *outptr;
static int maxlen;
/* printf */
static void outchar(char x) {
if (maxlen) {
static void outchar( char x )
{
if ( maxlen )
{
maxlen--;
outfunc( x );
outlength++;
@@ -70,15 +72,18 @@ static void outchar(char x) {
}
/* sprintf */
static void outstr(char x) {
if (maxlen) {
static void outstr( char x )
{
if ( maxlen )
{
maxlen--;
*outptr++ = x;
outlength++;
}
}
static int internal_nprintf(void (*output_function)(char c), const char *fmt, va_list ap) {
static int internal_nprintf( void ( *output_function )( char c ), const char *fmt, va_list ap )
{
unsigned int width;
unsigned int flags;
unsigned int base = 0;
@@ -86,16 +91,24 @@ static int internal_nprintf(void (*output_function)(char c), const char *fmt, va
outlength = 0;
while (*fmt) {
while (1) {
while ( *fmt )
{
while ( 1 )
{
if ( *fmt == 0 )
{
goto end;
}
if (*fmt == '%') {
if ( *fmt == '%' )
{
fmt++;
if ( *fmt != '%' )
{
break;
}
}
output_function( *fmt++ );
}
@@ -104,9 +117,12 @@ static int internal_nprintf(void (*output_function)(char c), const char *fmt, va
width = 0;
/* read all flags */
do {
if (flags < FLAG_WIDTH) {
switch (*fmt) {
do
{
if ( flags < FLAG_WIDTH )
{
switch ( *fmt )
{
case '0':
flags |= FLAG_ZEROPAD;
continue;
@@ -125,8 +141,10 @@ static int internal_nprintf(void (*output_function)(char c), const char *fmt, va
}
}
if (flags < FLAG_LONG) {
if (*fmt >= '0' && *fmt <= '9') {
if ( flags < FLAG_LONG )
{
if ( *fmt >= '0' && *fmt <= '9' )
{
unsigned char tmp = *fmt - '0';
width = 10 * width + tmp;
flags |= FLAG_WIDTH;
@@ -134,20 +152,26 @@ static int internal_nprintf(void (*output_function)(char c), const char *fmt, va
}
if ( *fmt == 'h' )
{
continue;
}
if (*fmt == 'l') {
if ( *fmt == 'l' )
{
flags |= FLAG_LONG;
continue;
}
}
break;
} while (*fmt++);
}
while ( *fmt++ );
/* Strings */
if (*fmt == 'c' || *fmt == 's') {
switch (*fmt) {
if ( *fmt == 'c' || *fmt == 's' )
{
switch ( *fmt )
{
case 'c':
buffer[0] = va_arg( ap, int );
ptr = buffer;
@@ -162,9 +186,11 @@ static int internal_nprintf(void (*output_function)(char c), const char *fmt, va
}
/* Numbers */
switch (*fmt) {
switch ( *fmt )
{
case 'u':
flags |= FLAG_UNSIGNED;
case 'd':
base = 10;
break;
@@ -178,6 +204,7 @@ static int internal_nprintf(void (*output_function)(char c), const char *fmt, va
output_function( '0' );
output_function( 'x' );
width -= 2;
case 'x':
case 'X':
base = 16;
@@ -187,59 +214,89 @@ static int internal_nprintf(void (*output_function)(char c), const char *fmt, va
unsigned int num;
if (!(flags & FLAG_UNSIGNED)) {
if ( !( flags & FLAG_UNSIGNED ) )
{
int tmp = va_arg( ap, int );
if (tmp < 0) {
if ( tmp < 0 )
{
num = -tmp;
flags |= FLAG_NEGATIVE;
} else
}
else
{
num = tmp;
} else {
}
}
else
{
num = va_arg( ap, unsigned int );
}
/* Convert number into buffer */
ptr = buffer + sizeof( buffer );
*--ptr = 0;
do {
do
{
*--ptr = hexdigits[num % base];
num /= base;
} while (num != 0);
}
while ( num != 0 );
/* Sign */
if (flags & FLAG_NEGATIVE) {
if ( flags & FLAG_NEGATIVE )
{
output_function( '-' );
width--;
} else if (flags & FLAG_FORCESIGN) {
}
else if ( flags & FLAG_FORCESIGN )
{
output_function( '+' );
width--;
} else if (flags & FLAG_BLANK) {
}
else if ( flags & FLAG_BLANK )
{
output_function( ' ' );
width--;
}
output:
/* left padding */
if ((flags & FLAG_WIDTH) && !(flags & FLAG_LEFTADJ)) {
while (strlen(ptr) < width) {
if ( ( flags & FLAG_WIDTH ) && !( flags & FLAG_LEFTADJ ) )
{
while ( strlen( ptr ) < width )
{
if ( flags & FLAG_ZEROPAD )
{
output_function( '0' );
}
else
{
output_function( ' ' );
}
width--;
}
}
/* data */
while (*ptr) {
while ( *ptr )
{
output_function( *ptr++ );
if ( width )
{
width--;
}
}
/* right padding */
if (flags & FLAG_WIDTH) {
while (width) {
if ( flags & FLAG_WIDTH )
{
while ( width )
{
output_function( ' ' );
width--;
}
@@ -252,7 +309,8 @@ static int internal_nprintf(void (*output_function)(char c), const char *fmt, va
return outlength;
}
int printf(const char *format, ...) {
int printf( const char *format, ... )
{
va_list ap;
int res;
@@ -263,7 +321,8 @@ int printf(const char *format, ...) {
return res;
}
int snprintf(char *str, size_t size, const char *format, ...) {
int snprintf( char *str, size_t size, const char *format, ... )
{
va_list ap;
int res;
@@ -272,20 +331,26 @@ int snprintf(char *str, size_t size, const char *format, ...) {
va_start( ap, format );
res = internal_nprintf( outstr, format, ap );
va_end( ap );
if ( res < size )
{
str[res] = 0;
}
return res;
}
/* Required for gcc compatibility */
int puts(const char *str) {
int puts( const char *str )
{
uart_puts( str );
uart_putc( '\n' );
return 0;
}
#undef putchar
int putchar(int c) {
int putchar( int c )
{
uart_putc( c );
return 0;
}

View File

@@ -2,65 +2,92 @@
#include "rle.h"
#include "fileops.h"
uint8_t rle_file_getc() {
uint8_t rle_file_getc()
{
static uint16_t rle_filled = 0;
static uint8_t data;
if(!rle_filled) {
if ( !rle_filled )
{
data = file_getc();
switch(data) {
switch ( data )
{
case RLE_RUN:
data = file_getc();
rle_filled = file_getc() - 1;
break;
case RLE_RUNLONG:
data = file_getc();
rle_filled = file_getc();
rle_filled |= file_getc() << 8;
rle_filled--;
break;
case RLE_ESC:
data = file_getc();
break;
}
} else {
}
else
{
rle_filled--;
}
if(file_status || file_res) rle_filled = 0;
if ( file_status || file_res )
{
rle_filled = 0;
}
return data;
}
void rle_mem_init(const uint8_t* address, uint32_t len) {
void rle_mem_init( const uint8_t *address, uint32_t len )
{
rle_mem_ptr = address;
rle_mem_endptr = address + len;
rle_state = 0;
}
uint8_t rle_mem_getc() {
uint8_t rle_mem_getc()
{
static uint16_t rle_mem_filled = 0;
static uint8_t rle_mem_data;
if(!rle_mem_filled) {
if ( !rle_mem_filled )
{
rle_mem_data = *( rle_mem_ptr++ );
switch(rle_mem_data) {
switch ( rle_mem_data )
{
case RLE_RUN:
rle_mem_data = *( rle_mem_ptr )++;
rle_mem_filled = *( rle_mem_ptr )++ - 1;
break;
case RLE_RUNLONG:
rle_mem_data = *( rle_mem_ptr )++;
rle_mem_filled = *( rle_mem_ptr )++;
rle_mem_filled |= *( rle_mem_ptr )++ << 8;
rle_mem_filled--;
break;
case RLE_ESC:
rle_mem_data = *( rle_mem_ptr )++;
break;
}
} else {
}
else
{
rle_mem_filled--;
}
if(rle_mem_ptr>=rle_mem_endptr){
if ( rle_mem_ptr >= rle_mem_endptr )
{
rle_mem_filled = 0;
rle_state = 1;
}
return rle_mem_data;
}

View File

@@ -11,23 +11,32 @@ rtcstate_t rtc_state;
#define CLKEN 0
#define CTCRST 1
uint8_t rtc_isvalid(void) {
if(LPC_RTC->GPREG0 == RTC_MAGIC) {
uint8_t rtc_isvalid( void )
{
if ( LPC_RTC->GPREG0 == RTC_MAGIC )
{
return RTC_OK;
}
return RTC_INVALID;
}
void rtc_init(void) {
if (LPC_RTC->CCR & BV(CLKEN)) {
void rtc_init( void )
{
if ( LPC_RTC->CCR & BV( CLKEN ) )
{
rtc_state = RTC_OK;
} else {
}
else
{
rtc_state = RTC_INVALID;
}
}
void read_rtc(struct tm *time) {
do {
void read_rtc( struct tm *time )
{
do
{
time->tm_sec = LPC_RTC->SEC;
time->tm_min = LPC_RTC->MIN;
time->tm_hour = LPC_RTC->HOUR;
@@ -35,24 +44,33 @@ void read_rtc(struct tm *time) {
time->tm_mon = LPC_RTC->MONTH;
time->tm_year = LPC_RTC->YEAR;
time->tm_wday = LPC_RTC->DOW;
} while (time->tm_sec != LPC_RTC->SEC);
}
while ( time->tm_sec != LPC_RTC->SEC );
}
uint8_t calc_weekday(struct tm *time) {
uint8_t calc_weekday( struct tm *time )
{
int month = time->tm_mon;
int year = time->tm_year;
int day = time->tm_mday;
/* Variation of Sillke for the Gregorian calendar.
* http://www.mathematik.uni-bielefeld.de/~sillke/ALGORITHMS/calendar/weekday.c */
if (month <= 2) {
if ( month <= 2 )
{
month += 10;
year--;
} else month -= 2;
}
else
{
month -= 2;
}
return ( 83 * month / 32 + day + year + year / 4 - year / 100 + year / 400 ) % 7;
}
void set_rtc(struct tm *time) {
void set_rtc( struct tm *time )
{
LPC_RTC->CCR = BV( CTCRST );
LPC_RTC->SEC = time->tm_sec;
LPC_RTC->MIN = time->tm_min;
@@ -65,11 +83,13 @@ void set_rtc(struct tm *time) {
LPC_RTC->GPREG0 = RTC_MAGIC;
}
void invalidate_rtc() {
void invalidate_rtc()
{
LPC_RTC->GPREG0 = 0;
}
uint32_t get_fattime(void) {
uint32_t get_fattime( void )
{
struct tm time;
read_rtc( &time );
@@ -81,7 +101,8 @@ uint32_t get_fattime(void) {
( ( uint32_t )time.tm_sec ) >> 1;
}
uint64_t get_bcdtime(void) {
uint64_t get_bcdtime( void )
{
struct tm time;
read_rtc( &time );
uint16_t year = time.tm_year;
@@ -103,7 +124,8 @@ uint64_t get_bcdtime(void) {
| ( time.tm_sec % 10 );
}
void set_bcdtime(uint64_t btime) {
void set_bcdtime( uint64_t btime )
{
struct tm time;
time.tm_sec = ( btime & 0xf ) + ( ( btime >> 4 ) & 0xf ) * 10;
time.tm_min = ( ( btime >> 8 ) & 0xf ) + ( ( btime >> 12 ) & 0xf ) * 10;
@@ -116,12 +138,14 @@ void set_bcdtime(uint64_t btime) {
set_rtc( &time );
}
void printtime(struct tm *time) {
void printtime( struct tm *time )
{
printf( "%04d-%02d-%02d %02d:%02d:%02d\n", time->tm_year, time->tm_mon,
time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec );
}
void testbattery() {
void testbattery()
{
printf( "%lx\n", LPC_RTC->GPREG0 );
LPC_RTC->GPREG0 = RTC_MAGIC;
printf( "%lx\n", LPC_RTC->GPREG0 );

View File

@@ -29,13 +29,15 @@
#include <stdint.h>
typedef enum {
typedef enum
{
RTC_NOT_FOUND, /* No RTC present */
RTC_INVALID, /* RTC present, but contents invalid */
RTC_OK /* RTC present and working */
} rtcstate_t;
struct tm {
struct tm
{
uint8_t tm_sec; // 0..59
uint8_t tm_min; // 0..59
uint8_t tm_hour; // 0..23

View File

@@ -1,46 +0,0 @@
/* sd2iec - SD/MMC to Commodore serial bus interface/controller
Copyright (C) 2007-2010 Ingo Korb <ingo@akana.de>
Inspiration and low-level SD/MMC access based on code from MMC2IEC
by Lars Pontoppidan et al., see sdcard.c|h and config.h.
FAT filesystem access based on code from ChaN and Jim Brain, see ff.c|h.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License only.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
sdcard.h: Definitions for the SD/MMC access routines
*/
#ifndef SDCARD_H
#define SDCARD_H
#include "diskio.h"
#define SD_TX_BYTE(x) spi_tx_byte(x, SPI_SD);
#define SD_RX_BYTE(x) spi_rx_byte(x, SPI_SD);
#define SD_TX_BLOCK(x,y) spi_tx_block(x,y, SPI_SD);
#define SD_RX_BLOCK(x,y) spi_rx_block(x,y, SPI_SD);
/* These functions are weak-aliased to disk_... */
void sd_init(void);
DSTATUS sd_status(BYTE drv);
DSTATUS sd_initialize(BYTE drv);
DRESULT sd_read(BYTE drv, BYTE *buffer, DWORD sector, BYTE count);
DRESULT sd_write(BYTE drv, const BYTE *buffer, DWORD sector, BYTE count);
DRESULT sd_getinfo(BYTE drv, BYTE page, void *buffer);
void sd_changed(void);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -22,6 +22,7 @@ DSTATUS sdn_initialize(BYTE drv);
DRESULT sdn_read( BYTE drv, BYTE *buffer, DWORD sector, BYTE count );
DRESULT sdn_write( BYTE drv, const BYTE *buffer, DWORD sector, BYTE count );
DRESULT sdn_getinfo( BYTE drv, BYTE page, void *buffer );
DRESULT sdn_ioctl( BYTE drv, BYTE cmd, void *buffer );
void sdn_changed( void );
uint8_t *sdn_getcid( void );

232
src/smc.c
View File

@@ -35,27 +35,39 @@ snes_romprops_t romprops;
uint32_t hdr_addr[6] = {0xffb0, 0x101b0, 0x7fb0, 0x81b0, 0x40ffb0, 0x4101b0};
uint8_t isFixed(uint8_t* data, int size, uint8_t value) {
uint8_t isFixed( uint8_t *data, int size, uint8_t value )
{
uint8_t res = 1;
do {
do
{
size--;
if(data[size] != value) {
if ( data[size] != value )
{
res = 0;
}
} while (size);
}
while ( size );
return res;
}
uint8_t checkChksum(uint16_t cchk, uint16_t chk) {
uint8_t checkChksum( uint16_t cchk, uint16_t chk )
{
uint32_t sum = cchk + chk;
uint8_t res = 0;
if(sum==0x0000ffff) {
if ( sum == 0x0000ffff )
{
res = 1;
}
return res;
}
void smc_id(snes_romprops_t* props) {
void smc_id( snes_romprops_t *props )
{
uint8_t score, maxscore = 1, score_idx = 2; /* assume LoROM */
snes_header_t *header = &( props->header );
@@ -64,17 +76,25 @@ void smc_id(snes_romprops_t* props) {
props->has_cx4 = 0;
props->fpga_features = 0;
props->fpga_conf = NULL;
for(uint8_t num = 0; num < 6; num++) {
for ( uint8_t num = 0; num < 6; num++ )
{
score = smc_headerscore( hdr_addr[num], header );
printf( "%d: offset = %lX; score = %d\n", num, hdr_addr[num], score ); // */
if(score>=maxscore) {
if ( score >= maxscore )
{
score_idx = num;
maxscore = score;
}
}
if(score_idx & 1) {
if ( score_idx & 1 )
{
props->offset = 0x200;
} else {
}
else
{
props->offset = 0;
}
@@ -82,71 +102,98 @@ void smc_id(snes_romprops_t* props) {
/*dprintf("winner is %d\n", score_idx); */
file_readblock( header, hdr_addr[score_idx], sizeof( snes_header_t ) );
if(header->name[0x13] == 0x00 || header->name[0x13] == 0xff) {
if(header->name[0x14] == 0x00) {
if ( header->name[0x13] == 0x00 || header->name[0x13] == 0xff )
{
if ( header->name[0x14] == 0x00 )
{
const uint8_t n15 = header->map;
if ( n15 == 0x00 || n15 == 0x80 || n15 == 0x84 || n15 == 0x9c
|| n15 == 0xbc || n15 == 0xfc) {
if(header->licensee == 0x33 || header->licensee == 0xff) {
|| n15 == 0xbc || n15 == 0xfc )
{
if ( header->licensee == 0x33 || header->licensee == 0xff )
{
props->mapper_id = 0;
/*XXX do this properly */
props->ramsize_bytes = 0x8000;
props->romsize_bytes = 0x100000;
props->expramsize_bytes = 0;
props->mapper_id = 3; /* BS-X Memory Map */
props->region = 0; /* BS-X only existed in Japan */
return;
}
}
}
}
switch(header->map & 0xef) {
switch ( header->map & 0xef )
{
case 0x21: /* HiROM */
props->mapper_id = 0;
if(header->map == 0x31 && (header->carttype == 0x03 || header->carttype == 0x05)) {
if ( header->map == 0x31 && ( header->carttype == 0x03 || header->carttype == 0x05 ) )
{
props->has_dspx = 1;
props->dsp_fw = DSPFW_1B;
props->fpga_features |= FEAT_DSPX;
}
break;
case 0x20: /* LoROM */
props->mapper_id = 1;
if (header->map == 0x20 && header->carttype == 0xf3) {
if ( header->map == 0x20 && header->carttype == 0xf3 )
{
props->has_cx4 = 1;
props->dsp_fw = CX4FW;
props->fpga_conf = FPGA_CX4;
props->fpga_features |= FEAT_CX4;
}
else if ( ( header->map == 0x20 && header->carttype == 0x03 ) ||
(header->map == 0x30 && header->carttype == 0x05 && header->licensee != 0xb2)) {
( header->map == 0x30 && header->carttype == 0x05 && header->licensee != 0xb2 ) )
{
props->has_dspx = 1;
props->fpga_features |= FEAT_DSPX;
/* Pilotwings uses DSP1 instead of DSP1B */
if(!memcmp(header->name, "PILOTWINGS", 10)) {
if ( !memcmp( header->name, "PILOTWINGS", 10 ) )
{
props->dsp_fw = DSPFW_1;
} else {
}
else
{
props->dsp_fw = DSPFW_1B;
}
} else if (header->map == 0x20 && header->carttype == 0x05) {
}
else if ( header->map == 0x20 && header->carttype == 0x05 )
{
props->has_dspx = 1;
props->dsp_fw = DSPFW_2;
props->fpga_features |= FEAT_DSPX;
} else if (header->map == 0x30 && header->carttype == 0x05 && header->licensee == 0xb2) {
}
else if ( header->map == 0x30 && header->carttype == 0x05 && header->licensee == 0xb2 )
{
props->has_dspx = 1;
props->dsp_fw = DSPFW_3;
props->fpga_features |= FEAT_DSPX;
} else if (header->map == 0x30 && header->carttype == 0x03) {
}
else if ( header->map == 0x30 && header->carttype == 0x03 )
{
props->has_dspx = 1;
props->dsp_fw = DSPFW_4;
props->fpga_features |= FEAT_DSPX;
} else if (header->map == 0x30 && header->carttype == 0xf6 && header->romsize >= 0xa) {
}
else if ( header->map == 0x30 && header->carttype == 0xf6 && header->romsize >= 0xa )
{
props->has_dspx = 1;
props->has_st0010 = 1;
props->dsp_fw = DSPFW_ST0010;
props->fpga_features |= FEAT_ST0010;
header->ramsize = 2;
}
break;
case 0x25: /* ExHiROM */
@@ -154,84 +201,159 @@ void smc_id(snes_romprops_t* props) {
break;
case 0x22: /* ExLoROM */
if(file_handle.fsize > 0x400200) {
if ( file_handle.fsize > 0x400200 )
{
props->mapper_id = 6; /* SO96 */
} else {
}
else
{
props->mapper_id = 1;
}
break;
default: /* invalid/unsupported mapper, use header location */
switch(score_idx) {
switch ( score_idx )
{
case 0:
case 1:
props->mapper_id = 0;
break;
case 2:
case 3:
if(file_handle.fsize > 0x800200) {
if ( file_handle.fsize > 0x800200 )
{
props->mapper_id = 6; /* SO96 interleaved */
} else if(file_handle.fsize > 0x400200) {
}
else if ( file_handle.fsize > 0x400200 )
{
props->mapper_id = 1; /* ExLoROM */
} else {
}
else
{
props->mapper_id = 1; /* LoROM */
}
break;
case 4:
case 5:
props->mapper_id = 2;
break;
default:
props->mapper_id = 1; // whatever
}
}
if(header->romsize == 0 || header->romsize > 13) {
header->romsize = 13;
if ( header->romsize == 0 || header->romsize > 13 )
{
props->romsize_bytes = 1024;
header->romsize = 0;
if ( file_handle.fsize >= 1024 )
{
while ( props->romsize_bytes < file_handle.fsize - 1 )
{
header->romsize++;
props->romsize_bytes <<= 1;
}
}
}
props->ramsize_bytes = ( uint32_t )1024 << header->ramsize;
props->romsize_bytes = ( uint32_t )1024 << header->romsize;
props->expramsize_bytes = ( uint32_t )1024 << header->expramsize;
/*dprintf("ramsize_bytes: %ld\n", props->ramsize_bytes); */
if(props->ramsize_bytes > 32768 || props->ramsize_bytes < 2048) {
//dprintf("ramsize_bytes: %ld\n", props->ramsize_bytes);
if ( props->ramsize_bytes > 32768 || props->ramsize_bytes < 2048 )
{
props->ramsize_bytes = 0;
}
props->region = ( header->destcode <= 1 || header->destcode >= 13 ) ? 0 : 1;
/*dprintf("ramsize_bytes: %ld\n", props->ramsize_bytes); */
}
uint8_t smc_headerscore(uint32_t addr, snes_header_t* header) {
uint8_t smc_headerscore( uint32_t addr, snes_header_t *header )
{
int score = 0;
uint8_t reset_inst;
uint16_t header_offset;
if((addr & 0xfff) == 0x1b0) {
if ( ( addr & 0xfff ) == 0x1b0 )
{
header_offset = 0x200;
} else {
}
else
{
header_offset = 0;
}
if ( ( file_readblock( header, addr, sizeof( snes_header_t ) ) < sizeof( snes_header_t ) )
|| file_res) {
|| file_res )
{
return 0;
}
uint8_t mapper = header->map & ~0x10;
uint16_t resetvector = header->vect_reset; /* not endian safe! */
uint32_t file_addr = ( ( ( addr - header_offset ) & ~0x7fff ) | ( resetvector & 0x7fff ) ) + header_offset;
if(resetvector < 0x8000) return 0;
if ( resetvector < 0x8000 )
{
return 0;
}
score += 2 * isFixed( &header->licensee, sizeof( header->licensee ), 0x33 );
score += 4 * checkChksum( header->cchk, header->chk );
if(header->carttype < 0x08) score++;
if(header->romsize < 0x10) score++;
if(header->ramsize < 0x08) score++;
if(header->destcode < 0x0e) score++;
if((addr-header_offset) == 0x007fc0 && mapper == 0x20) score += 2;
if((addr-header_offset) == 0x00ffc0 && mapper == 0x21) score += 2;
if((addr-header_offset) == 0x007fc0 && mapper == 0x22) score += 2;
if((addr-header_offset) == 0x40ffc0 && mapper == 0x25) score += 2;
if ( header->carttype < 0x08 )
{
score++;
}
if ( header->romsize < 0x10 )
{
score++;
}
if ( header->ramsize < 0x08 )
{
score++;
}
if ( header->destcode < 0x0e )
{
score++;
}
if ( ( addr - header_offset ) == 0x007fc0 && mapper == 0x20 )
{
score += 2;
}
if ( ( addr - header_offset ) == 0x00ffc0 && mapper == 0x21 )
{
score += 2;
}
if ( ( addr - header_offset ) == 0x007fc0 && mapper == 0x22 )
{
score += 2;
}
if ( ( addr - header_offset ) == 0x40ffc0 && mapper == 0x25 )
{
score += 2;
}
file_readblock( &reset_inst, file_addr, 1 );
switch(reset_inst) {
switch ( reset_inst )
{
case 0x78: /* sei */
case 0x18: /* clc */
case 0x38: /* sec */
@@ -273,8 +395,16 @@ uint8_t smc_headerscore(uint32_t addr, snes_header_t* header) {
break;
}
if(score && addr > 0x400000) score += 4;
if(score < 0) score = 0;
if ( score && addr > 0x400000 )
{
score += 4;
}
if ( score < 0 )
{
score = 0;
}
return score;
}

View File

@@ -37,7 +37,8 @@
#define FPGA_CX4 ((const uint8_t*)"/sd2snes/fpga_cx4.bit")
typedef struct _snes_header {
typedef struct _snes_header
{
uint8_t maker[2]; /* 0xB0 */
uint8_t gamecode[4]; /* 0xB2 */
uint8_t fixed_00[7]; /* 0xB6 */
@@ -69,7 +70,8 @@ typedef struct _snes_header {
uint16_t vect_brk8; /* 0xFE */
} snes_header_t;
typedef struct _snes_romprops {
typedef struct _snes_romprops
{
uint16_t offset; /* start of actual ROM image */
uint8_t mapper_id; /* FPGA mapper */
uint8_t pad1; /* for alignment */

View File

@@ -25,6 +25,7 @@
*/
#include <arm/NXP/LPC17xx/LPC17xx.h>
#include <string.h>
#include "bits.h"
#include "config.h"
#include "uart.h"
@@ -46,37 +47,53 @@ extern snes_romprops_t romprops;
volatile int reset_changed;
volatile int reset_pressed;
void prepare_reset() {
void prepare_reset()
{
snes_reset( 1 );
delay_ms(1);
if(romprops.ramsize_bytes && fpga_test() == FPGA_TEST_TOKEN) {
delay_ms( SNES_RESET_PULSELEN_MS );
if ( romprops.ramsize_bytes && fpga_test() == FPGA_TEST_TOKEN )
{
writeled( 1 );
save_sram( file_lfn, romprops.ramsize_bytes, SRAM_SAVE_ADDR );
writeled( 0 );
}
rdyled( 1 );
readled( 1 );
writeled( 1 );
snes_reset( 0 );
while ( get_snes_reset() );
snes_reset( 1 );
fpga_dspx_reset( 1 );
delay_ms( 200 );
}
void snes_init() {
void snes_init()
{
/* put reset level on reset pin */
BITBAND( SNES_RESET_REG->FIOCLR, SNES_RESET_BIT ) = 1;
/* reset the SNES */
snes_reset( 1 );
}
void snes_reset_pulse()
{
snes_reset( 1 );
delay_ms( SNES_RESET_PULSELEN_MS );
snes_reset( 0 );
}
/*
* sets the SNES reset state.
*
* state: put SNES in reset state when 1, release when 0
*/
void snes_reset(int state) {
void snes_reset( int state )
{
BITBAND( SNES_RESET_REG->FIODIR, SNES_RESET_BIT ) = state;
}
@@ -85,7 +102,8 @@ void snes_reset(int state) {
*
* returns: 1 when reset, 0 when not reset
*/
uint8_t get_snes_reset() {
uint8_t get_snes_reset()
{
return !BITBAND( SNES_RESET_REG->FIOPIN, SNES_RESET_BIT );
}
@@ -95,80 +113,122 @@ uint8_t get_snes_reset() {
*/
uint32_t diffcount = 0, samecount = 0, didnotsave = 0;
uint8_t sram_valid = 0;
void snes_main_loop() {
if(!romprops.ramsize_bytes)return;
if(initloop) {
void snes_main_loop()
{
if ( !romprops.ramsize_bytes )
{
return;
}
if ( initloop )
{
saveram_crc_old = calc_sram_crc( SRAM_SAVE_ADDR, romprops.ramsize_bytes );
initloop = 0;
}
saveram_crc = calc_sram_crc( SRAM_SAVE_ADDR, romprops.ramsize_bytes );
sram_valid = sram_reliable();
if(crc_valid && sram_valid) {
if(saveram_crc != saveram_crc_old) {
if(samecount) {
if ( crc_valid && sram_valid )
{
if ( saveram_crc != saveram_crc_old )
{
if ( samecount )
{
diffcount = 1;
} else {
}
else
{
diffcount++;
didnotsave++;
}
samecount = 0;
}
if(saveram_crc == saveram_crc_old) {
if ( saveram_crc == saveram_crc_old )
{
samecount++;
}
if(diffcount>=1 && samecount==5) {
printf("SaveRAM CRC: 0x%04lx; saving\n", saveram_crc);
if ( diffcount >= 1 && samecount == 5 )
{
printf( "SaveRAM CRC: 0x%04lx; saving %s\n", saveram_crc, file_lfn );
writeled( 1 );
save_sram( file_lfn, romprops.ramsize_bytes, SRAM_SAVE_ADDR );
writeled( 0 );
didnotsave = 0;
}
if(didnotsave>50) {
if ( didnotsave > 50 )
{
printf( "periodic save (sram contents keep changing...)\n" );
diffcount = 0;
writeled( 1 );
save_sram( file_lfn, romprops.ramsize_bytes, SRAM_SAVE_ADDR );
didnotsave = 0;
writeled(0);
writeled( 1 );
}
saveram_crc_old = saveram_crc;
}
printf("crc=%lx crc_valid=%d sram_valid=%d diffcount=%ld samecount=%ld, didnotsave=%ld\n", saveram_crc, crc_valid, sram_valid, diffcount, samecount, didnotsave);
printf( "crc=%lx crc_valid=%d sram_valid=%d diffcount=%ld samecount=%ld, didnotsave=%ld\n", saveram_crc, crc_valid,
sram_valid, diffcount, samecount, didnotsave );
}
/*
* SD2SNES menu loop.
* monitors menu selection. return when selection was made.
*/
uint8_t menu_main_loop() {
uint8_t menu_main_loop()
{
uint8_t cmd = 0;
sram_writebyte( 0, SRAM_CMD_ADDR );
while(!cmd) {
if(!get_snes_reset()) {
while(!sram_reliable())printf("hurr\n");
cmd = sram_readbyte(SRAM_CMD_ADDR);
while ( !cmd )
{
if ( !get_snes_reset() )
{
while ( !sram_reliable() )
{
printf( "hurr\n" );
}
if(get_snes_reset()) {
cmd = sram_readbyte( SRAM_CMD_ADDR );
//cmd = SNES_CMD_LOADSPC;
}
if ( get_snes_reset() )
{
cmd = 0;
}
sleep_ms( 20 );
cli_entrycheck();
}
return cmd;
}
void get_selected_name(uint8_t* fn) {
void get_selected_name( uint8_t *fn )
{
uint32_t addr;
addr = sram_readlong( SRAM_PARAM_ADDR );
printf( "fd addr=%lx\n", addr );
sram_readblock( fn, addr + 7 + SRAM_MENU_ADDR, 256 );
//memcpy(fn, "dossier sans titre/ff6.sfc", 28);
}
void snes_bootprint(void* msg) {
void snes_bootprint( void *msg )
{
printf( "SNES SAY: %s\n", ( char * )msg );
sram_writeblock( msg, SRAM_CMD_ADDR, 33 );
}
void snes_menu_errmsg(int err, void* msg) {
void snes_menu_errmsg( int err, void *msg )
{
printf( "%d: %s\n", err, ( char * )msg );
sram_writeblock( msg, SRAM_CMD_ADDR + 1, 64 );
sram_writebyte( err, SRAM_CMD_ADDR );
}

View File

@@ -31,15 +31,20 @@
#define SNES_CMD_SETRTC (2)
#define SNES_CMD_SYSINFO (3)
#define SNES_CMD_LOADLAST (4)
#define SNES_CMD_LOADSPC (5)
#define SNES_CMD_RESET (6)
#define MENU_ERR_OK (0)
#define MENU_ERR_NODSP (1)
#define MENU_ERR_NOBSX (2)
#define SNES_RESET_PULSELEN_MS (100)
uint8_t crc_valid;
void prepare_reset( void );
void snes_init( void );
void snes_reset_pulse( void );
void snes_reset( int state );
uint8_t get_snes_reset( void );
void snes_main_loop( void );

View File

@@ -1,330 +1,295 @@
const uint8_t bootrle[] = {
0xe2, 0x20, 0xc2, 0x10, 0xa9, 0x00, 0x48, 0xab,
0xad, 0x10, 0x42, 0xa2, 0x00, 0x58, 0x8e, 0x16,
0x21, 0xa9, 0x01, 0x8d, 0x15, 0x00, 0xa2, 0x00,
0xb0, 0xa9, 0x7f, 0x8e, 0x10, 0x00, 0x8d, 0x0f,
0x00, 0xa2, 0x00, 0x09, 0x8e, 0x13, 0x00, 0xa9,
0x18, 0x8d, 0x12, 0x00, 0x20, 0xdc, 0x0b, 0xa9,
0x01, 0x8d, 0x16, 0x00, 0x6b, 0xe2, 0x20, 0xad,
0x11, 0x42, 0x6b, 0xe2, 0x20, 0xc2, 0x10, 0x78,
0x9c, 0x00, 0x42, 0x20, 0x2a, 0x01, 0xa9, 0x01,
0x8d, 0x0d, 0x42, 0x20, 0x84, 0x02, 0x20, 0x93,
0x01, 0x20, 0x8b, 0x01, 0x20, 0x04, 0x0c, 0x20,
0x57, 0x02, 0xa2, 0x41, 0x00, 0xa9, 0x00, 0xca,
0x9f, 0x00, 0x70, 0x30, 0xd0, 0xf9, 0xa9, 0x7e,
0xa2, 0x1b, 0x00, 0x8d, 0x83, 0x21, 0x8e, 0x81,
0x21, 0xa9, 0x00, 0x8d, 0x15, 0x00, 0xa2, 0xbc,
0x00, 0xa9, 0xc0, 0x8e, 0x10, 0x00, 0x8d, 0x0f,
0x00, 0xa2, 0x6f, 0x00, 0x8e, 0x13, 0x00, 0xa9,
0x80, 0x8d, 0x12, 0x00, 0x20, 0xdc, 0x0b, 0xa9,
0x7e, 0xa2, 0x8b, 0x00, 0x8d, 0x83, 0x21, 0x8e,
0x81, 0x21, 0xa9, 0x00, 0x8d, 0x15, 0x00, 0xa2,
0x8c, 0x0b, 0xa9, 0xc0, 0x8e, 0x10, 0x00, 0x8d,
0x0f, 0x00, 0xa2, 0x4f, 0x00, 0x8e, 0x13, 0x00,
0xa9, 0x80, 0x8d, 0x12, 0x00, 0x20, 0xdc, 0x0b,
0x22, 0x1b, 0x00, 0x7e, 0xc2, 0x10, 0xe2, 0x20,
0xa9, 0x00, 0x8f, 0x00, 0x00, 0x7e, 0xa9, 0x0d,
0x8f, 0x02, 0x00, 0x7e, 0xa9, 0x30, 0x8f, 0x06,
0x00, 0x7e, 0xc2, 0x20, 0xa9, 0x00, 0x70, 0x8f,
0x04, 0x00, 0x7e, 0xe2, 0x20, 0xa9, 0x00, 0x8f,
0x07, 0x00, 0x7e, 0x20, 0x8b, 0x00, 0xc2, 0x20,
0xa9, 0x00, 0x58, 0x8d, 0x16, 0x21, 0xe2, 0x20,
0xa9, 0x01, 0x8d, 0x00, 0x43, 0xa9, 0x18, 0x8d,
0x01, 0x43, 0xa9, 0x7f, 0x8d, 0x04, 0x43, 0xa2,
0x00, 0xb0, 0x8e, 0x02, 0x43, 0xa2, 0x00, 0x09,
0x8e, 0x05, 0x43, 0xaf, 0x12, 0x42, 0x00, 0x29,
0x80, 0xd0, 0xf8, 0xaf, 0x12, 0x42, 0x00, 0x29,
0x80, 0xf0, 0xf8, 0xa9, 0x01, 0x8d, 0x0b, 0x42,
0x80, 0x9a, 0x58, 0x9c, 0x00, 0x42, 0x5c, 0x19,
0x00, 0x7e, 0x9c, 0x0b, 0x42, 0x9c, 0x0c, 0x42,
0x9c, 0x10, 0x43, 0x9c, 0x11, 0x43, 0x9c, 0x12,
0x43, 0x9c, 0x13, 0x43, 0x9c, 0x14, 0x43, 0x9c,
0x20, 0x43, 0x9c, 0x21, 0x43, 0x9c, 0x22, 0x43,
0x9c, 0x23, 0x43, 0x9c, 0x24, 0x43, 0x9c, 0x30,
0x43, 0x9c, 0x31, 0x43, 0x9c, 0x32, 0x43, 0x9c,
0x33, 0x43, 0x9c, 0x34, 0x43, 0x9c, 0x40, 0x43,
0x9c, 0x41, 0x43, 0x9c, 0x42, 0x43, 0x9c, 0x43,
0x43, 0x9c, 0x44, 0x43, 0x9c, 0x50, 0x43, 0x9c,
0x51, 0x43, 0x9c, 0x52, 0x43, 0x9c, 0x53, 0x43,
0x9c, 0x54, 0x43, 0x60, 0xad, 0x12, 0x42, 0x29,
0x80, 0xd0, 0xf9, 0xad, 0x12, 0x42, 0x29, 0x80,
0xf0, 0xf9, 0x60, 0xe2, 0x20, 0xc2, 0x10, 0x9c,
0x30, 0x21, 0x60, 0xe2, 0x20, 0xc2, 0x10, 0x9c,
0x00, 0x42, 0x9c, 0x0b, 0x42, 0x9c, 0x0c, 0x42,
0xa2, 0x00, 0xb0, 0x8e, 0x81, 0x21, 0xa9, 0x01,
0x8d, 0x83, 0x21, 0xa9, 0x08, 0x8d, 0x15, 0x00,
0xa2, 0x59, 0xff, 0xa9, 0xc0, 0x8e, 0x10, 0x00,
0x8d, 0x0f, 0x00, 0xa2, 0x40, 0x07, 0x8e, 0x13,
0x00, 0xa9, 0x80, 0x8d, 0x12, 0x00, 0x20, 0xdc,
0x0b, 0xa2, 0x00, 0x00, 0x8e, 0x16, 0x21, 0xa9,
0x01, 0x8d, 0x15, 0x00, 0xa2, 0x7c, 0x03, 0xa9,
0xc0, 0x8e, 0x10, 0x00, 0x8d, 0x0f, 0x00, 0xa2,
0x00, 0x08, 0x8e, 0x13, 0x00, 0xa9, 0x18, 0x8d,
0x12, 0x00, 0x20, 0xdc, 0x0b, 0xa2, 0x00, 0x58,
0x8e, 0x16, 0x21, 0xa9, 0x09, 0x8d, 0x15, 0x00,
0xa2, 0x59, 0xff, 0xa9, 0xc0, 0x8e, 0x10, 0x00,
0x8d, 0x0f, 0x00, 0xa2, 0x40, 0x07, 0x8e, 0x13,
0x00, 0xa9, 0x18, 0x8d, 0x12, 0x00, 0x20, 0xdc,
0x0b, 0xa2, 0x00, 0x00, 0x8e, 0x02, 0x21, 0xa9,
0x08, 0x8d, 0x15, 0x00, 0xa2, 0x59, 0xff, 0xa9,
0xc0, 0x8e, 0x10, 0x00, 0x8d, 0x0f, 0x00, 0xa2,
0x20, 0x02, 0x8e, 0x13, 0x00, 0xa9, 0x04, 0x8d,
0x12, 0x00, 0x20, 0xdc, 0x0b, 0x9c, 0x21, 0x21,
0xa9, 0x00, 0x8d, 0x15, 0x00, 0xa2, 0x7c, 0x0b,
0xa9, 0xc0, 0x8e, 0x10, 0x00, 0x8d, 0x0f, 0x00,
0xa2, 0x10, 0x00, 0x8e, 0x13, 0x00, 0xa9, 0x22,
0x8d, 0x12, 0x00, 0x20, 0xdc, 0x0b, 0x60, 0xe2,
0x20, 0xc2, 0x10, 0xa9, 0x00, 0x8d, 0x05, 0x21,
0xa9, 0x58, 0x09, 0x02, 0x8d, 0x07, 0x21, 0xa9,
0x40, 0x8d, 0x0b, 0x21, 0xa9, 0x01, 0x8d, 0x2c,
0x21, 0xa9, 0x01, 0x8d, 0x2d, 0x21, 0xa9, 0x00,
0x8d, 0x30, 0x21, 0x9c, 0x21, 0x21, 0xa9, 0x0f,
0x8d, 0x00, 0x21, 0x60, 0xe2, 0x20, 0xc2, 0x10,
0x9c, 0x00, 0x42, 0xa9, 0xff, 0x8d, 0x01, 0x42,
0x9c, 0x02, 0x42, 0x9c, 0x03, 0x42, 0x9c, 0x04,
0x42, 0x9c, 0x05, 0x42, 0x9c, 0x06, 0x42, 0x9c,
0x07, 0x42, 0x9c, 0x08, 0x42, 0x9c, 0x09, 0x42,
0x9c, 0x0a, 0x42, 0x9c, 0x0b, 0x42, 0x9c, 0x0c,
0x42, 0xa9, 0x00, 0x8d, 0x0d, 0x42, 0xa9, 0x8f,
0x8d, 0x00, 0x21, 0xa9, 0x03, 0x8d, 0x01, 0x21,
0x9c, 0x02, 0x21, 0x9c, 0x03, 0x21, 0x9c, 0x05,
0x21, 0x9c, 0x06, 0x21, 0x9c, 0x07, 0x21, 0x9c,
0x08, 0x21, 0x9c, 0x09, 0x21, 0x9c, 0x0a, 0x21,
0x9c, 0x0b, 0x21, 0x9c, 0x0c, 0x21, 0x9c, 0x0d,
0x21, 0x9c, 0x0d, 0x21, 0x9c, 0x0e, 0x21, 0x9c,
0x0e, 0x21, 0x9c, 0x0f, 0x21, 0x9c, 0x0f, 0x21,
0xa9, 0x05, 0x8d, 0x10, 0x21, 0x9c, 0x10, 0x21,
0x9c, 0x11, 0x21, 0x9c, 0x11, 0x21, 0x9c, 0x12,
0x21, 0x9c, 0x12, 0x21, 0x9c, 0x13, 0x21, 0x9c,
0x13, 0x21, 0x9c, 0x14, 0x21, 0x9c, 0x14, 0x21,
0xa9, 0x80, 0x8d, 0x15, 0x21, 0x9c, 0x16, 0x21,
0x9c, 0x17, 0x21, 0x9c, 0x1a, 0x21, 0x9c, 0x1b,
0x21, 0xa9, 0x01, 0x8d, 0x1b, 0x21, 0x9c, 0x1c,
0x21, 0x9c, 0x1c, 0x21, 0x9c, 0x1d, 0x21, 0x9c,
0x1d, 0x21, 0x9c, 0x1e, 0x21, 0x8d, 0x1e, 0x21,
0x9c, 0x1f, 0x21, 0x9c, 0x1f, 0x21, 0x9c, 0x20,
0x21, 0x9c, 0x20, 0x21, 0x9c, 0x21, 0x21, 0x9c,
0x23, 0x21, 0x9c, 0x24, 0x21, 0x9c, 0x25, 0x21,
0x9c, 0x26, 0x21, 0x9c, 0x27, 0x21, 0x9c, 0x28,
0x21, 0x9c, 0x29, 0x21, 0x9c, 0x2a, 0x21, 0x9c,
0x2b, 0x21, 0x9c, 0x2c, 0x21, 0x9c, 0x2d, 0x21,
0x9c, 0x2e, 0x21, 0xa9, 0x30, 0x8d, 0x30, 0x21,
0x9c, 0x31, 0x21, 0xa9, 0xe0, 0x8d, 0x32, 0x21,
0x9c, 0x33, 0x21, 0x60, 0x77, 0x00, 0x11, 0x02,
0x30, 0x30, 0x48, 0x30, 0x48, 0x30, 0x48, 0x20,
0x58, 0x00, 0x30, 0x30, 0x48, 0x00, 0x30, 0x00,
0x6c, 0x6c, 0x92, 0x24, 0x5a, 0x00, 0x36, 0x5b,
0x00, 0x09, 0x6c, 0x6c, 0x92, 0xfe, 0x01, 0x6c,
0x92, 0xfe, 0x01, 0x6c, 0x92, 0x00, 0x6c, 0x00,
0x00, 0x10, 0x6c, 0x7c, 0xc6, 0xc6, 0x39, 0xf0,
0x0e, 0x1e, 0xe1, 0xc6, 0x39, 0x7c, 0xc6, 0x10,
0x6c, 0x42, 0xa5, 0xa4, 0x5a, 0x48, 0xb4, 0x10,
0x6c, 0x24, 0x5a, 0x4a, 0xb5, 0x84, 0x4a, 0x00,
0x84, 0x70, 0xc8, 0xc0, 0x34, 0xc4, 0x2e, 0x6e,
0xdb, 0xc4, 0x2a, 0xc4, 0x3a, 0x7c, 0xc6, 0x00,
0x7c, 0x00, 0x18, 0x18, 0x24, 0x10, 0x28, 0x00,
0x10, 0x5b, 0x00, 0x08, 0x18, 0x24, 0x30, 0x68,
0x30, 0x48, 0x30, 0x48, 0x30, 0x48, 0x30, 0x68,
0x18, 0x24, 0x00, 0x18, 0x30, 0x48, 0x18, 0x2c,
0x18, 0x24, 0x18, 0x24, 0x18, 0x24, 0x18, 0x2c,
0x30, 0x48, 0x00, 0x30, 0x00, 0x6c, 0x6c, 0x92,
0x38, 0x44, 0x7c, 0x82, 0x38, 0x44, 0x6c, 0x92,
0x00, 0x6c, 0x00, 0x00, 0x00, 0x18, 0x18, 0x24,
0x18, 0x66, 0x7e, 0x81, 0x18, 0x66, 0x18, 0x24,
0x00, 0x18, 0x5b, 0x00, 0x0b, 0x18, 0x18, 0x24,
0x18, 0x24, 0x10, 0x28, 0x5b, 0x00, 0x05, 0x7e,
0x7e, 0x81, 0x00, 0x7e, 0x5b, 0x00, 0x0f, 0x18,
0x18, 0x24, 0x18, 0x24, 0x00, 0x18, 0x03, 0x04,
0x06, 0x09, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48,
0x60, 0x90, 0xc0, 0x20, 0x00, 0xc0, 0x7c, 0xc6,
0xe6, 0x39, 0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x29,
0xce, 0x39, 0x7c, 0xc6, 0x00, 0x7c, 0x18, 0x34,
0x18, 0x24, 0x18, 0x24, 0x18, 0x24, 0x18, 0x24,
0x18, 0x24, 0x18, 0x24, 0x00, 0x18, 0xfc, 0x06,
0x06, 0xf9, 0x06, 0x79, 0x7c, 0x86, 0xc0, 0xbc,
0xc0, 0x3e, 0xfe, 0x01, 0x00, 0xfe, 0xfc, 0x06,
0x06, 0xf9, 0x06, 0x39, 0x3c, 0x46, 0x06, 0x39,
0x06, 0xf9, 0xfc, 0x06, 0x00, 0xfc, 0xc6, 0x29,
0xc6, 0x29, 0xc6, 0x39, 0x7e, 0xc1, 0x06, 0x79,
0x06, 0x09, 0x06, 0x09, 0x00, 0x06, 0xfe, 0x01,
0xc0, 0x3e, 0xc0, 0x3c, 0xfc, 0x06, 0x06, 0xf9,
0x06, 0xf9, 0xfc, 0x06, 0x00, 0xf8, 0x7c, 0xc2,
0xc0, 0x3c, 0xc0, 0x3c, 0xfc, 0x06, 0xc6, 0x39,
0xc6, 0x39, 0x7c, 0xc6, 0x00, 0x7c, 0xfc, 0x06,
0x06, 0xf9, 0x06, 0x09, 0x06, 0x09, 0x06, 0x09,
0x06, 0x09, 0x06, 0x09, 0x00, 0x06, 0x7c, 0xc6,
0xc6, 0x39, 0xc6, 0x39, 0x7c, 0xc6, 0xc6, 0x39,
0xc6, 0x39, 0x7c, 0xc6, 0x00, 0x7c, 0x7c, 0xc6,
0xc6, 0x39, 0xc6, 0x39, 0x7e, 0xc1, 0x06, 0x79,
0x06, 0x79, 0x7c, 0x86, 0x00, 0x7c, 0x00, 0x00,
0x00, 0x30, 0x30, 0x48, 0x00, 0x30, 0x00, 0x30,
0x30, 0x48, 0x00, 0x30, 0x5b, 0x00, 0x05, 0x30,
0x30, 0x48, 0x00, 0x30, 0x00, 0x30, 0x30, 0x48,
0x20, 0x50, 0x00, 0x20, 0x00, 0x18, 0x18, 0x24,
0x30, 0x48, 0x60, 0x90, 0x30, 0x48, 0x18, 0x24,
0x00, 0x18, 0x5b, 0x00, 0x05, 0x3c, 0x3c, 0x42,
0x00, 0x3c, 0x00, 0x3c, 0x3c, 0x42, 0x00, 0x3c,
0x00, 0x00, 0x00, 0x30, 0x30, 0x48, 0x18, 0x24,
0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x00, 0x30,
0x00, 0x00, 0xf8, 0x0c, 0x0c, 0xf2, 0x0c, 0x12,
0x18, 0x24, 0x30, 0x48, 0x00, 0x30, 0x30, 0x48,
0x00, 0x30, 0x7c, 0xc6, 0xc6, 0x39, 0xc6, 0x39,
0xde, 0x21, 0xde, 0x21, 0xc0, 0x3e, 0x7e, 0xc1,
0x00, 0x7e, 0x7c, 0xc6, 0xc6, 0x39, 0xc6, 0x39,
0xde, 0x21, 0xc6, 0x39, 0xc6, 0x29, 0xc6, 0x29,
0x00, 0xc6, 0xfc, 0x06, 0xc6, 0x39, 0xc6, 0x39,
0xdc, 0x26, 0xc6, 0x39, 0xc6, 0x39, 0xfc, 0x06,
0x00, 0xfc, 0x7e, 0xc1, 0xc0, 0x3e, 0xc0, 0x20,
0xc0, 0x20, 0xc0, 0x20, 0xc0, 0x3e, 0x7e, 0xc1,
0x00, 0x7e, 0xfc, 0x02, 0xc6, 0x3b, 0xc6, 0x29,
0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x3b, 0xfc, 0x02,
0x00, 0xfc, 0xfe, 0x01, 0xc0, 0x3e, 0xc0, 0x38,
0xf8, 0x04, 0xc0, 0x38, 0xc0, 0x3e, 0xfe, 0x01,
0x00, 0xfe, 0xfe, 0x01, 0xc0, 0x3e, 0xc0, 0x38,
0xf8, 0x04, 0xc0, 0x38, 0xc0, 0x20, 0xc0, 0x20,
0x00, 0xc0, 0x7e, 0xc1, 0xc0, 0x3e, 0xc0, 0x2e,
0xce, 0x33, 0xc6, 0x29, 0xc6, 0x39, 0x7c, 0xc6,
0x00, 0x7c, 0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x39,
0xfe, 0x01, 0xc6, 0x39, 0xc6, 0x29, 0xc6, 0x29,
0x00, 0xc6, 0x18, 0x24, 0x18, 0x24, 0x18, 0x24,
0x18, 0x24, 0x18, 0x24, 0x18, 0x24, 0x18, 0x24,
0x00, 0x18, 0x0c, 0x12, 0x0c, 0x12, 0x0c, 0x12,
0x0c, 0x12, 0x0c, 0x12, 0x0c, 0xf6, 0xf8, 0x06,
0x00, 0xfc, 0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x38,
0xfc, 0x06, 0xc6, 0x39, 0xc6, 0x29, 0xc6, 0x29,
0x00, 0xc7, 0xc0, 0x20, 0xc0, 0x20, 0xc0, 0x20,
0xc0, 0x20, 0xc0, 0x20, 0xc0, 0x3c, 0xfc, 0x02,
0x00, 0xfc, 0xec, 0x16, 0xd6, 0x29, 0xd6, 0x29,
0xd6, 0x29, 0xc6, 0x39, 0xc6, 0x29, 0xc6, 0x29,
0x00, 0xc7, 0xfc, 0x06, 0xc6, 0x39, 0xc6, 0x29,
0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x29,
0x00, 0xc6, 0x7c, 0xc6, 0xc6, 0x39, 0xc6, 0x29,
0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x39, 0x7c, 0xc6,
0x00, 0x7c, 0xfc, 0x06, 0xc6, 0x39, 0xc6, 0x29,
0xc6, 0x39, 0xfc, 0x06, 0xc0, 0x3c, 0xc0, 0x20,
0x00, 0xc0, 0x7c, 0x82, 0xc6, 0xbb, 0xc6, 0x29,
0xc6, 0x29, 0xc6, 0x29, 0xce, 0x31, 0x7e, 0xc1,
0x00, 0x7e, 0xfc, 0x06, 0xc6, 0x39, 0xc6, 0x39,
0xfc, 0x06, 0xc6, 0x39, 0xc6, 0x29, 0xc6, 0x29,
0x00, 0xc6, 0x7e, 0xc1, 0xc0, 0x3e, 0xc0, 0x3c,
0x7c, 0xc6, 0x06, 0x79, 0x06, 0xf9, 0xfc, 0x06,
0x00, 0xfc, 0xfe, 0x01, 0x18, 0xe6, 0x18, 0x24,
0x18, 0x24, 0x18, 0x24, 0x18, 0x24, 0x18, 0x24,
0x00, 0x18, 0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x29,
0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x39, 0x7c, 0xc6,
0x00, 0x7c, 0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x29,
0xc6, 0x29, 0x66, 0x99, 0x36, 0x49, 0x1e, 0x21,
0x00, 0x1f, 0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x39,
0xd6, 0x29, 0xd6, 0x29, 0xd6, 0x29, 0x6e, 0xd1,
0x00, 0x6e, 0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x39,
0x7c, 0xc6, 0xc6, 0x39, 0xc6, 0x29, 0xc6, 0x29,
0x00, 0xc6, 0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x39,
0x7e, 0xc1, 0x06, 0x79, 0x06, 0xf9, 0xfc, 0x06,
0x00, 0xfc, 0xfe, 0x01, 0x06, 0xf9, 0x06, 0x79,
0x7c, 0xc6, 0xc0, 0x3c, 0xc0, 0x3e, 0xfe, 0x01,
0x00, 0xfe, 0x3c, 0x42, 0x30, 0x4c, 0x30, 0x48,
0x30, 0x48, 0x30, 0x48, 0x30, 0x4c, 0x3c, 0x42,
0x00, 0x3c, 0xc0, 0x20, 0x60, 0x90, 0x30, 0x48,
0x18, 0x24, 0x0c, 0x12, 0x06, 0x09, 0x03, 0x04,
0x00, 0x03, 0x3c, 0x42, 0x0c, 0x32, 0x0c, 0x12,
0x0c, 0x12, 0x0c, 0x12, 0x0c, 0x32, 0x3c, 0x42,
0x00, 0x3c, 0x18, 0x24, 0x3c, 0x66, 0x66, 0x99,
0x00, 0x66, 0x5b, 0x00, 0x13, 0x7e, 0x7e, 0x81,
0x00, 0x7e, 0x30, 0x48, 0x18, 0x24, 0x18, 0x24,
0x00, 0x18, 0x5b, 0x00, 0x0b, 0x7c, 0x7c, 0x86,
0x06, 0x79, 0x7e, 0xc1, 0xc6, 0x39, 0x7e, 0xc1,
0x00, 0x7e, 0xc0, 0x20, 0xc0, 0x3c, 0xfc, 0x06,
0xc6, 0x39, 0xc6, 0x29, 0xc6, 0x39, 0xfc, 0x06,
0x00, 0xfc, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0xc1,
0xc0, 0x3e, 0xc0, 0x20, 0xc0, 0x3e, 0x7e, 0xc1,
0x00, 0x7e, 0x06, 0x09, 0x06, 0x79, 0x7e, 0xc1,
0xc6, 0x39, 0xc6, 0x29, 0xc6, 0x39, 0x7e, 0xc1,
0x00, 0x7f, 0x00, 0x00, 0x00, 0x7c, 0x7c, 0xc6,
0xc6, 0x39, 0xfe, 0x01, 0xc0, 0x3e, 0x7e, 0xc3,
0x00, 0x7e, 0x1e, 0x21, 0x30, 0x6e, 0x30, 0x4c,
0x3c, 0x42, 0x30, 0x4c, 0x30, 0x48, 0x30, 0x48,
0x30, 0x48, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0xc1,
0xc6, 0x39, 0xc6, 0x39, 0x7e, 0xc1, 0x06, 0x79,
0x7c, 0x86, 0xc0, 0x20, 0xc0, 0x3c, 0xfc, 0x06,
0xc6, 0x39, 0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x29,
0x00, 0xc6, 0x00, 0x18, 0x18, 0x24, 0x00, 0x18,
0x18, 0x24, 0x18, 0x24, 0x18, 0x24, 0x18, 0x24,
0x00, 0x18, 0x00, 0x18, 0x18, 0x24, 0x00, 0x18,
0x18, 0x24, 0x18, 0x24, 0x18, 0x24, 0x18, 0x2c,
0x30, 0x48, 0xc0, 0x20, 0xc0, 0x26, 0xc6, 0x29,
0xc6, 0x2b, 0xfc, 0x06, 0xc6, 0x2b, 0xc6, 0x29,
0x00, 0xc7, 0x30, 0x48, 0x30, 0x48, 0x30, 0x48,
0x30, 0x48, 0x30, 0x48, 0x30, 0x68, 0x18, 0x24,
0x00, 0x1c, 0x00, 0x00, 0x00, 0xec, 0xec, 0x16,
0xd6, 0x29, 0xd6, 0x29, 0xd6, 0x29, 0xc6, 0x39,
0x00, 0xc7, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0x06,
0xc6, 0x39, 0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x29,
0x00, 0xc6, 0x00, 0x00, 0x00, 0x7c, 0x7c, 0xc6,
0xc6, 0x39, 0xc6, 0x29, 0xc6, 0x39, 0x7c, 0xc6,
0x00, 0x7c, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0x06,
0xc6, 0x39, 0xc6, 0x39, 0xfc, 0x06, 0xc0, 0x3c,
0xc0, 0x20, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0xc1,
0xc6, 0x39, 0xc6, 0x39, 0x7e, 0xc1, 0x06, 0x79,
0x06, 0x09, 0x00, 0x00, 0x00, 0x7c, 0x7c, 0xc2,
0xc0, 0x3c, 0xc0, 0x20, 0xc0, 0x20, 0xc0, 0x20,
0x00, 0xc0, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0xc1,
0xc0, 0x3e, 0x7c, 0xc6, 0x06, 0xf9, 0xfc, 0x06,
0x00, 0xfc, 0x30, 0x48, 0x30, 0x4c, 0x3c, 0x42,
0x30, 0x4c, 0x30, 0x48, 0x30, 0x4e, 0x1e, 0x31,
0x00, 0x1e, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x29,
0xc6, 0x29, 0xc6, 0x29, 0xc6, 0x39, 0x7c, 0xc6,
0x00, 0x7c, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x29,
0xc6, 0x29, 0x66, 0x99, 0x36, 0x49, 0x1e, 0x21,
0x00, 0x1e, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x39,
0xd6, 0x29, 0xd6, 0x29, 0xd6, 0x29, 0x6e, 0xd1,
0x00, 0x6e, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x29,
0xc6, 0x39, 0x7c, 0xc6, 0xc6, 0x39, 0xc6, 0x29,
0x00, 0xc6, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0x29,
0xc6, 0x39, 0x7e, 0xc1, 0x06, 0x79, 0x06, 0xf9,
0xfc, 0x06, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x01,
0x06, 0xf9, 0x7c, 0xc6, 0xc0, 0x3e, 0xfe, 0x01,
0x00, 0xfe, 0x18, 0x24, 0x30, 0x48, 0x30, 0x48,
0x70, 0x88, 0x30, 0x48, 0x30, 0x48, 0x18, 0x24,
0x00, 0x18, 0x18, 0x24, 0x18, 0x24, 0x18, 0x24,
0x00, 0x18, 0x18, 0x24, 0x18, 0x24, 0x18, 0x24,
0x00, 0x18, 0x30, 0x48, 0x18, 0x24, 0x18, 0x24,
0x1c, 0x22, 0x18, 0x24, 0x18, 0x24, 0x30, 0x48,
0x00, 0x30, 0x00, 0x00, 0x00, 0x72, 0x72, 0x9d,
0xfe, 0x01, 0x9c, 0x72, 0x00, 0x9c, 0x5b, 0x00,
0x14, 0x42, 0x08, 0xff, 0x7f, 0x00, 0x00, 0x9c,
0x73, 0x42, 0x08, 0xff, 0x43, 0x00, 0x00, 0x18,
0x63, 0xc2, 0x30, 0xad, 0x00, 0x00, 0x29, 0xff,
0x00, 0x0a, 0x18, 0x69, 0x00, 0xb0, 0x8d, 0x09,
0x00, 0xad, 0x02, 0x00, 0x29, 0xff, 0x00, 0x5b,
0x0a, 0x06, 0x18, 0x6d, 0x09, 0x00, 0x8f, 0x81,
0x21, 0x00, 0xe2, 0x20, 0xa9, 0x7f, 0x8f, 0x83,
0x21, 0x00, 0xae, 0x04, 0x00, 0xad, 0x06, 0x00,
0x48, 0xab, 0xbd, 0x00, 0x00, 0xf0, 0x11, 0x8f,
0x80, 0x21, 0x00, 0xa9, 0x00, 0x69, 0x00, 0x09,
0x20, 0x8f, 0x80, 0x21, 0x00, 0xe8, 0x80, 0xea,
0xa9, 0x00, 0x48, 0xab, 0x60, 0xff, 0xc2, 0x10,
0xe2, 0x20, 0xad, 0x15, 0x00, 0x8d, 0x00, 0x43,
0xad, 0x12, 0x00, 0x8d, 0x01, 0x43, 0xad, 0x0f,
0x00, 0xae, 0x10, 0x00, 0x8e, 0x02, 0x43, 0x8d,
0x04, 0x43, 0xae, 0x13, 0x00, 0x8e, 0x05, 0x43,
0xa9, 0x01, 0x8d, 0x0b, 0x42, 0x60, 0xe2, 0x20,
0xc2, 0x10, 0x9c, 0x0b, 0x42, 0x9c, 0x0c, 0x42,
0x9c, 0x00, 0x42, 0x60, 0x77, 0x00, 0xee, 0xf2,
0x78, 0x18, 0xfb, 0x5c, 0x3b, 0x00, 0xc0, 0x08,
0xc2, 0x30, 0x48, 0xda, 0x5a, 0x0b, 0x8b, 0x22,
0x35, 0x00, 0xc0, 0xc2, 0x30, 0xab, 0x2b, 0x7a,
0xfa, 0x68, 0x28, 0x40, 0x08, 0xc2, 0x30, 0x48,
0xda, 0x5a, 0x0b, 0x8b, 0x22, 0x00, 0x00, 0xc0,
0xc2, 0x30, 0xab, 0x2b, 0x7a, 0xfa, 0x68, 0x28,
0x40, 0xcb, 0xaf, 0xef, 0xcd, 0xab, 0x80, 0xf9,
0x5b, 0x20, 0x1c, 0x76, 0x30, 0x2e, 0x31, 0x00,
0x00, 0x00, 0x5b, 0x20, 0x41, 0x00, 0x20, 0x3c,
0x64, 0x69, 0x72, 0x3e, 0x5b, 0x00, 0x0d, 0x4d,
0x52, 0x42, 0x4f, 0x4f, 0x54, 0x5b, 0x00, 0x0a,
0x53, 0x44, 0x32, 0x53, 0x4e, 0x45, 0x53, 0x20,
0x42, 0x4f, 0x4f, 0x54, 0x5b, 0x20, 0x09, 0x31,
0x02, 0x06, 0x03, 0x09, 0x33, 0x00, 0x4f, 0x87,
0xb0, 0x78, 0x5b, 0x00, 0x04, 0x31, 0xff, 0x31,
0xff, 0x31, 0xff, 0x1c, 0xff, 0x00, 0x00, 0x07,
0xff, 0x5b, 0x00, 0x04, 0x31, 0xff, 0x00, 0x00,
0x31, 0xff, 0x31, 0xff, 0x00, 0xff, 0x31, 0xff};
0xE2, 0x20, 0xC2, 0x10, 0xA9, 0x00, 0x48, 0xAB, 0xAD,
0x10, 0x42, 0xA2, 0x00, 0x58, 0x8E, 0x16, 0x21, 0xA9,
0x01, 0x8D, 0x15, 0x00, 0xA2, 0x00, 0xB0, 0xA9, 0x7F,
0x8E, 0x10, 0x00, 0x8D, 0x0F, 0x00, 0xA2, 0x00, 0x09,
0x8E, 0x13, 0x00, 0xA9, 0x18, 0x8D, 0x12, 0x00, 0x20,
0xDC, 0x0B, 0xA9, 0x01, 0x8D, 0x16, 0x00, 0x6B, 0xE2,
0x20, 0xAD, 0x11, 0x42, 0x6B, 0xE2, 0x20, 0xC2, 0x10,
0x78, 0x9C, 0x00, 0x42, 0x20, 0x2A, 0x01, 0xA9, 0x01,
0x8D, 0x0D, 0x42, 0x20, 0x84, 0x02, 0x20, 0x93, 0x01,
0x20, 0x8B, 0x01, 0x20, 0x04, 0x0C, 0x20, 0x57, 0x02,
0xA2, 0x41, 0x00, 0xA9, 0x00, 0xCA, 0x9F, 0x00, 0x70,
0x30, 0xD0, 0xF9, 0xA9, 0x7E, 0xA2, 0x1B, 0x00, 0x8D,
0x83, 0x21, 0x8E, 0x81, 0x21, 0xA9, 0x00, 0x8D, 0x15,
0x00, 0xA2, 0xBC, 0x00, 0xA9, 0xC0, 0x8E, 0x10, 0x00,
0x8D, 0x0F, 0x00, 0xA2, 0x6F, 0x00, 0x8E, 0x13, 0x00,
0xA9, 0x80, 0x8D, 0x12, 0x00, 0x20, 0xDC, 0x0B, 0xA9,
0x7E, 0xA2, 0x8B, 0x00, 0x8D, 0x83, 0x21, 0x8E, 0x81,
0x21, 0xA9, 0x00, 0x8D, 0x15, 0x00, 0xA2, 0x8C, 0x0B,
0xA9, 0xC0, 0x8E, 0x10, 0x00, 0x8D, 0x0F, 0x00, 0xA2,
0x4F, 0x00, 0x8E, 0x13, 0x00, 0xA9, 0x80, 0x8D, 0x12,
0x00, 0x20, 0xDC, 0x0B, 0x22, 0x1B, 0x00, 0x7E, 0xC2,
0x10, 0xE2, 0x20, 0xA9, 0x00, 0x8F, 0x00, 0x00, 0x7E,
0xA9, 0x0D, 0x8F, 0x02, 0x00, 0x7E, 0xA9, 0x30, 0x8F,
0x06, 0x00, 0x7E, 0xC2, 0x20, 0xA9, 0x00, 0x70, 0x8F,
0x04, 0x00, 0x7E, 0xE2, 0x20, 0xA9, 0x00, 0x8F, 0x07,
0x00, 0x7E, 0x20, 0x8B, 0x00, 0xC2, 0x20, 0xA9, 0x00,
0x58, 0x8D, 0x16, 0x21, 0xE2, 0x20, 0xA9, 0x01, 0x8D,
0x00, 0x43, 0xA9, 0x18, 0x8D, 0x01, 0x43, 0xA9, 0x7F,
0x8D, 0x04, 0x43, 0xA2, 0x00, 0xB0, 0x8E, 0x02, 0x43,
0xA2, 0x00, 0x09, 0x8E, 0x05, 0x43, 0xAF, 0x12, 0x42,
0x00, 0x29, 0x80, 0xD0, 0xF8, 0xAF, 0x12, 0x42, 0x00,
0x29, 0x80, 0xF0, 0xF8, 0xA9, 0x01, 0x8D, 0x0B, 0x42,
0x80, 0x9A, 0x58, 0x9C, 0x00, 0x42, 0x5C, 0x19, 0x00,
0x7E, 0x9C, 0x0B, 0x42, 0x9C, 0x0C, 0x42, 0x9C, 0x10,
0x43, 0x9C, 0x11, 0x43, 0x9C, 0x12, 0x43, 0x9C, 0x13,
0x43, 0x9C, 0x14, 0x43, 0x9C, 0x20, 0x43, 0x9C, 0x21,
0x43, 0x9C, 0x22, 0x43, 0x9C, 0x23, 0x43, 0x9C, 0x24,
0x43, 0x9C, 0x30, 0x43, 0x9C, 0x31, 0x43, 0x9C, 0x32,
0x43, 0x9C, 0x33, 0x43, 0x9C, 0x34, 0x43, 0x9C, 0x40,
0x43, 0x9C, 0x41, 0x43, 0x9C, 0x42, 0x43, 0x9C, 0x43,
0x43, 0x9C, 0x44, 0x43, 0x9C, 0x50, 0x43, 0x9C, 0x51,
0x43, 0x9C, 0x52, 0x43, 0x9C, 0x53, 0x43, 0x9C, 0x54,
0x43, 0x60, 0xAD, 0x12, 0x42, 0x29, 0x80, 0xD0, 0xF9,
0xAD, 0x12, 0x42, 0x29, 0x80, 0xF0, 0xF9, 0x60, 0xE2,
0x20, 0xC2, 0x10, 0x9C, 0x30, 0x21, 0x60, 0xE2, 0x20,
0xC2, 0x10, 0x9C, 0x00, 0x42, 0x9C, 0x0B, 0x42, 0x9C,
0x0C, 0x42, 0xA2, 0x00, 0xB0, 0x8E, 0x81, 0x21, 0xA9,
0x01, 0x8D, 0x83, 0x21, 0xA9, 0x08, 0x8D, 0x15, 0x00,
0xA2, 0x59, 0xFF, 0xA9, 0xC0, 0x8E, 0x10, 0x00, 0x8D,
0x0F, 0x00, 0xA2, 0x40, 0x07, 0x8E, 0x13, 0x00, 0xA9,
0x80, 0x8D, 0x12, 0x00, 0x20, 0xDC, 0x0B, 0xA2, 0x00,
0x00, 0x8E, 0x16, 0x21, 0xA9, 0x01, 0x8D, 0x15, 0x00,
0xA2, 0x7C, 0x03, 0xA9, 0xC0, 0x8E, 0x10, 0x00, 0x8D,
0x0F, 0x00, 0xA2, 0x00, 0x08, 0x8E, 0x13, 0x00, 0xA9,
0x18, 0x8D, 0x12, 0x00, 0x20, 0xDC, 0x0B, 0xA2, 0x00,
0x58, 0x8E, 0x16, 0x21, 0xA9, 0x09, 0x8D, 0x15, 0x00,
0xA2, 0x59, 0xFF, 0xA9, 0xC0, 0x8E, 0x10, 0x00, 0x8D,
0x0F, 0x00, 0xA2, 0x40, 0x07, 0x8E, 0x13, 0x00, 0xA9,
0x18, 0x8D, 0x12, 0x00, 0x20, 0xDC, 0x0B, 0xA2, 0x00,
0x00, 0x8E, 0x02, 0x21, 0xA9, 0x08, 0x8D, 0x15, 0x00,
0xA2, 0x59, 0xFF, 0xA9, 0xC0, 0x8E, 0x10, 0x00, 0x8D,
0x0F, 0x00, 0xA2, 0x20, 0x02, 0x8E, 0x13, 0x00, 0xA9,
0x04, 0x8D, 0x12, 0x00, 0x20, 0xDC, 0x0B, 0x9C, 0x21,
0x21, 0xA9, 0x00, 0x8D, 0x15, 0x00, 0xA2, 0x7C, 0x0B,
0xA9, 0xC0, 0x8E, 0x10, 0x00, 0x8D, 0x0F, 0x00, 0xA2,
0x10, 0x00, 0x8E, 0x13, 0x00, 0xA9, 0x22, 0x8D, 0x12,
0x00, 0x20, 0xDC, 0x0B, 0x60, 0xE2, 0x20, 0xC2, 0x10,
0xA9, 0x00, 0x8D, 0x05, 0x21, 0xA9, 0x58, 0x09, 0x02,
0x8D, 0x07, 0x21, 0xA9, 0x40, 0x8D, 0x0B, 0x21, 0xA9,
0x01, 0x8D, 0x2C, 0x21, 0xA9, 0x01, 0x8D, 0x2D, 0x21,
0xA9, 0x00, 0x8D, 0x30, 0x21, 0x9C, 0x21, 0x21, 0xA9,
0x0F, 0x8D, 0x00, 0x21, 0x60, 0xE2, 0x20, 0xC2, 0x10,
0x9C, 0x00, 0x42, 0xA9, 0xFF, 0x8D, 0x01, 0x42, 0x9C,
0x02, 0x42, 0x9C, 0x03, 0x42, 0x9C, 0x04, 0x42, 0x9C,
0x05, 0x42, 0x9C, 0x06, 0x42, 0x9C, 0x07, 0x42, 0x9C,
0x08, 0x42, 0x9C, 0x09, 0x42, 0x9C, 0x0A, 0x42, 0x9C,
0x0B, 0x42, 0x9C, 0x0C, 0x42, 0xA9, 0x00, 0x8D, 0x0D,
0x42, 0xA9, 0x8F, 0x8D, 0x00, 0x21, 0xA9, 0x03, 0x8D,
0x01, 0x21, 0x9C, 0x02, 0x21, 0x9C, 0x03, 0x21, 0x9C,
0x05, 0x21, 0x9C, 0x06, 0x21, 0x9C, 0x07, 0x21, 0x9C,
0x08, 0x21, 0x9C, 0x09, 0x21, 0x9C, 0x0A, 0x21, 0x9C,
0x0B, 0x21, 0x9C, 0x0C, 0x21, 0x9C, 0x0D, 0x21, 0x9C,
0x0D, 0x21, 0x9C, 0x0E, 0x21, 0x9C, 0x0E, 0x21, 0x9C,
0x0F, 0x21, 0x9C, 0x0F, 0x21, 0xA9, 0x05, 0x8D, 0x10,
0x21, 0x9C, 0x10, 0x21, 0x9C, 0x11, 0x21, 0x9C, 0x11,
0x21, 0x9C, 0x12, 0x21, 0x9C, 0x12, 0x21, 0x9C, 0x13,
0x21, 0x9C, 0x13, 0x21, 0x9C, 0x14, 0x21, 0x9C, 0x14,
0x21, 0xA9, 0x80, 0x8D, 0x15, 0x21, 0x9C, 0x16, 0x21,
0x9C, 0x17, 0x21, 0x9C, 0x1A, 0x21, 0x9C, 0x1B, 0x21,
0xA9, 0x01, 0x8D, 0x1B, 0x21, 0x9C, 0x1C, 0x21, 0x9C,
0x1C, 0x21, 0x9C, 0x1D, 0x21, 0x9C, 0x1D, 0x21, 0x9C,
0x1E, 0x21, 0x8D, 0x1E, 0x21, 0x9C, 0x1F, 0x21, 0x9C,
0x1F, 0x21, 0x9C, 0x20, 0x21, 0x9C, 0x20, 0x21, 0x9C,
0x21, 0x21, 0x9C, 0x23, 0x21, 0x9C, 0x24, 0x21, 0x9C,
0x25, 0x21, 0x9C, 0x26, 0x21, 0x9C, 0x27, 0x21, 0x9C,
0x28, 0x21, 0x9C, 0x29, 0x21, 0x9C, 0x2A, 0x21, 0x9C,
0x2B, 0x21, 0x9C, 0x2C, 0x21, 0x9C, 0x2D, 0x21, 0x9C,
0x2E, 0x21, 0xA9, 0x30, 0x8D, 0x30, 0x21, 0x9C, 0x31,
0x21, 0xA9, 0xE0, 0x8D, 0x32, 0x21, 0x9C, 0x33, 0x21,
0x60, 0x77, 0x00, 0x11, 0x02, 0x30, 0x30, 0x48, 0x30,
0x48, 0x30, 0x48, 0x20, 0x58, 0x00, 0x30, 0x30, 0x48,
0x00, 0x30, 0x00, 0x6C, 0x6C, 0x92, 0x24, 0x5A, 0x00,
0x36, 0x5B, 0x00, 0x09, 0x6C, 0x6C, 0x92, 0xFE, 0x01,
0x6C, 0x92, 0xFE, 0x01, 0x6C, 0x92, 0x00, 0x6C, 0x00,
0x00, 0x10, 0x6C, 0x7C, 0xC6, 0xC6, 0x39, 0xF0, 0x0E,
0x1E, 0xE1, 0xC6, 0x39, 0x7C, 0xC6, 0x10, 0x6C, 0x42,
0xA5, 0xA4, 0x5A, 0x48, 0xB4, 0x10, 0x6C, 0x24, 0x5A,
0x4A, 0xB5, 0x84, 0x4A, 0x00, 0x84, 0x70, 0xC8, 0xC0,
0x34, 0xC4, 0x2E, 0x6E, 0xDB, 0xC4, 0x2A, 0xC4, 0x3A,
0x7C, 0xC6, 0x00, 0x7C, 0x00, 0x18, 0x18, 0x24, 0x10,
0x28, 0x00, 0x10, 0x5B, 0x00, 0x08, 0x18, 0x24, 0x30,
0x68, 0x30, 0x48, 0x30, 0x48, 0x30, 0x48, 0x30, 0x68,
0x18, 0x24, 0x00, 0x18, 0x30, 0x48, 0x18, 0x2C, 0x18,
0x24, 0x18, 0x24, 0x18, 0x24, 0x18, 0x2C, 0x30, 0x48,
0x00, 0x30, 0x00, 0x6C, 0x6C, 0x92, 0x38, 0x44, 0x7C,
0x82, 0x38, 0x44, 0x6C, 0x92, 0x00, 0x6C, 0x00, 0x00,
0x00, 0x18, 0x18, 0x24, 0x18, 0x66, 0x7E, 0x81, 0x18,
0x66, 0x18, 0x24, 0x00, 0x18, 0x5B, 0x00, 0x0B, 0x18,
0x18, 0x24, 0x18, 0x24, 0x10, 0x28, 0x5B, 0x00, 0x05,
0x7E, 0x7E, 0x81, 0x00, 0x7E, 0x5B, 0x00, 0x0F, 0x18,
0x18, 0x24, 0x18, 0x24, 0x00, 0x18, 0x03, 0x04, 0x06,
0x09, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x90,
0xC0, 0x20, 0x00, 0xC0, 0x7C, 0xC6, 0xE6, 0x39, 0xC6,
0x29, 0xC6, 0x29, 0xC6, 0x29, 0xCE, 0x39, 0x7C, 0xC6,
0x00, 0x7C, 0x18, 0x34, 0x18, 0x24, 0x18, 0x24, 0x18,
0x24, 0x18, 0x24, 0x18, 0x24, 0x18, 0x24, 0x00, 0x18,
0xFC, 0x06, 0x06, 0xF9, 0x06, 0x79, 0x7C, 0x86, 0xC0,
0xBC, 0xC0, 0x3E, 0xFE, 0x01, 0x00, 0xFE, 0xFC, 0x06,
0x06, 0xF9, 0x06, 0x39, 0x3C, 0x46, 0x06, 0x39, 0x06,
0xF9, 0xFC, 0x06, 0x00, 0xFC, 0xC6, 0x29, 0xC6, 0x29,
0xC6, 0x39, 0x7E, 0xC1, 0x06, 0x79, 0x06, 0x09, 0x06,
0x09, 0x00, 0x06, 0xFE, 0x01, 0xC0, 0x3E, 0xC0, 0x3C,
0xFC, 0x06, 0x06, 0xF9, 0x06, 0xF9, 0xFC, 0x06, 0x00,
0xF8, 0x7C, 0xC2, 0xC0, 0x3C, 0xC0, 0x3C, 0xFC, 0x06,
0xC6, 0x39, 0xC6, 0x39, 0x7C, 0xC6, 0x00, 0x7C, 0xFC,
0x06, 0x06, 0xF9, 0x06, 0x09, 0x06, 0x09, 0x06, 0x09,
0x06, 0x09, 0x06, 0x09, 0x00, 0x06, 0x7C, 0xC6, 0xC6,
0x39, 0xC6, 0x39, 0x7C, 0xC6, 0xC6, 0x39, 0xC6, 0x39,
0x7C, 0xC6, 0x00, 0x7C, 0x7C, 0xC6, 0xC6, 0x39, 0xC6,
0x39, 0x7E, 0xC1, 0x06, 0x79, 0x06, 0x79, 0x7C, 0x86,
0x00, 0x7C, 0x00, 0x00, 0x00, 0x30, 0x30, 0x48, 0x00,
0x30, 0x00, 0x30, 0x30, 0x48, 0x00, 0x30, 0x5B, 0x00,
0x05, 0x30, 0x30, 0x48, 0x00, 0x30, 0x00, 0x30, 0x30,
0x48, 0x20, 0x50, 0x00, 0x20, 0x00, 0x18, 0x18, 0x24,
0x30, 0x48, 0x60, 0x90, 0x30, 0x48, 0x18, 0x24, 0x00,
0x18, 0x5B, 0x00, 0x05, 0x3C, 0x3C, 0x42, 0x00, 0x3C,
0x00, 0x3C, 0x3C, 0x42, 0x00, 0x3C, 0x00, 0x00, 0x00,
0x30, 0x30, 0x48, 0x18, 0x24, 0x0C, 0x12, 0x18, 0x24,
0x30, 0x48, 0x00, 0x30, 0x00, 0x00, 0xF8, 0x0C, 0x0C,
0xF2, 0x0C, 0x12, 0x18, 0x24, 0x30, 0x48, 0x00, 0x30,
0x30, 0x48, 0x00, 0x30, 0x7C, 0xC6, 0xC6, 0x39, 0xC6,
0x39, 0xDE, 0x21, 0xDE, 0x21, 0xC0, 0x3E, 0x7E, 0xC1,
0x00, 0x7E, 0x7C, 0xC6, 0xC6, 0x39, 0xC6, 0x39, 0xDE,
0x21, 0xC6, 0x39, 0xC6, 0x29, 0xC6, 0x29, 0x00, 0xC6,
0xFC, 0x06, 0xC6, 0x39, 0xC6, 0x39, 0xDC, 0x26, 0xC6,
0x39, 0xC6, 0x39, 0xFC, 0x06, 0x00, 0xFC, 0x7E, 0xC1,
0xC0, 0x3E, 0xC0, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0xC0,
0x3E, 0x7E, 0xC1, 0x00, 0x7E, 0xFC, 0x02, 0xC6, 0x3B,
0xC6, 0x29, 0xC6, 0x29, 0xC6, 0x29, 0xC6, 0x3B, 0xFC,
0x02, 0x00, 0xFC, 0xFE, 0x01, 0xC0, 0x3E, 0xC0, 0x38,
0xF8, 0x04, 0xC0, 0x38, 0xC0, 0x3E, 0xFE, 0x01, 0x00,
0xFE, 0xFE, 0x01, 0xC0, 0x3E, 0xC0, 0x38, 0xF8, 0x04,
0xC0, 0x38, 0xC0, 0x20, 0xC0, 0x20, 0x00, 0xC0, 0x7E,
0xC1, 0xC0, 0x3E, 0xC0, 0x2E, 0xCE, 0x33, 0xC6, 0x29,
0xC6, 0x39, 0x7C, 0xC6, 0x00, 0x7C, 0xC6, 0x29, 0xC6,
0x29, 0xC6, 0x39, 0xFE, 0x01, 0xC6, 0x39, 0xC6, 0x29,
0xC6, 0x29, 0x00, 0xC6, 0x18, 0x24, 0x18, 0x24, 0x18,
0x24, 0x18, 0x24, 0x18, 0x24, 0x18, 0x24, 0x18, 0x24,
0x00, 0x18, 0x0C, 0x12, 0x0C, 0x12, 0x0C, 0x12, 0x0C,
0x12, 0x0C, 0x12, 0x0C, 0xF6, 0xF8, 0x06, 0x00, 0xFC,
0xC6, 0x29, 0xC6, 0x29, 0xC6, 0x38, 0xFC, 0x06, 0xC6,
0x39, 0xC6, 0x29, 0xC6, 0x29, 0x00, 0xC7, 0xC0, 0x20,
0xC0, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0xC0, 0x20, 0xC0,
0x3C, 0xFC, 0x02, 0x00, 0xFC, 0xEC, 0x16, 0xD6, 0x29,
0xD6, 0x29, 0xD6, 0x29, 0xC6, 0x39, 0xC6, 0x29, 0xC6,
0x29, 0x00, 0xC7, 0xFC, 0x06, 0xC6, 0x39, 0xC6, 0x29,
0xC6, 0x29, 0xC6, 0x29, 0xC6, 0x29, 0xC6, 0x29, 0x00,
0xC6, 0x7C, 0xC6, 0xC6, 0x39, 0xC6, 0x29, 0xC6, 0x29,
0xC6, 0x29, 0xC6, 0x39, 0x7C, 0xC6, 0x00, 0x7C, 0xFC,
0x06, 0xC6, 0x39, 0xC6, 0x29, 0xC6, 0x39, 0xFC, 0x06,
0xC0, 0x3C, 0xC0, 0x20, 0x00, 0xC0, 0x7C, 0x82, 0xC6,
0xBB, 0xC6, 0x29, 0xC6, 0x29, 0xC6, 0x29, 0xCE, 0x31,
0x7E, 0xC1, 0x00, 0x7E, 0xFC, 0x06, 0xC6, 0x39, 0xC6,
0x39, 0xFC, 0x06, 0xC6, 0x39, 0xC6, 0x29, 0xC6, 0x29,
0x00, 0xC6, 0x7E, 0xC1, 0xC0, 0x3E, 0xC0, 0x3C, 0x7C,
0xC6, 0x06, 0x79, 0x06, 0xF9, 0xFC, 0x06, 0x00, 0xFC,
0xFE, 0x01, 0x18, 0xE6, 0x18, 0x24, 0x18, 0x24, 0x18,
0x24, 0x18, 0x24, 0x18, 0x24, 0x00, 0x18, 0xC6, 0x29,
0xC6, 0x29, 0xC6, 0x29, 0xC6, 0x29, 0xC6, 0x29, 0xC6,
0x39, 0x7C, 0xC6, 0x00, 0x7C, 0xC6, 0x29, 0xC6, 0x29,
0xC6, 0x29, 0xC6, 0x29, 0x66, 0x99, 0x36, 0x49, 0x1E,
0x21, 0x00, 0x1F, 0xC6, 0x29, 0xC6, 0x29, 0xC6, 0x39,
0xD6, 0x29, 0xD6, 0x29, 0xD6, 0x29, 0x6E, 0xD1, 0x00,
0x6E, 0xC6, 0x29, 0xC6, 0x29, 0xC6, 0x39, 0x7C, 0xC6,
0xC6, 0x39, 0xC6, 0x29, 0xC6, 0x29, 0x00, 0xC6, 0xC6,
0x29, 0xC6, 0x29, 0xC6, 0x39, 0x7E, 0xC1, 0x06, 0x79,
0x06, 0xF9, 0xFC, 0x06, 0x00, 0xFC, 0xFE, 0x01, 0x06,
0xF9, 0x06, 0x79, 0x7C, 0xC6, 0xC0, 0x3C, 0xC0, 0x3E,
0xFE, 0x01, 0x00, 0xFE, 0x3C, 0x42, 0x30, 0x4C, 0x30,
0x48, 0x30, 0x48, 0x30, 0x48, 0x30, 0x4C, 0x3C, 0x42,
0x00, 0x3C, 0xC0, 0x20, 0x60, 0x90, 0x30, 0x48, 0x18,
0x24, 0x0C, 0x12, 0x06, 0x09, 0x03, 0x04, 0x00, 0x03,
0x3C, 0x42, 0x0C, 0x32, 0x0C, 0x12, 0x0C, 0x12, 0x0C,
0x12, 0x0C, 0x32, 0x3C, 0x42, 0x00, 0x3C, 0x18, 0x24,
0x3C, 0x66, 0x66, 0x99, 0x00, 0x66, 0x5B, 0x00, 0x13,
0x7E, 0x7E, 0x81, 0x00, 0x7E, 0x30, 0x48, 0x18, 0x24,
0x18, 0x24, 0x00, 0x18, 0x5B, 0x00, 0x0B, 0x7C, 0x7C,
0x86, 0x06, 0x79, 0x7E, 0xC1, 0xC6, 0x39, 0x7E, 0xC1,
0x00, 0x7E, 0xC0, 0x20, 0xC0, 0x3C, 0xFC, 0x06, 0xC6,
0x39, 0xC6, 0x29, 0xC6, 0x39, 0xFC, 0x06, 0x00, 0xFC,
0x00, 0x00, 0x00, 0x7E, 0x7E, 0xC1, 0xC0, 0x3E, 0xC0,
0x20, 0xC0, 0x3E, 0x7E, 0xC1, 0x00, 0x7E, 0x06, 0x09,
0x06, 0x79, 0x7E, 0xC1, 0xC6, 0x39, 0xC6, 0x29, 0xC6,
0x39, 0x7E, 0xC1, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x7C,
0x7C, 0xC6, 0xC6, 0x39, 0xFE, 0x01, 0xC0, 0x3E, 0x7E,
0xC3, 0x00, 0x7E, 0x1E, 0x21, 0x30, 0x6E, 0x30, 0x4C,
0x3C, 0x42, 0x30, 0x4C, 0x30, 0x48, 0x30, 0x48, 0x30,
0x48, 0x00, 0x00, 0x00, 0x7E, 0x7E, 0xC1, 0xC6, 0x39,
0xC6, 0x39, 0x7E, 0xC1, 0x06, 0x79, 0x7C, 0x86, 0xC0,
0x20, 0xC0, 0x3C, 0xFC, 0x06, 0xC6, 0x39, 0xC6, 0x29,
0xC6, 0x29, 0xC6, 0x29, 0x00, 0xC6, 0x00, 0x18, 0x18,
0x24, 0x00, 0x18, 0x18, 0x24, 0x18, 0x24, 0x18, 0x24,
0x18, 0x24, 0x00, 0x18, 0x00, 0x18, 0x18, 0x24, 0x00,
0x18, 0x18, 0x24, 0x18, 0x24, 0x18, 0x24, 0x18, 0x2C,
0x30, 0x48, 0xC0, 0x20, 0xC0, 0x26, 0xC6, 0x29, 0xC6,
0x2B, 0xFC, 0x06, 0xC6, 0x2B, 0xC6, 0x29, 0x00, 0xC7,
0x30, 0x48, 0x30, 0x48, 0x30, 0x48, 0x30, 0x48, 0x30,
0x48, 0x30, 0x68, 0x18, 0x24, 0x00, 0x1C, 0x00, 0x00,
0x00, 0xEC, 0xEC, 0x16, 0xD6, 0x29, 0xD6, 0x29, 0xD6,
0x29, 0xC6, 0x39, 0x00, 0xC7, 0x00, 0x00, 0x00, 0xFC,
0xFC, 0x06, 0xC6, 0x39, 0xC6, 0x29, 0xC6, 0x29, 0xC6,
0x29, 0x00, 0xC6, 0x00, 0x00, 0x00, 0x7C, 0x7C, 0xC6,
0xC6, 0x39, 0xC6, 0x29, 0xC6, 0x39, 0x7C, 0xC6, 0x00,
0x7C, 0x00, 0x00, 0x00, 0xFC, 0xFC, 0x06, 0xC6, 0x39,
0xC6, 0x39, 0xFC, 0x06, 0xC0, 0x3C, 0xC0, 0x20, 0x00,
0x00, 0x00, 0x7E, 0x7E, 0xC1, 0xC6, 0x39, 0xC6, 0x39,
0x7E, 0xC1, 0x06, 0x79, 0x06, 0x09, 0x00, 0x00, 0x00,
0x7C, 0x7C, 0xC2, 0xC0, 0x3C, 0xC0, 0x20, 0xC0, 0x20,
0xC0, 0x20, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x7E, 0x7E,
0xC1, 0xC0, 0x3E, 0x7C, 0xC6, 0x06, 0xF9, 0xFC, 0x06,
0x00, 0xFC, 0x30, 0x48, 0x30, 0x4C, 0x3C, 0x42, 0x30,
0x4C, 0x30, 0x48, 0x30, 0x4E, 0x1E, 0x31, 0x00, 0x1E,
0x00, 0x00, 0x00, 0xC6, 0xC6, 0x29, 0xC6, 0x29, 0xC6,
0x29, 0xC6, 0x39, 0x7C, 0xC6, 0x00, 0x7C, 0x00, 0x00,
0x00, 0xC6, 0xC6, 0x29, 0xC6, 0x29, 0x66, 0x99, 0x36,
0x49, 0x1E, 0x21, 0x00, 0x1E, 0x00, 0x00, 0x00, 0xC6,
0xC6, 0x39, 0xD6, 0x29, 0xD6, 0x29, 0xD6, 0x29, 0x6E,
0xD1, 0x00, 0x6E, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0x29,
0xC6, 0x39, 0x7C, 0xC6, 0xC6, 0x39, 0xC6, 0x29, 0x00,
0xC6, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0x29, 0xC6, 0x39,
0x7E, 0xC1, 0x06, 0x79, 0x06, 0xF9, 0xFC, 0x06, 0x00,
0x00, 0x00, 0xFE, 0xFE, 0x01, 0x06, 0xF9, 0x7C, 0xC6,
0xC0, 0x3E, 0xFE, 0x01, 0x00, 0xFE, 0x18, 0x24, 0x30,
0x48, 0x30, 0x48, 0x70, 0x88, 0x30, 0x48, 0x30, 0x48,
0x18, 0x24, 0x00, 0x18, 0x18, 0x24, 0x18, 0x24, 0x18,
0x24, 0x00, 0x18, 0x18, 0x24, 0x18, 0x24, 0x18, 0x24,
0x00, 0x18, 0x30, 0x48, 0x18, 0x24, 0x18, 0x24, 0x1C,
0x22, 0x18, 0x24, 0x18, 0x24, 0x30, 0x48, 0x00, 0x30,
0x00, 0x00, 0x00, 0x72, 0x72, 0x9D, 0xFE, 0x01, 0x9C,
0x72, 0x00, 0x9C, 0x5B, 0x00, 0x14, 0x42, 0x08, 0xFF,
0x7F, 0x00, 0x00, 0x9C, 0x73, 0x42, 0x08, 0xFF, 0x43,
0x00, 0x00, 0x18, 0x63, 0xC2, 0x30, 0xAD, 0x00, 0x00,
0x29, 0xFF, 0x00, 0x0A, 0x18, 0x69, 0x00, 0xB0, 0x8D,
0x09, 0x00, 0xAD, 0x02, 0x00, 0x29, 0xFF, 0x00, 0x5B,
0x0A, 0x06, 0x18, 0x6D, 0x09, 0x00, 0x8F, 0x81, 0x21,
0x00, 0xE2, 0x20, 0xA9, 0x7F, 0x8F, 0x83, 0x21, 0x00,
0xAE, 0x04, 0x00, 0xAD, 0x06, 0x00, 0x48, 0xAB, 0xBD,
0x00, 0x00, 0xF0, 0x11, 0x8F, 0x80, 0x21, 0x00, 0xA9,
0x00, 0x69, 0x00, 0x09, 0x20, 0x8F, 0x80, 0x21, 0x00,
0xE8, 0x80, 0xEA, 0xA9, 0x00, 0x48, 0xAB, 0x60, 0xFF,
0xC2, 0x10, 0xE2, 0x20, 0xAD, 0x15, 0x00, 0x8D, 0x00,
0x43, 0xAD, 0x12, 0x00, 0x8D, 0x01, 0x43, 0xAD, 0x0F,
0x00, 0xAE, 0x10, 0x00, 0x8E, 0x02, 0x43, 0x8D, 0x04,
0x43, 0xAE, 0x13, 0x00, 0x8E, 0x05, 0x43, 0xA9, 0x01,
0x8D, 0x0B, 0x42, 0x60, 0xE2, 0x20, 0xC2, 0x10, 0x9C,
0x0B, 0x42, 0x9C, 0x0C, 0x42, 0x9C, 0x00, 0x42, 0x60,
0x77, 0x00, 0xEE, 0xF2, 0x78, 0x18, 0xFB, 0x5C, 0x3B,
0x00, 0xC0, 0x08, 0xC2, 0x30, 0x48, 0xDA, 0x5A, 0x0B,
0x8B, 0x22, 0x35, 0x00, 0xC0, 0xC2, 0x30, 0xAB, 0x2B,
0x7A, 0xFA, 0x68, 0x28, 0x40, 0x08, 0xC2, 0x30, 0x48,
0xDA, 0x5A, 0x0B, 0x8B, 0x22, 0x00, 0x00, 0xC0, 0xC2,
0x30, 0xAB, 0x2B, 0x7A, 0xFA, 0x68, 0x28, 0x40, 0xCB,
0xAF, 0xEF, 0xCD, 0xAB, 0x80, 0xF9, 0x5B, 0x20, 0x1C,
0x76, 0x30, 0x2E, 0x31, 0x00, 0x00, 0x00, 0x5B, 0x20,
0x41, 0x00, 0x20, 0x3C, 0x64, 0x69, 0x72, 0x3E, 0x5B,
0x00, 0x0D, 0x4D, 0x52, 0x42, 0x4F, 0x4F, 0x54, 0x5B,
0x00, 0x0A, 0x53, 0x44, 0x32, 0x53, 0x4E, 0x45, 0x53,
0x20, 0x42, 0x4F, 0x4F, 0x54, 0x5B, 0x20, 0x09, 0x31,
0x02, 0x06, 0x03, 0x09, 0x33, 0x00, 0x4F, 0x87, 0xB0,
0x78, 0x5B, 0x00, 0x04, 0x31, 0xFF, 0x31, 0xFF, 0x31,
0xFF, 0x1C, 0xFF, 0x00, 0x00, 0x07, 0xFF, 0x5B, 0x00,
0x04, 0x31, 0xFF, 0x00, 0x00, 0x31, 0xFF, 0x31, 0xFF,
0x00, 0xFF, 0x31, 0xFF, 0xFF,
};

View File

@@ -15,93 +15,135 @@
*/
uint32_t stat_getstring = 0;
static char sort_str1[21], sort_str2[21];
static char sort_str1[SORT_STRLEN + 1], sort_str2[SORT_STRLEN + 1];
uint32_t ptrcache[QSORT_MAXELEM] IN_AHBRAM;
/* get element from pointer table in external RAM*/
uint32_t sort_get_elem(uint32_t base, unsigned int index) {
uint32_t sort_get_elem( uint32_t base, unsigned int index )
{
return sram_readlong( base + 4 * index );
}
/* put element from pointer table in external RAM */
void sort_put_elem(uint32_t base, unsigned int index, uint32_t elem) {
void sort_put_elem( uint32_t base, unsigned int index, uint32_t elem )
{
sram_writelong( elem, base + 4 * index );
}
/* compare strings pointed to by elements of pointer table */
int sort_cmp_idx(uint32_t base, unsigned int index1, unsigned int index2) {
int sort_cmp_idx( uint32_t base, unsigned int index1, unsigned int index2 )
{
uint32_t elem1, elem2;
elem1 = sort_get_elem( base, index1 );
elem2 = sort_get_elem( base, index2 );
return sort_cmp_elem( ( void * )&elem1, ( void * )&elem2 );
}
int sort_cmp_elem(const void* elem1, const void* elem2) {
int sort_cmp_elem( const void *elem1, const void *elem2 )
{
uint32_t el1 = *( uint32_t * )elem1;
uint32_t el2 = *( uint32_t * )elem2;
sort_getstring_for_dirent( sort_str1, el1 );
sort_getstring_for_dirent( sort_str2, el2 );
/*printf("i1=%d i2=%d elem1=%lx elem2=%lx ; compare %s --- %s\n", index1, index2, elem1, elem2, sort_str1, sort_str2); */
if ((el1 & 0x80000000) && !(el2 & 0x80000000)) {
if ( ( el1 & 0x80000000 ) && !( el2 & 0x80000000 ) )
{
return -1;
}
if (!(el1 & 0x80000000) && (el2 & 0x80000000)) {
if ( !( el1 & 0x80000000 ) && ( el2 & 0x80000000 ) )
{
return 1;
}
/*
uint16_t cmp_i;
for(cmp_i=0; cmp_i<8 && sort_long1[cmp_i] == sort_long2[cmp_i]; cmp_i++);
if(cmp_i==8) {
return 0;
if ( *sort_str1 == '.' )
{
return -1;
}
return sort_long1[cmp_i]-sort_long2[cmp_i]; */
if ( *sort_str2 == '.' )
{
return 1;
}
/* Do not compare trailing slashes of directory names */
if ( ( el1 & 0x80000000 ) && ( el2 & 0x80000000 ) )
{
char *str1_slash = strrchr( sort_str1, '/' );
char *str2_slash = strrchr( sort_str2, '/' );
if ( str1_slash != NULL )
{
*str1_slash = 0;
}
if ( str2_slash != NULL )
{
*str2_slash = 0;
}
}
return strcasecmp( sort_str1, sort_str2 );
}
/* get truncated string from database */
void sort_getstring_for_dirent(char *ptr, uint32_t addr) {
void sort_getstring_for_dirent( char *ptr, uint32_t addr )
{
uint8_t leaf_offset;
if(addr & 0x80000000) {
if ( addr & 0x80000000 )
{
/* is directory link, name offset 4 */
leaf_offset = sram_readbyte( addr + 4 + SRAM_MENU_ADDR );
sram_readblock(ptr, addr + 5 + leaf_offset + SRAM_MENU_ADDR, 20);
} else {
sram_readstrn( ptr, addr + 5 + leaf_offset + SRAM_MENU_ADDR, SORT_STRLEN );
}
else
{
/* is file link, name offset 6 */
leaf_offset = sram_readbyte( addr + 6 + SRAM_MENU_ADDR );
sram_readblock(ptr, addr + 7 + leaf_offset + SRAM_MENU_ADDR, 20);
sram_readstrn( ptr, addr + 7 + leaf_offset + SRAM_MENU_ADDR, SORT_STRLEN );
}
ptr[20]=0;
}
void sort_heapify( uint32_t addr, unsigned int i, unsigned int heapsize )
{
while(1) {
while ( 1 )
{
unsigned int l = 2 * i + 1;
unsigned int r = 2 * i + 2;
unsigned int largest = ( l < heapsize && sort_cmp_idx( addr, i, l ) < 0 ) ? l : i;
if ( r < heapsize && sort_cmp_idx( addr, largest, r ) < 0 )
{
largest = r;
}
if(largest != i) {
if ( largest != i )
{
uint32_t tmp = sort_get_elem( addr, i );
sort_put_elem( addr, i, sort_get_elem( addr, largest ) );
sort_put_elem( addr, largest, tmp );
i = largest;
}
else break;
else
{
break;
}
}
}
void sort_dir( uint32_t addr, unsigned int size )
{
stat_getstring = 0;
if(size > QSORT_MAXELEM) {
if ( size > QSORT_MAXELEM )
{
printf( "more than %d dir entries, doing slower in-place sort\n", QSORT_MAXELEM );
ext_heapsort( addr, size );
} else {
}
else
{
/* retrieve, sort, and store dir table */
sram_readblock( ptrcache, addr, size * 4 );
qsort( ( void * )ptrcache, size, 4, sort_cmp_elem );
@@ -109,10 +151,15 @@ stat_getstring=0;
}
}
void ext_heapsort(uint32_t addr, unsigned int size) {
for(unsigned int i = size/2; i > 0;) sort_heapify(addr, --i, size);
void ext_heapsort( uint32_t addr, unsigned int size )
{
for ( unsigned int i = size / 2; i > 0; )
{
sort_heapify( addr, --i, size );
}
for(unsigned int i = size-1; i>0; --i) {
for ( unsigned int i = size - 1; i > 0; --i )
{
uint32_t tmp = sort_get_elem( addr, 0 );
sort_put_elem( addr, 0, sort_get_elem( addr, i ) );
sort_put_elem( addr, i, tmp );

View File

@@ -30,27 +30,20 @@
#include "spi.h"
#include "uart.h"
void spi_preinit() {
void spi_preinit()
{
/* Set clock prescaler to 1:1 */
BITBAND( LPC_SC->SSP_PCLKREG, SSP_PCLKBIT ) = 1;
}
void spi_init(spi_speed_t speed) {
void spi_init()
{
/* configure data format - 8 bits, SPI, CPOL=0, CPHA=0, 1 clock per bit */
SSP_REGS->CR0 = ( 8 - 1 );
/* set clock prescaler */
if (speed == SPI_SPEED_FAST) {
SSP_REGS->CPSR = SSP_CLK_DIVISOR_FAST;
} else if (speed == SPI_SPEED_SLOW) {
SSP_REGS->CPSR = SSP_CLK_DIVISOR_SLOW;
} else if (speed == SPI_SPEED_FPGA_FAST) {
SSP_REGS->CPSR = SSP_CLK_DIVISOR_FPGA_FAST;
} else {
SSP_REGS->CPSR = SSP_CLK_DIVISOR_FPGA_SLOW;
}
SSP_REGS->CPSR = SSP_CLK_DIVISOR;
/* Enable SSP */
SSP_REGS->CR1 = BV( 1 );
@@ -60,12 +53,14 @@ void spi_init(spi_speed_t speed) {
LPC_GPDMA->DMACConfig = 1;
}
void spi_tx_sync() {
void spi_tx_sync()
{
/* Wait until TX fifo is flushed */
while ( BITBAND( SSP_REGS->SR, SSP_BSY ) ) ;
}
void spi_tx_byte(uint8_t data) {
void spi_tx_byte( uint8_t data )
{
/* Wait until TX fifo can accept data */
while ( !BITBAND( SSP_REGS->SR, SSP_TNF ) ) ;
@@ -73,13 +68,16 @@ void spi_tx_byte(uint8_t data) {
SSP_REGS->DR = data;
}
uint8_t spi_txrx_byte(uint8_t data) {
uint8_t spi_txrx_byte( uint8_t data )
{
/* Wait until SSP is not busy */
while ( BITBAND( SSP_REGS->SR, SSP_BSY ) ) ;
/* Clear RX fifo */
while ( BITBAND( SSP_REGS->SR, SSP_RNE ) )
{
( void ) SSP_REGS->DR;
}
/* Transmit a single byte */
SSP_REGS->DR = data;
@@ -90,13 +88,16 @@ uint8_t spi_txrx_byte(uint8_t data) {
return SSP_REGS->DR;
}
uint8_t spi_rx_byte() {
uint8_t spi_rx_byte()
{
/* Wait until SSP is not busy */
while ( BITBAND( SSP_REGS->SR, SSP_BSY ) ) ;
/* Clear RX fifo */
while ( BITBAND( SSP_REGS->SR, SSP_RNE ) )
{
( void ) SSP_REGS->DR;
}
/* Transmit a single dummy byte */
SSP_REGS->DR = 0xff;
@@ -107,10 +108,12 @@ uint8_t spi_rx_byte() {
return SSP_REGS->DR;
}
void spi_tx_block(const void *ptr, unsigned int length) {
void spi_tx_block( const void *ptr, unsigned int length )
{
const uint8_t *data = ( const uint8_t * )ptr;
while (length--) {
while ( length-- )
{
/* Wait until TX fifo can accept data */
while ( !BITBAND( SSP_REGS->SR, SSP_TNF ) ) ;
@@ -118,7 +121,8 @@ void spi_tx_block(const void *ptr, unsigned int length) {
}
}
void spi_rx_block(void *ptr, unsigned int length) {
void spi_rx_block( void *ptr, unsigned int length )
{
uint8_t *data = ( uint8_t * )ptr;
unsigned int txlen = length;
@@ -127,28 +131,36 @@ void spi_rx_block(void *ptr, unsigned int length) {
/* Clear RX fifo */
while ( BITBAND( SSP_REGS->SR, SSP_RNE ) )
{
( void ) SSP_REGS->DR;
}
if ((length & 3) != 0 || ((uint32_t)ptr & 3) != 0) {
if ( ( length & 3 ) != 0 || ( ( uint32_t )ptr & 3 ) != 0 )
{
/* Odd length or unaligned buffer */
while (length > 0) {
while ( length > 0 )
{
/* Wait until TX or RX FIFO are ready */
while ( txlen > 0 && !BITBAND( SSP_REGS->SR, SSP_TNF ) &&
!BITBAND( SSP_REGS->SR, SSP_RNE ) ) ;
/* Try to receive data */
while (length > 0 && BITBAND(SSP_REGS->SR, SSP_RNE)) {
while ( length > 0 && BITBAND( SSP_REGS->SR, SSP_RNE ) )
{
*data++ = SSP_REGS->DR;
length--;
}
/* Send dummy data until TX full or RX ready */
while (txlen > 0 && BITBAND(SSP_REGS->SR, SSP_TNF) && !BITBAND(SSP_REGS->SR, SSP_RNE)) {
while ( txlen > 0 && BITBAND( SSP_REGS->SR, SSP_TNF ) && !BITBAND( SSP_REGS->SR, SSP_RNE ) )
{
txlen--;
SSP_REGS->DR = 0xff;
}
}
} else {
}
else
{
/* Clear interrupt flags of DMA channels 0 */
LPC_GPDMA->DMACIntTCClear = BV( 0 );
LPC_GPDMA->DMACIntErrClr = BV( 0 );
@@ -175,8 +187,10 @@ void spi_rx_block(void *ptr, unsigned int length) {
/* Write <length> bytes into TX FIFO */
// FIXME: Any value in doing this using DMA too?
while (txlen > 0) {
while (txlen > 0 && BITBAND(SSP_REGS->SR, SSP_TNF)) {
while ( txlen > 0 )
{
while ( txlen > 0 && BITBAND( SSP_REGS->SR, SSP_TNF ) )
{
txlen--;
SSP_REGS->DR = 0xff;
}
@@ -189,25 +203,3 @@ void spi_rx_block(void *ptr, unsigned int length) {
SSP_REGS->DMACR = 0;
}
}
void spi_set_speed(spi_speed_t speed) {
/* Wait until TX fifo is empty */
while (!BITBAND(SSP_REGS->SR, 0)) ;
/* Disable SSP (FIXME: Is this required?) */
SSP_REGS->CR1 = 0;
/* Change clock divisor */
if (speed == SPI_SPEED_FAST) {
SSP_REGS->CPSR = SSP_CLK_DIVISOR_FAST;
} else if (speed == SPI_SPEED_SLOW) {
SSP_REGS->CPSR = SSP_CLK_DIVISOR_SLOW;
} else if (speed == SPI_SPEED_FPGA_FAST) {
SSP_REGS->CPSR = SSP_CLK_DIVISOR_FPGA_FAST;
} else {
SSP_REGS->CPSR = SSP_CLK_DIVISOR_FPGA_SLOW;
}
/* Enable SSP */
SSP_REGS->CR1 = BV(1);
}

View File

@@ -42,7 +42,7 @@ typedef enum { SPI_SPEED_FAST, SPI_SPEED_SLOW, SPI_SPEED_FPGA_FAST, SPI_SPEED_FP
void spi_preinit( void );
/* Initialize SPI interface */
void spi_init(spi_speed_t speed);
void spi_init( void );
/* Transmit a single byte */
void spi_tx_byte( uint8_t data );
@@ -59,9 +59,6 @@ uint8_t spi_rx_byte(void);
/* Receive a data block */
void spi_rx_block( void *data, unsigned int length );
/* Switch speed of SPI interface */
void spi_set_speed(spi_speed_t speed);
/* wait for SPI TX FIFO to become empty */
void spi_tx_sync( void );

155
src/sysinfo.c Normal file
View File

@@ -0,0 +1,155 @@
#include <arm/NXP/LPC17xx/LPC17xx.h>
#include <arm/bits.h>
#include <string.h>
#include "config.h"
#include "diskio.h"
#include "ff.h"
#include "timer.h"
#include "uart.h"
#include "fileops.h"
#include "memory.h"
#include "snes.h"
#include "fpga.h"
#include "fpga_spi.h"
#include "cic.h"
#include "sdnative.h"
#include "sysinfo.h"
static uint32_t sd_tacc_max, sd_tacc_avg;
void sysinfo_loop()
{
sd_tacc_max = 0;
sd_tacc_avg = 0;
while ( sram_readbyte( SRAM_CMD_ADDR ) != 0x00 )
{
write_sysinfo();
delay_ms( 100 );
}
}
void write_sysinfo()
{
uint32_t sram_addr = SRAM_SYSINFO_ADDR;
char linebuf[40];
int len;
int sd_ok = 0;
uint8_t *sd_cid = sdn_getcid();
uint32_t sd_tacc_max_int = sd_tacc_max / 1000;
uint32_t sd_tacc_max_frac = sd_tacc_max - ( sd_tacc_max_int * 1000 );
uint32_t sd_tacc_avg_int = sd_tacc_avg / 1000;
uint32_t sd_tacc_avg_frac = sd_tacc_avg - ( sd_tacc_avg_int * 1000 );
uint16_t numfiles = sram_readshort( SRAM_DB_ADDR + 12 );
uint16_t numdirs = sram_readshort( SRAM_DB_ADDR + 14 );
int32_t sysclk = get_snes_sysclk();
len = snprintf( linebuf, sizeof( linebuf ), "Firmware version: %s", CONFIG_VERSION );
sram_writeblock( linebuf, sram_addr, 40 );
sram_memset( sram_addr + len, 40 - len, 0x20 );
sram_addr += 40;
len = snprintf( linebuf, sizeof( linebuf ), " " );
sram_writeblock( linebuf, sram_addr, 40 );
sram_memset( sram_addr + len, 40 - len, 0x20 );
sram_addr += 40;
if ( disk_state == DISK_REMOVED )
{
sd_tacc_max = 0;
sd_tacc_avg = 0;
len = snprintf( linebuf, sizeof( linebuf ), " " );
sram_writeblock( linebuf, sram_addr, 40 );
sram_memset( sram_addr + len, 40 - len, 0x20 );
sram_addr += 40;
len = snprintf( linebuf, sizeof( linebuf ), " *** SD Card removed *** " );
sram_writeblock( linebuf, sram_addr, 40 );
sram_memset( sram_addr + len, 40 - len, 0x20 );
sram_addr += 40;
len = snprintf( linebuf, sizeof( linebuf ), " " );
sram_writeblock( linebuf, sram_addr, 40 );
sram_memset( sram_addr + len, 40 - len, 0x20 );
sram_addr += 40;
len = snprintf( linebuf, sizeof( linebuf ), " " );
sram_writeblock( linebuf, sram_addr, 40 );
sram_memset( sram_addr + len, 40 - len, 0x20 );
sram_addr += 40;
sd_ok = 0;
}
else
{
len = snprintf( linebuf, sizeof( linebuf ), "SD Maker/OEM: 0x%02x, \"%c%c\"", sd_cid[1], sd_cid[2], sd_cid[3] );
sram_writeblock( linebuf, sram_addr, 40 );
sram_memset( sram_addr + len, 40 - len, 0x20 );
sram_addr += 40;
len = snprintf( linebuf, sizeof( linebuf ), "SD Product Name: \"%c%c%c%c%c\", Rev. %d.%d", sd_cid[4], sd_cid[5],
sd_cid[6], sd_cid[7], sd_cid[8], sd_cid[9] >> 4, sd_cid[9] & 15 );
sram_writeblock( linebuf, sram_addr, 40 );
sram_memset( sram_addr + len, 40 - len, 0x20 );
sram_addr += 40;
len = snprintf( linebuf, sizeof( linebuf ), "SD Serial No.: %02x%02x%02x%02x, Mfd. %d/%02d", sd_cid[10], sd_cid[11],
sd_cid[12], sd_cid[13], 2000 + ( ( sd_cid[14] & 15 ) << 4 ) + ( sd_cid[15] >> 4 ), sd_cid[15] & 15 );
sram_writeblock( linebuf, sram_addr, 40 );
sram_memset( sram_addr + len, 40 - len, 0x20 );
sram_addr += 40;
if ( sd_tacc_max )
{
len = snprintf( linebuf, sizeof( linebuf ), "SD acc. time: %ld.%03ld / %ld.%03ld ms avg/max", sd_tacc_avg_int,
sd_tacc_avg_frac, sd_tacc_max_int, sd_tacc_max_frac );
}
else
{
len = snprintf( linebuf, sizeof( linebuf ), "SD acc. time: measuring... " );
}
sram_writeblock( linebuf, sram_addr, 40 );
sram_memset( sram_addr + len, 40 - len, 0x20 );
sram_addr += 40;
sd_ok = 1;
}
len = snprintf( linebuf, sizeof( linebuf ), " " );
sram_writeblock( linebuf, sram_addr, 40 );
sram_memset( sram_addr + len, 40 - len, 0x20 );
sram_addr += 40;
len = snprintf( linebuf, sizeof( linebuf ), "CIC state: %s", get_cic_statefriendlyname( get_cic_state() ) );
sram_writeblock( linebuf, sram_addr, 40 );
sram_memset( sram_addr + len, 40 - len, 0x20 );
sram_addr += 40;
if ( sysclk == -1 )
{
len = snprintf( linebuf, sizeof( linebuf ), "SNES master clock: measuring..." );
}
else
{
len = snprintf( linebuf, sizeof( linebuf ), "SNES master clock: %ldHz ", get_snes_sysclk() );
}
sram_writeblock( linebuf, sram_addr, 40 );
sram_memset( sram_addr + len, 40 - len, 0x20 );
sram_addr += 40;
len = snprintf( linebuf, sizeof( linebuf ), " " );
sram_writeblock( linebuf, sram_addr, 40 );
sram_memset( sram_addr + len, 40 - len, 0x20 );
sram_addr += 40;
len = snprintf( linebuf, sizeof( linebuf ), "Database: %d files, %d dirs", numfiles, numdirs );
sram_writeblock( linebuf, sram_addr, 40 );
sram_memset( sram_addr + len, 40 - len, 0x20 );
sram_addr += 40;
len = snprintf( linebuf, sizeof( linebuf ), " " );
sram_writeblock( linebuf, sram_addr, 40 );
sram_memset( sram_addr + len, 40 - len, 0x20 );
sram_addr += 40;
len = snprintf( linebuf, sizeof( linebuf ), " " );
sram_writeblock( linebuf, sram_addr, 40 );
sram_memset( sram_addr + len, 40 - len, 0x20 );
sram_hexdump( SRAM_SYSINFO_ADDR, 13 * 40 );
if ( sysclk != -1 && sd_ok )
{
sdn_gettacc( &sd_tacc_max, &sd_tacc_avg );
}
}

7
src/sysinfo.h Normal file
View File

@@ -0,0 +1,7 @@
#ifndef _SYSINFO_H
#define _SYSINFO_H
void write_sysinfo(void);
void sysinfo_loop(void);
#endif

View File

@@ -7,5 +7,6 @@ void test_sdbench_local(char *filename);
void test_rom_rw(void);
void test_fpga_echo(void);
int test_mem(void);
#endif

View File

@@ -138,7 +138,8 @@ CFLAGS += $(CDEFS) $(CINCS)
CFLAGS += -O$(OPT)
CFLAGS += $(CPUFLAGS) -nostartfiles
#CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
CFLAGS += -Wall -Wstrict-prototypes -Werror
CFLAGS += -Wall -Wstrict-prototypes
# -Werror
CFLAGS += -Wa,-adhlns=$(OBJDIR)/$(<:.c=.lst)
CFLAGS += -I$(OBJDIR)
CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))

View File

@@ -38,7 +38,8 @@
//#define CONFIG_CPU_FREQUENCY 46000000
#define CONFIG_UART_PCLKDIV 1
#define CONFIG_UART_TX_BUF_SHIFT 8
#define CONFIG_UART_BAUDRATE 921600
//#define CONFIG_UART_BAUDRATE 921600
#define CONFIG_UART_BAUDRATE 115200
#define CONFIG_UART_DEADLOCKABLE
#define SSP_CLK_DIVISOR_FAST 2

View File

@@ -101,9 +101,9 @@ led_pwm();
testresults[TEST_SD] = test_sd();
//testresults[TEST_USB] = test_usb();
testresults[TEST_RTC] = test_rtc();
//testresults[TEST_RTC] = test_rtc();
delay_ms(209);
testresults[TEST_CIC] = test_cic();
// testresults[TEST_CIC] = test_cic();
testresults[TEST_FPGA] = test_fpga();
testresults[TEST_RAM] = test_mem();
printf("Loading SNES test ROM\n=====================\n");

Some files were not shown because too many files have changed in this diff Show More