12 | typedef unsigned __int64 QWORD;
13 |
14 |
15 | #else /* Embedded platform */
16 |
17 | /* These types MUST be 16-bit or 32-bit */
18 | typedef int INT;
19 | typedef unsigned int UINT;
20 |
21 | /* This type MUST be 8-bit */
22 | typedef unsigned char BYTE;
23 |
24 | /* These types MUST be 16-bit */
25 | typedef short SHORT;
26 | typedef unsigned short WORD;
27 | typedef unsigned short WCHAR;
28 |
29 | /* These types MUST be 32-bit */
30 | typedef long LONG;
31 | typedef unsigned long DWORD;
32 |
33 | /* This type MUST be 64-bit (Remove this for ANSI C (C89) compatibility) */
34 | typedef unsigned long long QWORD;
35 |
36 | #endif
37 |
38 | #endif
39 |
--------------------------------------------------------------------------------
/inc/localevar.h:
--------------------------------------------------------------------------------
1 | //language
2 | char *dirempty;
3 | char *fnddb;
4 | char *done;
5 | char *romloaded;
6 | char *loadgb;
7 | char *loading;
8 | char *plgmp3;
9 | char *savemem;
10 | char *save32;
11 | char *save128;
12 | char *save768;
13 | char *save4k;
14 | char *save16k;
15 | char *saveflash;
16 | char *OpComsucc;
17 | char *mpksub;
18 | char *viewcont;
19 | char *viewmpk;
20 | char *backnew;
21 | char *formatt;
22 | char *abortmen;
23 | char *restoreback;
24 | char *confreq;
25 | char *aresure;
26 | char *cupcont;
27 | char *cancelmenu;
28 | char *romconfig;
29 | char *updatelastgamerecord;
30 | char *ramarea2sd;
31 | char *cpyingram2SD;
32 | char *transfersavedat;
33 | char *tvforceoff;
34 | char *cheatoff;
35 | char *cheaton;
36 | char *checksumenable;
37 | char *checksumdisable;
38 | char *presstart;
39 | char *reallyformatrpak;
40 | char *searchfds;
41 | char *formating;
42 | char *mpkformat;
43 | char *plswait;
44 | char *errorformating;
45 | char *ratoff;
46 | char *ratcomo;
47 | char *ratuncomo;
48 | char *ratrare;
49 | char *ratepic;
50 | char *ratlegend;
51 | char *bcancel;
52 | char *countrydef;
53 | char *countryntsc;
54 | char *countrypal;
55 | char *Asaveconf;
56 | char *directoriesNO;
57 | char *bexit;
58 | char *deletefile;
59 | char *aconfirm;
60 | char *znpage;
61 | char *fcontents;
62 | char *freebock;
63 | char *freespace;
64 | char *blocks;
65 | char *emptyfile;
66 | char *filexist;
67 | char *overridefile;
68 | char *fileMPK;
69 | char *backupdone;
70 | char *sizeMB;
71 | char *savetypeinf;
72 | char *mpkbackup;
73 | char *mpkrestore;
74 | char *quickback;
75 | char *cheatnofound;
76 | char *parsingfail;
77 | char *resetconsol;
78 | char *cheatfound;
79 | char *emunofound;
80 | char *controlsmenucon;
81 | char *showmpkmenu;
82 | char *aboutscreen;
83 | char *Astartromdirectory;
84 | char *Amempak;
85 | char *Bbackcancel;
86 | char *Startlastrom;
87 | char *CLEFT;
88 | char *CLEFTVIEMPK;
89 | char *CRIGHT;
90 | char *CUP;
91 | char *CDOWN;
92 | char *LplusR;
93 | char *errornoready;
94 | char *filenoexist;
95 | char *pathnoexist;
96 | char *invalidname;
97 | char *operdenied;
98 | char *filealrrexist;
99 | char *errtimeout;
100 | char *devicelocked;
101 | char *orparsingfailed;
102 | char *done3p;
103 | char *readystr;
104 | char *cheatsysact;
105 | char *cupactcheat;
106 | char *crightv;
107 | char *donepresstart;
108 | char *filopenerror;
109 | char *nosavfund;
110 | char *trssavedata;
111 | char *errtrssavedata;
112 | char *errsavSD;
113 | char *errsavSDnocrfile;
114 | char *trloadchfile;
115 | char *chsfund;
116 | char *forcetvmd;
--------------------------------------------------------------------------------
/inc/main.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 The Altra64 project contributors
3 | // Portions (c) 2013 saturnu (Alt64) based on libdragon, Neo64Menu, ED64IO, libn64-hkz, libmikmod
4 | // See LICENSE file in the project root for full license information.
5 | //
6 | #ifndef MAIN_H
7 | #define MAIN_H
8 |
9 | //TODO: these should probably be static not protos in main
10 | void bootRom(display_context_t disp, int silent);
11 | void loadrom(display_context_t disp, u8 *buff, int fast);
12 |
13 | void HideSysvolumeinfo(char* fname);
14 |
15 | int showThisFolder(int hide_sysfolder, char* fname);
16 |
17 | void readSDcard(display_context_t disp, char *directory);
18 | int saveTypeToSd(display_context_t disp, char* save_filename ,int type);
19 |
20 | void drawShortInfoBox(display_context_t disp, char* text, u8 mode);
21 | void drawTextInput(display_context_t disp,char *msg);
22 |
23 | //#define ishexchar(c) (((c >= '0') && (c <= '9')) || ((c >= 'A') && (c <= 'F')) || ((c >= 'a') && (c <= 'f')))
24 |
25 | /**
26 | * @brief Return the uncached memory address of a cached address
27 | *
28 | * @param[in] x
29 | * The cached address
30 | *uint32_t
31 | * @return The uncached address
32 | */
33 | //#define UNCACHED_ADDR(x) ((void *)(((uint32_t)(x)) | 0xA0000000))
34 |
35 | /**
36 | * @brief Align a memory address to 16 byte offset
37 | *
38 | * @param[in] x
39 | * Unaligned memory address
40 | *
41 | * @return An aligned address guaranteed to be >= the unaligned address
42 | */
43 | //#define ALIGN_16BYTE(x) ((void *)(((uint32_t)(x)+15) & 0xFFFFFFF0))
44 |
45 | #endif
46 |
--------------------------------------------------------------------------------
/inc/mem.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 The Altra64 project contributors
3 | // Portions (c) 2011 KRIK
4 | // See LICENSE file in the project root for full license information.
5 | //
6 |
7 | #ifndef _MEM_H
8 | #define _MEM_H
9 |
10 | #define SPI_SPEED_INIT 2
11 | #define SPI_SPEED_25 1
12 | #define SPI_SPEED_50 0
13 |
14 | #define mem_spi evd_SPI
15 | #define memSpiSetSpeed evd_setSpiSpeed
16 | #define memSpiIsBusy evd_isSpiBusy
17 | #define memSpiSSOff evd_spiSSOff
18 | #define memSpiSSOn evd_spiSSOn
19 |
20 |
21 | void memSpiSSOn();
22 | void memSpiSSOff();
23 | void memSpiBusy();
24 | u8 memSpiIsBusy();
25 | void memSpiSetSpeed(u8 speed);
26 | void spiReadBlock(void *dat);
27 | void spiWriteBlock(void *dat);
28 | u8 memSpiRead(void *dst, u16 slen);
29 | u8 memSpiWrite(const void *src);
30 | //u8 mem_spi(u8 dat);
31 | void memfill(void *dst, u8 val, u16 len);
32 | void memcopy(void *src, void *dst, u16 len);
33 | void memSpiSetDma(u8 mode);
34 | void memRomWrite32(u32 addr, u32 val);
35 | u32 memRomRead32(u32 addr);
36 |
37 | #endif /* _MEM_H */
--------------------------------------------------------------------------------
/inc/memorypak.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 The Altra64 project contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | #ifndef _MEMORYPAK_H
7 | #define _MEMORYPAK_H
8 |
9 | //TODO: not sure if this is correct!!!
10 | extern char *mempak_path;
11 |
12 | int file_to_mpk(display_context_t disp, u8 *filename);
13 | void mpk_to_file(display_context_t disp, char *mpk_filename, int quick);
14 | void view_mpk_file(display_context_t disp, char *mpk_filename);
15 | void view_mpk(display_context_t disp);
16 |
17 | #endif
--------------------------------------------------------------------------------
/inc/mempak.h:
--------------------------------------------------------------------------------
1 | /**
2 | * @file mempak.h
3 | * @brief Mempak Filesystem Routines
4 | * @ingroup mempak
5 | */
6 | #ifndef __LIBDRAGON_MEMPAK_H
7 | #define __LIBDRAGON_MEMPAK_H
8 |
9 | /**
10 | * @addtogroup mempak
11 | * @{
12 | */
13 |
14 | /** @brief Size in bytes of a Mempak block */
15 | #define MEMPAK_BLOCK_SIZE 256
16 |
17 | /**
18 | * @brief Structure representing a save entry in a mempak
19 | */
20 | typedef struct entry_structure
21 | {
22 | /** @brief Vendor ID */
23 | uint32_t vendor;
24 | /** @brief Game ID */
25 | uint16_t game_id;
26 | /** @brief Inode pointer */
27 | uint16_t inode;
28 | /** @brief Intended region */
29 | uint8_t region;
30 | /** @brief Number of blocks used by this entry.
31 | * @see MEMPAK_BLOCK_SIZE */
32 | uint8_t blocks;
33 | /** @brief Validity of this entry. */
34 | uint8_t valid;
35 | /** @brief ID of this entry */
36 | uint8_t entry_id;
37 | /**
38 | * @brief Name of this entry
39 | *
40 | * The complete list of valid ASCII characters in a note name is:
41 | *
42 | *
43 | * ABCDEFGHIJKLMNOPQRSTUVWXYZ!"#`*+,-./:=?\@
44 | *
45 | *
46 | * The space character is also allowed. Any other character will be
47 | * converted to a space before writing to the mempak.
48 | */
49 | char name[19];
50 | } entry_structure_t;
51 |
52 | #ifdef __cplusplus
53 | extern "C" {
54 | #endif
55 |
56 | int read_mempak_sector( int controller, int sector, uint8_t *sector_data );
57 | int write_mempak_sector( int controller, int sector, uint8_t *sector_data );
58 | int validate_mempak( int controller );
59 | int get_mempak_free_space( int controller );
60 | int get_mempak_entry( int controller, int entry, entry_structure_t *entry_data );
61 | int format_mempak( int controller );
62 | int read_mempak_entry_data( int controller, entry_structure_t *entry, uint8_t *data );
63 | int write_mempak_entry_data( int controller, entry_structure_t *entry, uint8_t *data );
64 | int delete_mempak_entry( int controller, entry_structure_t *entry );
65 |
66 | #ifdef __cplusplus
67 | }
68 | #endif
69 |
70 | /** @} */ /* mempak */
71 |
72 | #endif
73 |
--------------------------------------------------------------------------------
/inc/menu.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 The Altra64 project contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | #ifndef _MENU_H_
7 | #define _MENU_H_
8 |
9 | extern int text_offset;
10 |
11 | void printText(char *msg, int x, int y, display_context_t dcon);
12 |
13 | void menu_about(display_context_t disp);
14 | void menu_controls(display_context_t disp);
15 | void menu_delete(display_context_t disp, bool isdir);
16 |
17 | #endif
18 |
--------------------------------------------------------------------------------
/inc/mp3.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 The Altra64 project contributors
3 | // Portions (c) 2013 saturnu (Alt64) based on libdragon, Neo64Menu, ED64IO, libn64-hkz, libmikmod
4 | // See LICENSE file in the project root for full license information.
5 | //
6 |
7 | #ifndef _MP3_H_
8 | #define _MP3_H_
9 |
10 | void mp3_Start(char *fname, long long *samples, int *rate, int *channels);
11 | void mp3_Stop(void);
12 | int mp3_Update(char *buf, int bytes);
13 |
14 | #endif // _MP3_H_
15 |
--------------------------------------------------------------------------------
/inc/regsinternal.h:
--------------------------------------------------------------------------------
1 | //TODO: this file is actually part of the libdragon source and should be included from there!!!
2 |
3 | /**
4 | * @file regsinternal.h
5 | * @brief Register definitions for various hardware in the N64
6 | * @ingroup lowlevel
7 | */
8 | #ifndef __LIBDRAGON_REGSINTERNAL_H
9 | #define __LIBDRAGON_REGSINTERNAL_H
10 |
11 | /**
12 | * @defgroup lowlevel Low Level Hardware Interfaces
13 | * @ingroup libdragon
14 | * @brief Low level hardware interface descriptions and functionality
15 | *
16 | * The low level hardware interfaces handle several functions in the N64 that
17 | * would otherwise be handled by a kernel or RTOS. This includes the @ref dma,
18 | * the @ref exceptions, the @ref interrupt and the @ref n64sys. The DMA controller
19 | * handles DMA requests between the cartridge and the N64 RDRAM. Other systems
20 | * in the N64 have their own DMA controllers that are handled in the relevant
21 | * subsystems. The exception handler traps any exceptions raised by the N64,
22 | * including the reset exception. The interrupt handler sets up the MIPS
23 | * interface (MI) which handles low level interrupt functionality for all other
24 | * systems in the N64. The N64 system interface provides the ability for code to
25 | * manipulate cache and boot options.
26 | */
27 |
28 | /**
29 | * @brief Register definition for the AI interface
30 | * @ingroup lowlevel
31 | */
32 | typedef struct AI_regs_s {
33 | /** @brief Pointer to uncached memory buffer of samples to play */
34 | volatile void * address;
35 | /** @brief Size in bytes of the buffer to be played. Should be
36 | * number of stereo samples * 2 * sizeof( uint16_t )
37 | */
38 | uint32_t length;
39 | /** @brief DMA start register. Write a 1 to this register to start
40 | * playing back an audio sample. */
41 | uint32_t control;
42 | /** @brief AI status register. Bit 31 is the full bit, bit 30 is the busy bit. */
43 | uint32_t status;
44 | /** @brief Rate at which the buffer should be played.
45 | *
46 | * Use the following formula to calculate the value: ((2 * clockrate / frequency) + 1) / 2 - 1
47 | */
48 | uint32_t dacrate;
49 | /** @brief The size of a single sample in bits. */
50 | uint32_t samplesize;
51 | } AI_regs_t;
52 |
53 | /**
54 | * @brief Register definition for the MI interface
55 | * @ingroup lowlevel
56 | */
57 | typedef struct MI_regs_s {
58 | /** @brief Mode register */
59 | uint32_t mode;
60 | /** @brief Version register */
61 | uint32_t version;
62 | /** @brief Current interrupts on the system */
63 | uint32_t intr;
64 | /** @brief Interrupt mask */
65 | uint32_t mask;
66 | } MI_regs_t;
67 |
68 | /**
69 | * @brief Register definition for the VI interface
70 | * @ingroup lowlevel
71 | */
72 | typedef struct VI_regs_s {
73 | /** @brief VI control register. Sets up various rasterization modes */
74 | uint32_t control;
75 | /** @brief Pointer to uncached buffer in memory to rasterize */
76 | void * framebuffer;
77 | /** @brief Width of the buffer in pixels */
78 | uint32_t width;
79 | /** @brief Vertical interrupt control register. Controls which horizontal
80 | * line must be hit to generate a VI interrupt
81 | */
82 | uint32_t v_int;
83 | /** @brief Current vertical line counter. */
84 | uint32_t cur_line;
85 | /** @brief Timing generation register for PAL/NTSC signals */
86 | uint32_t timing;
87 | /** @brief Number of lines per frame */
88 | uint32_t v_sync;
89 | /** @brief Number of pixels in line and leap pattern */
90 | uint32_t h_sync;
91 | /** @brief Number of pixels in line, set identically to h_sync */
92 | uint32_t h_sync2;
93 | /** @brief Beginning and end of video horizontally */
94 | uint32_t h_limits;
95 | /** @brief Beginning and end of video vertically */
96 | uint32_t v_limits;
97 | /** @brief Beginning and end of color burst in vertical lines */
98 | uint32_t color_burst;
99 | /** @brief Horizontal scaling factor from buffer to screen */
100 | uint32_t h_scale;
101 | /** @brief Vertical scaling factor from buffer to screen */
102 | uint32_t v_scale;
103 | } VI_regs_t;
104 |
105 | /**
106 | * @brief Register definition for the PI interface
107 | * @ingroup lowlevel
108 | */
109 | typedef struct PI_regs_s {
110 | /** @brief Uncached address in RAM where data should be found */
111 | volatile void * ram_address;
112 | /** @brief Address of data on peripheral */
113 | uint32_t pi_address;
114 | /** @brief How much data to read from RAM into the peripheral */
115 | uint32_t read_length;
116 | /** @brief How much data to write to RAM from the peripheral */
117 | uint32_t write_length;
118 | /** @brief Status of the PI, including DMA busy */
119 | uint32_t status;
120 | } PI_regs_t;
121 |
122 | /**
123 | * @brief Register definition for the SI interface
124 | * @ingroup lowlevel
125 | */
126 | typedef struct SI_regs_s {
127 | /** @brief Uncached address in RAM where data should be found */
128 | volatile void * DRAM_addr;
129 | /** @brief Address to read when copying from PIF RAM */
130 | volatile void * PIF_addr_read;
131 | /** @brief Reserved word */
132 | uint32_t reserved1;
133 | /** @brief Reserved word */
134 | uint32_t reserved2;
135 | /** @brief Address to write when copying to PIF RAM */
136 | volatile void * PIF_addr_write;
137 | /** @brief Reserved word */
138 | uint32_t reserved3;
139 | /** @brief SI status, including DMA busy and IO busy */
140 | uint32_t status;
141 | } SI_regs_t;
142 |
143 | /**
144 | * @brief Register definition for the SP interface
145 | * @ingroup lowlevel
146 | */
147 | typedef struct SP_regs_s {
148 | /** @brief RSP memory address (IMEM/DMEM) */
149 | volatile void * RSP_addr;
150 | /** @brief RDRAM memory address */
151 | volatile void * RDAM_addr;
152 | /** @brief RDRAM->RSP DMA length */
153 | uint32_t rsp_read_length;
154 | /** @brief RDP->RDRAM DMA length */
155 | uint32_t rsp_write_length;
156 | /** @brief RSP status */
157 | uint32_t status;
158 | /** @brief RSP DMA full */
159 | uint32_t rsp_dma_full;
160 | /** @brief RSP DMA busy */
161 | uint32_t rsp_dma_busy;
162 | /** @brief RSP Semaphore */
163 | uint32_t rsp_semaphore;
164 | } SP_regs_t;
165 |
166 | #endif
--------------------------------------------------------------------------------
/inc/rom.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 The Altra64 project contributors
3 | // Portions (c) 2013 saturnu (Alt64) based on libdragon, Neo64Menu, ED64IO, libn64-hkz, libmikmod
4 | // See LICENSE file in the project root for full license information.
5 | //
6 |
7 | #ifndef _ROM_H
8 | #define _ROM_H
9 |
10 | /*
11 | *
12 | 0000h (1 byte): initial PI_BSB_DOM1_LAT_REG value (0x80)
13 | 0001h (1 byte): initial PI_BSB_DOM1_PGS_REG value (0x37)
14 | 0002h (1 byte): initial PI_BSB_DOM1_PWD_REG value (0x12)
15 | 0003h (1 byte): initial PI_BSB_DOM1_PGS_REG value (0x40)
16 | 0004h - 0007h (1 dword): ClockRate
17 | 0008h - 000Bh (1 dword): Program Counter (PC)
18 | 000Ch - 000Fh (1 dword): Release
19 | 0010h - 0013h (1 dword): CRC1
20 | 0014h - 0017h (1 dword): CRC2
21 | 0018h - 001Fh (2 dwords): Unknown (0x0000000000000000)
22 | 0020h - 0033h (20 bytes): Image name
23 | Padded with 0x00 or spaces (0x20)
24 | 0034h - 0037h (1 dword): Unknown (0x00000000)
25 | 0038h - 003Bh (1 dword): Manufacturer ID
26 | 0x0000004E = Nintendo ('N')
27 | 003Ch - 003Dh (1 word): Cartridge ID
28 | 003Eh - 003Fh (1 word): Country code
29 | 0x4400 = Germany ('D')
30 | 0x4500 = USA ('E')
31 | 0x4A00 = Japan ('J')
32 | 0x5000 = Europe ('P')
33 | 0x5500 = Australia ('U')
34 | 0040h - 0FFFh (1008 dwords): Boot code
35 | */
36 |
37 | #define DP_BASE_REG 0x04100000
38 | #define VI_BASE_REG 0x04400000
39 | #define PI_BASE_REG 0x04600000
40 | #define PIF_RAM_START 0x1FC007C0
41 |
42 |
43 | /*
44 | * PI status register has 3 bits active when read from (PI_STATUS_REG - read)
45 | * Bit 0: DMA busy - set when DMA is in progress
46 | * Bit 1: IO busy - set when IO is in progress
47 | * Bit 2: Error - set when CPU issues IO request while DMA is busy
48 | */
49 |
50 | #define PI_STATUS_REG (PI_BASE_REG+0x10)
51 |
52 | /* PI DRAM address (R/W): starting RDRAM address */
53 | #define PI_DRAM_ADDR_REG (PI_BASE_REG+0x00) /* DRAM address */
54 |
55 | /* PI pbus (cartridge) address (R/W): starting AD16 address */
56 | #define PI_CART_ADDR_REG (PI_BASE_REG+0x04)
57 |
58 | /* PI read length (R/W): read data length */
59 | #define PI_RD_LEN_REG (PI_BASE_REG+0x08)
60 |
61 | /* PI write length (R/W): write data length */
62 | #define PI_WR_LEN_REG (PI_BASE_REG+0x0C)
63 |
64 | /*
65 | * PI status (R): [0] DMA busy, [1] IO busy, [2], error
66 | * (W): [0] reset controller (and abort current op), [1] clear intr
67 | */
68 |
69 | #define PI_BSD_DOM1_LAT_REG (PI_BASE_REG+0x14)
70 |
71 | /* PI dom1 pulse width (R/W): [7:0] domain 1 device R/W strobe pulse width */
72 | #define PI_BSD_DOM1_PWD_REG (PI_BASE_REG+0x18)
73 |
74 | /* PI dom1 page size (R/W): [3:0] domain 1 device page size */
75 | #define PI_BSD_DOM1_PGS_REG (PI_BASE_REG+0x1C) /* page size */
76 |
77 | /* PI dom1 release (R/W): [1:0] domain 1 device R/W release duration */
78 | #define PI_BSD_DOM1_RLS_REG (PI_BASE_REG+0x20)
79 | /* PI dom2 latency (R/W): [7:0] domain 2 device latency */
80 | #define PI_BSD_DOM2_LAT_REG (PI_BASE_REG+0x24) /* Domain 2 latency */
81 |
82 | /* PI dom2 pulse width (R/W): [7:0] domain 2 device R/W strobe pulse width */
83 | #define PI_BSD_DOM2_PWD_REG (PI_BASE_REG+0x28) /* pulse width */
84 |
85 | /* PI dom2 page size (R/W): [3:0] domain 2 device page size */
86 | #define PI_BSD_DOM2_PGS_REG (PI_BASE_REG+0x2C) /* page size */
87 |
88 | /* PI dom2 release (R/W): [1:0] domain 2 device R/W release duration */
89 | #define PI_BSD_DOM2_RLS_REG (PI_BASE_REG+0x30) /* release duration */
90 |
91 |
92 | #define PI_DOMAIN1_REG PI_BSD_DOM1_LAT_REG
93 | #define PI_DOMAIN2_REG PI_BSD_DOM2_LAT_REG
94 |
95 |
96 | #define PI_STATUS_ERROR 0x04
97 | #define PI_STATUS_IO_BUSY 0x02
98 | #define PI_STATUS_DMA_BUSY 0x01
99 |
100 | #define DPC_START (DP_BASE_REG + 0x00)
101 | #define DPC_END (DP_BASE_REG + 0x04)
102 | #define DPC_CURRENT (DP_BASE_REG + 0x08)
103 | #define DPC_STATUS (DP_BASE_REG + 0x0C)
104 | #define DPC_CLOCK (DP_BASE_REG + 0x10)
105 | #define DPC_BUFBUSY (DP_BASE_REG + 0x14)
106 | #define DPC_PIPEBUSY (DP_BASE_REG + 0x18)
107 | #define DPC_TMEM (DP_BASE_REG + 0x1C)
108 |
109 | #define VI_CONTROL (VI_BASE_REG + 0x00)
110 | #define VI_FRAMEBUFFER (VI_BASE_REG + 0x04)
111 | #define VI_WIDTH (VI_BASE_REG + 0x08)
112 | #define VI_V_INT (VI_BASE_REG + 0x0C)
113 | #define VI_CUR_LINE (VI_BASE_REG + 0x10)
114 | #define VI_TIMING (VI_BASE_REG + 0x14)
115 | #define VI_V_SYNC (VI_BASE_REG + 0x18)
116 | #define VI_H_SYNC (VI_BASE_REG + 0x1C)
117 | #define VI_H_SYNC2 (VI_BASE_REG + 0x20)
118 | #define VI_H_LIMITS (VI_BASE_REG + 0x24)
119 | #define VI_COLOR_BURST (VI_BASE_REG + 0x28)
120 | #define VI_H_SCALE (VI_BASE_REG + 0x2C)
121 | #define VI_VSCALE (VI_BASE_REG + 0x30)
122 |
123 | #define PHYS_TO_K0(x) ((u32)(x)|0x80000000) /* physical to kseg0 */
124 | #define K0_TO_PHYS(x) ((u32)(x)&0x1FFFFFFF) /* kseg0 to physical */
125 | #define PHYS_TO_K1(x) ((u32)(x)|0xA0000000) /* physical to kseg1 */
126 | #define K1_TO_PHYS(x) ((u32)(x)&0x1FFFFFFF) /* kseg1 to physical */
127 |
128 | #define IO_READ(addr) (*(volatile u32*)PHYS_TO_K1(addr))
129 | #define IO_WRITE(addr,data) (*(volatile u32*)PHYS_TO_K1(addr)=(u32)(data))
130 |
131 | #define SAVE_SIZE_SRAM 32768
132 | #define SAVE_SIZE_SRAM128 131072
133 | #define SAVE_SIZE_SRAM768 98304
134 | #define SAVE_SIZE_EEP4k 512
135 | #define SAVE_SIZE_EEP16k 2048
136 | #define SAVE_SIZE_FLASH 131072
137 |
138 | #define ROM_ADDR 0xb0000000
139 |
140 |
141 | #define FRAM_EXECUTE_CMD 0xD2000000
142 | #define FRAM_STATUS_MODE_CMD 0xE1000000
143 | #define FRAM_ERASE_OFFSET_CMD 0x4B000000
144 | #define FRAM_WRITE_OFFSET_CMD 0xA5000000
145 | #define FRAM_ERASE_MODE_CMD 0x78000000
146 | #define FRAM_WRITE_MODE_CMD 0xB4000000
147 | #define FRAM_READ_MODE_CMD 0xF0000000
148 |
149 | #define FRAM_STATUS_REG 0xA8000000
150 | #define FRAM_COMMAND_REG 0xA8010000
151 |
152 | //see also utils.c
153 | #define REGION_UNKNOWN 0 //leave auto/off
154 | #define REGION_NTSC 1
155 | #define REGION_PAL 2
156 | #define REGION_PAL_M 3
157 |
158 |
159 |
160 | //void romFill(...);
161 | void pif_boot();
162 |
163 | int is_valid_rom(unsigned char *buffer);
164 | void swap_header(unsigned char* header, int loadlength);
165 |
166 | u8 getCicType(u8 bios_cic);
167 |
168 | void send_game_id(uint8_t* crc_hi, uint8_t* crc_lo, uint8_t media_format, uint8_t country_id);
169 | void get_country_and_region(unsigned char ccode, char* region_string);
170 | unsigned char get_region(unsigned char ccode);
171 | #endif
172 |
--------------------------------------------------------------------------------
/inc/sd.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 The Altra64 project contributors
3 | // Portions (c) 2011 KRIK
4 | // See LICENSE file in the project root for full license information.
5 | //
6 |
7 | #ifndef _SD_H
8 | #define _SD_H
9 |
10 | #include "types.h"
11 |
12 | u8 sdGetInterface();
13 | u8 sdInit();
14 | u8 sdRead(u32 sector, u8 *buff, u16 count);
15 | u8 sdWrite(u32 sector, const u8 *buff, u16 count);
16 |
17 | void sdSetInterface(u32 interface);
18 |
19 |
20 |
21 | #define WAIT 1024
22 |
23 | #define DISK_IFACE_SPI 0
24 | #define DISK_IFACE_SD 1
25 |
26 |
27 | #endif /* _SD_H */
28 |
--------------------------------------------------------------------------------
/inc/sound.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 The Altra64 project contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 | #ifndef _SOUND_H
6 | #define _SOUND_H
7 |
8 | void sndInit(void);
9 | void sndPlayBGM(char* filename);
10 | void sndStopAll(void);
11 | void sndPlaySFX(char* filename);
12 | void sndUpdate(void);
13 |
14 | #endif
15 |
--------------------------------------------------------------------------------
/inc/sram.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 The Altra64 project contributors
3 | // Portions (c) 2013 saturnu (Alt64) based on libdragon, Neo64Menu, ED64IO, libn64-hkz, libmikmod
4 | // See LICENSE file in the project root for full license information.
5 | //
6 |
7 | #ifndef _SRAM_H
8 | #define _SRAM_H
9 |
10 | #include
11 | #include "types.h"
12 |
13 | void data_cache_hit_writeback_invalidate(volatile void *, unsigned long);
14 | void dma_write_sram(void* src, u32 offset, u32 size);
15 | void dma_read_sram(void *dest, u32 offset, u32 size);
16 | void dma_write_s(void * ram_address, unsigned long pi_address, unsigned long len);
17 | void dma_read_s(void * ram_address, unsigned long pi_address, unsigned long len);
18 | int writeSram(void* src, u32 size);
19 | void setSDTiming(void);
20 |
21 |
22 | void PI_Init(void);
23 | void PI_Init_SRAM(void);
24 | void PI_DMAWait(void);
25 | void PI_DMAFromCart(void* dest, void* src, u32 size);
26 | void PI_DMAToCart(void* dest, void* src, u32 size);
27 | void PI_DMAFromSRAM(void *dest, u32 offset, u32 size);
28 | void PI_DMAToSRAM(void* src, u32 offset, u32 size);
29 | void PI_SafeDMAFromCart(void *dest, void *src, u32 size);
30 |
31 | //memory
32 | /*** MEMORY ***/
33 | void *safe_memalign(size_t boundary, size_t size);
34 | void *safe_calloc(size_t nmemb, size_t size);
35 | void *safe_malloc(size_t size);
36 | void safe_free(void *ptr);
37 | void *safe_memset(void *s, int c, size_t n);
38 | void *safe_memcpy(void *dest, const void *src, size_t n);
39 |
40 | #endif
41 |
--------------------------------------------------------------------------------
/inc/strlib.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 The Altra64 project contributors
3 | // Portions (c) 2013 saturnu (Alt64) based on libdragon, Neo64Menu, ED64IO, libn64-hkz, libmikmod
4 | // See LICENSE file in the project root for full license information.
5 | //
6 |
7 | #ifndef _STRLIB_H
8 | #define _STRLIB_H
9 |
10 | #include "types.h"
11 |
12 | enum strtrim_mode_t {
13 | STRLIB_MODE_ALL = 0,
14 | STRLIB_MODE_RIGHT = 0x01,
15 | STRLIB_MODE_LEFT = 0x02,
16 | STRLIB_MODE_BOTH = 0x03
17 | };
18 |
19 | char *strcpytrim(char *d, // destination
20 | char *s, // source
21 | int mode,
22 | char *delim
23 | );
24 |
25 | char *strtriml(char *d, char *s);
26 | char *strtrimr(char *d, char *s);
27 | char *strtrim(char *d, char *s);
28 | char *strstrlibkill(char *d, char *s);
29 |
30 | char *triml(char *s);
31 | char *trimr(char *s);
32 | char *trim(char *s);
33 | char *strlibkill(char *s);
34 |
35 | void strhicase(u8 *str, u8 len);
36 | u16 strcon(u8 *str1, u8 *str2, u8 *dst, u16 max_len);
37 | u8 slen(u8 *str);
38 | u8 scopy(u8 *src, u8 *dst);
39 |
40 | u8 streq(u8 *str1, u8 *str2);
41 | u8 streql(u8 *str1, u8 *str2, u8 len);
42 |
43 | u16 strContain(u8 *target, u8 *str);
44 |
45 | #endif
46 |
--------------------------------------------------------------------------------
/inc/sys.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 The Altra64 project contributors
3 | // Portions (c) 2011 KRIK
4 | // See LICENSE file in the project root for full license information.
5 | //
6 |
7 | #ifndef _SYS_H
8 | #define _SYS_H
9 |
10 | #include "types.h"
11 |
12 |
13 | void dma_read_s(void * ram_address, unsigned long pi_address, unsigned long len);
14 | void dma_write_s(void * ram_address, unsigned long pi_address, unsigned long len);
15 |
16 |
17 | void sleep(u32 ms);
18 | void dma_write_sram(void* src, u32 offset, u32 size);
19 | void dma_read_sram(void *dest, u32 offset, u32 size);
20 | u8 getSaveType();
21 |
22 |
23 | typedef struct SP_regs_s {
24 | u32 mem_addr;
25 | u32 dram_addr;
26 | u32 rd_len;
27 | u32 wr_len;
28 | u32 status;
29 | } _SP_regs_s;
30 |
31 | #define SP_PC *((volatile u32 *)0xA4080000)
32 | #define SP_IBIST_REG *((volatile u32 *)0xA4080004)
33 |
34 | static volatile struct AI_regs_s * const AI_regs = (struct AI_regs_s *) 0xa4500000;
35 | static volatile struct MI_regs_s * const MI_regs = (struct MI_regs_s *) 0xa4300000;
36 | static volatile struct VI_regs_s * const VI_regs = (struct VI_regs_s *) 0xa4400000;
37 | static volatile struct PI_regs_s * const PI_regs = (struct PI_regs_s *) 0xa4600000;
38 | static volatile struct SP_regs_s * const SP_regs = (struct SP_regs_s *) 0xA4040000;
39 |
40 | extern u32 native_tv_mode;
41 |
42 | typedef struct {
43 | u16 sd_speed;
44 | u16 font_size;
45 | u16 tv_mode;
46 | u8 wall[256];
47 | } Options_st;
48 |
49 |
50 | extern Options_st options;
51 | extern u32 asm_date;
52 |
53 | #endif /* _SYS_H */
54 |
--------------------------------------------------------------------------------
/inc/types.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 The Altra64 project contributors
3 | // Portions (c) 2011 KRIK
4 | // See LICENSE file in the project root for full license information.
5 | //
6 |
7 | #ifndef _TYPES_H
8 | #define _TYPES_H
9 |
10 | #include
11 |
12 | #define u8 unsigned char
13 | #define u16 unsigned short
14 | #define u32 unsigned long
15 | #define u64 unsigned long long
16 |
17 | #define vu8 volatile unsigned char
18 | #define vu16 volatile unsigned short
19 | #define vu32 volatile unsigned long
20 | #define vu64 volatile unsigned long long
21 |
22 | #define s8 signed char
23 | #define s16 short
24 | #define s32 long
25 | #define s64 long long
26 |
27 |
28 | typedef volatile uint64_t sim_vu64;
29 | typedef volatile uint64_t sim_vu64;
30 | typedef unsigned int sim_u32;
31 | typedef uint64_t sim_u64;
32 |
33 |
34 | #endif /* _TYPES_H */
35 |
36 |
--------------------------------------------------------------------------------
/inc/usb.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 The Altra64 project contributors
3 | // Portions (c) 2011 KRIK
4 | // See LICENSE file in the project root for full license information.
5 | //
6 |
7 | #ifndef _USB_H
8 | #define _USB_H
9 |
10 | //#include "types.h"
11 | u8 usbListener();
12 |
13 |
14 | #endif /* _USB_H */
15 |
--------------------------------------------------------------------------------
/inc/utils.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 The Altra64 project contributors
3 | // Portions (c) 2013 saturnu (Alt64) based on libdragon, Neo64Menu, ED64IO, libn64-hkz, libmikmod
4 | // See LICENSE file in the project root for full license information.
5 | //
6 |
7 |
8 | #ifndef _UTILS_H
9 | #define _UTILS_H
10 |
11 | #if !defined(MIN)
12 | #define MIN(a, b) ({ \
13 | __typeof__ (a) _a = (a); \
14 | __typeof__ (b) _b = (b); \
15 | _a < _b ? _a : _b; \
16 | })
17 | #endif
18 |
19 | #if !defined(MAX)
20 | #define MAX(a, b) ({ \
21 | __typeof__ (a) _a = (a); \
22 | __typeof__ (b) _b = (b); \
23 | _a > _b ? _a : _b; \
24 | })
25 | #endif
26 |
27 |
28 | void _sync_bus(void);
29 | void _data_cache_invalidate_all(void);
30 |
31 | // End ...
32 |
33 |
34 | void restoreTiming(void);
35 |
36 | void simulate_boot(u32 boot_cic, u8 bios_cic, u32 *cheat_list[2]);
37 |
38 |
39 | int get_cic_save(char *cartid, int *cic, int *save);
40 | //const char* saveTypeToExtension(int type);
41 | const char* saveTypeToExtension(int type, int etype);
42 | int saveTypeToSize(int type);
43 | int getSaveFromCart(int stype, uint8_t *buffer);
44 | int pushSaveToCart(int stype, uint8_t *buffer);
45 |
46 | int getSRAM( uint8_t *buffer,int size);
47 | int getSRAM32( uint8_t *buffer);
48 | int getSRAM128( uint8_t *buffer);
49 | int getSRAM768( uint8_t *buffer);
50 | int getEeprom4k( uint8_t *buffer);
51 | int getEeprom16k( uint8_t *buffer);
52 | int getFlashRAM( uint8_t *buffer);
53 |
54 | int setSRAM(uint8_t *buffer,int size);
55 | int setSRAM32( uint8_t *buffer);
56 | int setSRAM128( uint8_t *buffer);
57 | int setSRAM768( uint8_t *buffer);
58 | int setEeprom4k( uint8_t *buffer);
59 | int setEeprom16k( uint8_t *buffer);
60 | int setFlashRAM( uint8_t *buffer);
61 |
62 | #endif
63 |
--------------------------------------------------------------------------------
/inc/version.h:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 The Altra64 project contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | #ifndef _VERSION_H
7 | #define _VERSION_H
8 |
9 | const char* Altra64_GetVersionString(void);
10 |
11 | #endif
12 |
--------------------------------------------------------------------------------
/res/ALTRA64.INI:
--------------------------------------------------------------------------------
1 | ; alt64 config file
2 |
3 | [ed64] ; Menu config
4 | build=18 ; Release build nr
5 | border_color_1=FFFFFFFF ; 0x00000080 RGBT
6 | border_color_2=FFFFFFFF ; 0x3F3F3FFF RGBT 00000060 w light
7 | box_color=000000B6 ; 0x00000080 RGBT
8 | selection_color=80008070 ; 80008070 RGBT 6495ED60
9 | list_font_color=CDC9C940 ; 80008070 RGBT 6495ED60
10 | list_dir_font_color=FFFFE040 ; 80008070 RGBT 6495ED60
11 | selection_font_color=FFB90FFF ; 80008070 RGBT 6495ED60
12 | text_offset=0 ; shift menu horizontal e.g. -1
13 | cd_behaviour=1 ; 0=first entry 1=last entry
14 | scroll_behaviour=0 ; 0=page-system 1=classic
15 | quick_boot=1 ; 'START' boots last rom
16 | bgm_on=0
17 | sound_on=1 ; sounds 1=on 0=off
18 | page_display=1 ; display page
19 | tv_mode=0 ; 1=ntsc 2=pal 3=mpal 0=force_off
20 | enable_colored_list=1 ; 1=enable 0=disalbe
21 | ext_type=1 ; 0=classic 1=OS64
22 | sd_speed=2 ; 1=25MHz 2=50MHz
23 | background_image=bgr2.png ; backgrund png image 320x240 32bit
24 | hide_sysfolder=0 ; 1=hide 0=don't hide
25 | mempak_path=/ED64P/MEMPAKS/ ; surround with slashes
26 | save_path=SDSAVE ; save directory inside ED64P
27 | language=1 ;0=ENG 1=ES 2=FR
28 | show_splash=0 ;show splash
29 | splash_image= ;splash image
30 | save_backup=0 ;
31 |
32 | [user]
33 | name = saturnu ; Username
--------------------------------------------------------------------------------
/res/WALLPAPER/bg.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/WALLPAPER/bg.bmp
--------------------------------------------------------------------------------
/res/emulators/UltraSMS.z64:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/emulators/UltraSMS.z64
--------------------------------------------------------------------------------
/res/emulators/gb.v64:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/emulators/gb.v64
--------------------------------------------------------------------------------
/res/emulators/neon64bu.rom:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/emulators/neon64bu.rom
--------------------------------------------------------------------------------
/res/emulators/ultraMSX2.z64:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/emulators/ultraMSX2.z64
--------------------------------------------------------------------------------
/res/filesystem/sounds/bamboo.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/filesystem/sounds/bamboo.wav
--------------------------------------------------------------------------------
/res/filesystem/sounds/bgm21.it:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/filesystem/sounds/bgm21.it
--------------------------------------------------------------------------------
/res/filesystem/sounds/boot.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/filesystem/sounds/boot.wav
--------------------------------------------------------------------------------
/res/filesystem/sounds/done.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/filesystem/sounds/done.wav
--------------------------------------------------------------------------------
/res/filesystem/sounds/doned.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/filesystem/sounds/doned.wav
--------------------------------------------------------------------------------
/res/filesystem/sounds/ed64_mono.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/filesystem/sounds/ed64_mono.wav
--------------------------------------------------------------------------------
/res/filesystem/sounds/warning.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/filesystem/sounds/warning.wav
--------------------------------------------------------------------------------
/res/filesystem/sprites/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/filesystem/sprites/background.png
--------------------------------------------------------------------------------
/res/filesystem/sprites/background.sprite:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/filesystem/sprites/background.sprite
--------------------------------------------------------------------------------
/res/filesystem/sprites/n64controller.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/filesystem/sprites/n64controller.png
--------------------------------------------------------------------------------
/res/filesystem/sprites/n64controller.sprite:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/filesystem/sprites/n64controller.sprite
--------------------------------------------------------------------------------
/res/filesystem/sprites/old/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/filesystem/sprites/old/background.png
--------------------------------------------------------------------------------
/res/filesystem/sprites/old/background.sprite:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/filesystem/sprites/old/background.sprite
--------------------------------------------------------------------------------
/res/filesystem/sprites/old/n64controller.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/filesystem/sprites/old/n64controller.png
--------------------------------------------------------------------------------
/res/filesystem/sprites/old/n64controller.sprite:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/filesystem/sprites/old/n64controller.sprite
--------------------------------------------------------------------------------
/res/filesystem/sprites/old/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/filesystem/sprites/old/splash.png
--------------------------------------------------------------------------------
/res/filesystem/sprites/old/splash.sprite:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/filesystem/sprites/old/splash.sprite
--------------------------------------------------------------------------------
/res/filesystem/sprites/splash.sprite:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/filesystem/sprites/splash.sprite
--------------------------------------------------------------------------------
/res/header.ed64:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Suprapote/Altra64/a38e7c2f3e6ad3be823eb33118bc659b102e635d/res/header.ed64
--------------------------------------------------------------------------------
/src/chksum64.c:
--------------------------------------------------------------------------------
1 | /*
2 | checksum rom in psram, based on
3 |
4 | chksum64 V1.2, a program to calculate the ROM checksum of Nintendo64 ROMs.
5 | Copyright (C) 1997 Andreas Sterbenz (stan@sbox.tu-graz.ac.at)
6 |
7 | This program is free software; you can redistribute it and/or modify
8 | it under the terms of the GNU General Public License as published by
9 | the Free Software Foundation; either version 2 of the License, or
10 | (at your option) any later version.
11 |
12 | This program is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program; if not, write to the Free Software
19 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20 | */
21 |
22 | #include
23 |
24 | #include "sys.h"
25 | #include "chksum64.h"
26 |
27 |
28 | #define BUFSIZE 0x8000
29 | #define SDRAM_START 0xb0000000
30 |
31 | #define CHECKSUM_START 0x1000
32 | #define CHECKSUM_LENGTH 0x100000L
33 | #define CHECKSUM_HEADERPOS 0x10
34 | #define CHECKSUM_END (CHECKSUM_START + CHECKSUM_LENGTH)
35 |
36 | #define CHECKSUM_STARTVALUE 0xf8ca4ddc
37 |
38 | #define ROL(i, b) (((i)<<(b)) | ((i)>>(32-(b))))
39 |
40 | #define BYTES2LONG(b) ( (((b)[0] & 0xffL) << 24) | \
41 | (((b)[1] & 0xffL) << 16) | \
42 | (((b)[2] & 0xffL) << 8) | \
43 | (((b)[3] & 0xffL)) )
44 |
45 | #define LONG2BYTES(l, b) (b)[0] = ((l)>>24)&0xff; \
46 | (b)[1] = ((l)>>16)&0xff; \
47 | (b)[2] = ((l)>> 8)&0xff; \
48 | (b)[3] = ((l) )&0xff;
49 |
50 |
51 | static unsigned char __attribute__((aligned(16))) buffer1[BUFSIZE];
52 |
53 |
54 | void checksum_sdram(void)
55 | {
56 | unsigned int sum1, sum2, offs;
57 |
58 | {
59 | unsigned int i;
60 | unsigned int c1, k1, k2;
61 | unsigned int t1, t2, t3, t4;
62 | unsigned int t5, t6;
63 | unsigned int n;
64 | unsigned int clen = CHECKSUM_LENGTH;
65 |
66 | t1 = CHECKSUM_STARTVALUE;
67 | t2 = CHECKSUM_STARTVALUE;
68 | t3 = CHECKSUM_STARTVALUE;
69 | t4 = CHECKSUM_STARTVALUE;
70 | t5 = CHECKSUM_STARTVALUE;
71 | t6 = CHECKSUM_STARTVALUE;
72 |
73 | offs = CHECKSUM_START;
74 |
75 | for( ;; ) {
76 | n = (BUFSIZE < clen) ? BUFSIZE : clen;
77 | dma_read_s(buffer1, SDRAM_START+offs, n);
78 | data_cache_hit_writeback_invalidate(buffer1,n);
79 |
80 | offs += n;
81 |
82 | for( i=0; i
14 | #include
15 | #include
16 | #include
17 | #include "regsinternal.h"
18 | #include "cic.h"
19 | #include "types.h"
20 | #include "rom.h" //TODO: perhaps the pifram defines should be global
21 |
22 |
23 |
24 | // CIC seeds and status bits passed from PIF to IPL through PIF RAM
25 | // Bits | Description
26 | // 00080000 | ROM type (0 = Game Pack, 1 = DD)
27 | // 00040000 | Version
28 | // 00020000 | Reset Type (0 = cold reset, 1 = NMI)
29 | // 0000FF00 | CIC IPL3 seed value
30 | // 000000FF | CIC IPL2 seed value
31 | // #define CIC_SEED_NUS_5101 0x0000AC00U
32 | // #define CIC_SEED_NUS_6101 0x00043F3FU
33 | // #define CIC_SEED_NUS_6102 0x00003F3FU
34 | // #define CIC_SEED_NUS_6103 0x0000783FU
35 | // #define CIC_SEED_NUS_6105 0x0000913FU
36 | // #define CIC_SEED_NUS_6106 0x0000853FU
37 | // #define CIC_SEED_NUS_8303 0x0000DD00U
38 |
39 | #define CRC_NUS_5101 0x587BD543U
40 | #define CRC_NUS_6101 0x6170A4A1U
41 | #define CRC_NUS_7102 0x009E9EA3U
42 | #define CRC_NUS_6102 0x90BB6CB5U
43 | #define CRC_NUS_6103 0x0B050EE0U
44 | #define CRC_NUS_6105 0x98BC2C86U
45 | #define CRC_NUS_6106 0xACC8580AU
46 | #define CRC_NUS_8303 0x0E018159U
47 |
48 | static uint32_t si_crc32(const uint8_t *data, size_t size);
49 |
50 | // Determines the CIC seed for a cart, given the ROM data.
51 | //int get_cic_seed(const uint8_t *rom_data, uint32_t *cic_seed) {
52 | int get_cic(unsigned char *rom_data) {
53 | uint32_t crc = si_crc32(rom_data + 0x40, 0x1000 - 0x40);
54 | uint32_t aleck64crc = si_crc32(rom_data + 0x40, 0xC00 - 0x40);
55 |
56 | if (aleck64crc == CRC_NUS_5101)
57 | return 4;//*cic_seed = CIC_SEED_NUS_5101;
58 | else
59 | {
60 | switch (crc) {
61 | case CRC_NUS_6101:
62 | case CRC_NUS_7102:
63 | //*cic_seed = CIC_SEED_NUS_6101;
64 | return 1;
65 | break;
66 |
67 | case CRC_NUS_6102:
68 | //*cic_seed = CIC_SEED_NUS_6102;
69 | return 2;
70 | break;
71 |
72 | case CRC_NUS_6103:
73 | //*cic_seed = CIC_SEED_NUS_6103;
74 | return 3;
75 | break;
76 |
77 | case CRC_NUS_6105:
78 | //*cic_seed = CIC_SEED_NUS_6105;
79 | return 5;
80 | break;
81 |
82 | case CRC_NUS_6106:
83 | //*cic_seed = CIC_SEED_NUS_6106;
84 | return 6;
85 | break;
86 |
87 | case CRC_NUS_8303: //not sure if this is necessary as we are using cart conversions
88 | //cic_seed = CIC_SEED_NUS_8303;
89 | return 7;
90 | break;
91 |
92 | default:
93 | break;
94 | }
95 | }
96 | return 2;
97 | }
98 |
99 | uint32_t si_crc32(const uint8_t *data, size_t size) {
100 | uint32_t table[256];
101 | unsigned n, k;
102 | uint32_t c;
103 |
104 | for (n = 0; n < 256; n++) {
105 | c = (uint32_t) n;
106 |
107 | for (k = 0; k < 8; k++) {
108 | if (c & 1)
109 | c = 0xEDB88320L ^ (c >> 1);
110 | else
111 | c = c >> 1;
112 | }
113 |
114 | table[n] = c;
115 | }
116 |
117 | c = 0L ^ 0xFFFFFFFF;
118 |
119 | for (n = 0; n < size; n++)
120 | c = table[(c ^ data[n]) & 0xFF] ^ (c >> 8);
121 |
122 | return c ^ 0xFFFFFFFF;
123 | }
124 |
125 | static volatile struct SI_regs_s * const SI_regs = (struct SI_regs_s *) 0xa4800000;
126 | static void * const PIF_RAM = (void *) 0x1fc007c0;
127 |
128 | /** @brief SI DMA busy */
129 | #define SI_STATUS_DMA_BUSY ( 1 << 0 )
130 | /** @brief SI IO busy */
131 | #define SI_STATUS_IO_BUSY ( 1 << 1 )
132 |
133 | static void __SI_DMA_wait(void) {
134 | while (SI_regs->status & (PI_STATUS_DMA_BUSY | PI_STATUS_IO_BUSY));
135 | }
136 |
137 | static void __controller_exec_PIF(void *inblock, void *outblock) {
138 | volatile uint64_t inblock_temp[8];
139 | volatile uint64_t outblock_temp[8];
140 |
141 | data_cache_hit_writeback_invalidate(inblock_temp, 64);
142 | memcpy(UncachedAddr(inblock_temp), inblock, 64);
143 |
144 | /* Be sure another thread doesn't get into a resource fight */
145 | disable_interrupts();
146 |
147 | __SI_DMA_wait();
148 |
149 | SI_regs->DRAM_addr = inblock_temp; // only cares about 23:0
150 | MEMORY_BARRIER();
151 | SI_regs->PIF_addr_write = PIF_RAM; // is it really ever anything else?
152 | MEMORY_BARRIER();
153 |
154 | __SI_DMA_wait();
155 |
156 | data_cache_hit_writeback_invalidate(outblock_temp, 64);
157 |
158 | SI_regs->DRAM_addr = outblock_temp;
159 | MEMORY_BARRIER();
160 | SI_regs->PIF_addr_read = PIF_RAM;
161 | MEMORY_BARRIER();
162 |
163 | __SI_DMA_wait();
164 |
165 | /* Now that we've copied, its safe to let other threads go */
166 | enable_interrupts();
167 |
168 | memcpy(outblock, UncachedAddr(outblock_temp), 64);
169 | }
170 |
171 | int pifram_x105_response_test() {
172 |
173 | static unsigned long long SI_eeprom_read_block[8] = {
174 | 0xFFFFFFFFFFFFFFFF,
175 | 0xFFFFFFFFFFFFFFFF,
176 | 0xFFFFFFFFFFFFFFFF,
177 | 0xFFFFFFFFFFFFFFFF,
178 | 0xFFFFFFFFFFFFFFFF,
179 | 0xFFFFFFFFFFFF0F0F,
180 | 0x8B00620018000600,
181 | 0x0100C000B0000002 //0x3f=02
182 |
183 | };
184 | static unsigned long long output[8];
185 |
186 | __controller_exec_PIF(SI_eeprom_read_block,output);
187 |
188 | /*
189 | expected result
190 | FF FF FF FF FF FF FF FF
191 | FF FF FF FF FF FF FF FF
192 | FF FF FF FF FF FF FF FF
193 | FF FF FF FF FF FF FF FF
194 | FF FF FF FF FF FF FF FF
195 | FF FF FF FF FF FF 00 00
196 | 3E C6 C0 4E BD 37 15 55
197 | 5A 8C 2A 8C D3 71 71 00
198 | */
199 |
200 | /* We are looking for 0x55 in [6], which
201 | * signifies that there is an x105 present.*/
202 |
203 | if( (output[6] & 0xFF) == 0x55 )
204 | {
205 | //x105 found!
206 | return 1;
207 |
208 | } else {
209 | //x105 not found!
210 | return 0;
211 |
212 | }
213 |
214 | }
--------------------------------------------------------------------------------
/src/debug.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include "types.h"
5 | #include "debug.h"
6 | #include "menu.h"
7 | #include "sys.h"
8 |
9 | void dbg_printf(display_context_t disp, const char *fmt, ...)
10 | {
11 | char buf[256] = {0};
12 | setbuf(stderr, buf);
13 |
14 | va_list args;
15 | va_start(args, fmt);
16 | vfprintf(stderr, fmt, args);
17 | va_end(args);
18 |
19 | u8 tmp[256] = {0};
20 | sprintf(tmp, "%s", buf);
21 | printText(tmp, 3, -1, disp);
22 | display_show(disp);
23 | sleep(3000);
24 | }
25 |
26 |
27 | void dbg_print(display_context_t disp, char *fmt)
28 | {
29 | printText(fmt, 3, -1, disp);
30 | display_show(disp);
31 | sleep(3000);
32 | }
--------------------------------------------------------------------------------
/src/diskio.c:
--------------------------------------------------------------------------------
1 | /*-----------------------------------------------------------------------*/
2 | /* Low level disk I/O module skeleton for FatFs (C)ChaN, 2016 */
3 | /*-----------------------------------------------------------------------*/
4 | /* If a working storage control module is available, it should be */
5 | /* attached to the FatFs via a glue function rather than modifying it. */
6 | /* This is an example of glue functions to attach various exsisting */
7 | /* storage control modules to the FatFs module with a defined API. */
8 | /*-----------------------------------------------------------------------*/
9 |
10 | #include "diskio.h" /* FatFs lower layer API */
11 | #include "sd.h"
12 |
13 | /* Definitions of physical drive number for each drive */
14 | #define DEV_RAM 0 /* Example: Map Ramdisk to physical drive 0 */
15 | #define DEV_MMC 1 /* Example: Map MMC/SD card to physical drive 1 */
16 | #define DEV_USB 2 /* Example: Map USB MSD to physical drive 2 */
17 |
18 |
19 | /*-----------------------------------------------------------------------*/
20 | /* Get Drive Status */
21 | /*-----------------------------------------------------------------------*/
22 |
23 | DSTATUS disk_status (
24 | BYTE pdrv /* Physical drive nmuber to identify the drive */
25 | )
26 | {
27 | DSTATUS stat;
28 | // int result;
29 |
30 | // switch (pdrv) {
31 | // case DEV_RAM :
32 | // result = RAM_disk_status();
33 |
34 | // // translate the reslut code here
35 |
36 | // return stat;
37 |
38 | // case DEV_MMC :
39 | // result = MMC_disk_status();
40 |
41 | // // translate the reslut code here
42 |
43 | // return stat;
44 |
45 | // case DEV_USB :
46 | // result = USB_disk_status();
47 |
48 | // // translate the reslut code here
49 |
50 | // return stat;
51 | // }
52 | // return STA_NOINIT;
53 |
54 | if(pdrv)
55 | {
56 | return STA_NOINIT;
57 | }
58 | return RES_OK;
59 | }
60 |
61 |
62 |
63 | /*-----------------------------------------------------------------------*/
64 | /* Initialize a Drive */
65 | /*-----------------------------------------------------------------------*/
66 |
67 | DSTATUS disk_initialize (
68 | BYTE pdrv /* Physical drive nmuber to identify the drive */
69 | )
70 | {
71 | DSTATUS stat;
72 | int result;
73 |
74 | // switch (pdrv) {
75 | // case DEV_RAM :
76 | // result = RAM_disk_initialize();
77 |
78 | // // translate the reslut code here
79 |
80 | // return stat;
81 |
82 | // case DEV_MMC :
83 | // result = MMC_disk_initialize();
84 |
85 | // // translate the reslut code here
86 |
87 | // return stat;
88 |
89 | // case DEV_USB :
90 | // result = USB_disk_initialize();
91 |
92 | // // translate the reslut code here
93 |
94 | // return stat;
95 | // }
96 |
97 | stat=sdInit(); //SD card initialization
98 |
99 | if(stat == STA_NODISK)
100 | {
101 | return STA_NODISK;
102 | }
103 | else if(stat != 0)
104 | {
105 | return STA_NOINIT;
106 | }
107 | else
108 | {
109 | return 0;
110 | }
111 |
112 | return STA_NOINIT;
113 | }
114 |
115 |
116 |
117 | /*-----------------------------------------------------------------------*/
118 | /* Read Sector(s) */
119 | /*-----------------------------------------------------------------------*/
120 |
121 | DRESULT disk_read (
122 | BYTE pdrv, /* Physical drive nmuber to identify the drive */
123 | BYTE *buff, /* Data buffer to store read data */
124 | DWORD sector, /* Start sector in LBA */
125 | UINT count /* Number of sectors to read */
126 | )
127 | {
128 | DRESULT res;
129 | // int result;
130 |
131 | // switch (pdrv) {
132 | // case DEV_RAM :
133 | // // translate the arguments here
134 |
135 | // result = RAM_disk_read(buff, sector, count);
136 |
137 | // // translate the reslut code here
138 |
139 | // return res;
140 |
141 | // case DEV_MMC :
142 | // // translate the arguments here
143 |
144 | // result = MMC_disk_read(buff, sector, count);
145 |
146 | // // translate the reslut code here
147 |
148 | // return res;
149 |
150 | // case DEV_USB :
151 | // // translate the arguments here
152 |
153 | // result = USB_disk_read(buff, sector, count);
154 |
155 | // // translate the reslut code here
156 |
157 | // return res;
158 | // }
159 |
160 | // return RES_PARERR;
161 |
162 | if (pdrv || !count)
163 | {
164 | return RES_PARERR;
165 | }
166 |
167 | res = sdRead(sector, buff, count);
168 |
169 | if(res == 0x00)
170 | {
171 | return RES_OK;
172 | }
173 | else
174 | {
175 | return RES_ERROR;
176 | }
177 | }
178 |
179 |
180 |
181 | /*-----------------------------------------------------------------------*/
182 | /* Write Sector(s) */
183 | /*-----------------------------------------------------------------------*/
184 |
185 | DRESULT disk_write (
186 | BYTE pdrv, /* Physical drive nmuber to identify the drive */
187 | const BYTE *buff, /* Data to be written */
188 | DWORD sector, /* Start sector in LBA */
189 | UINT count /* Number of sectors to write */
190 | )
191 | {
192 | DRESULT res;
193 | // int result;
194 |
195 | // switch (pdrv) {
196 | // case DEV_RAM :
197 | // // translate the arguments here
198 |
199 | // result = RAM_disk_write(buff, sector, count);
200 |
201 | // // translate the reslut code here
202 |
203 | // return res;
204 |
205 | // case DEV_MMC :
206 | // // translate the arguments here
207 |
208 | // result = MMC_disk_write(buff, sector, count);
209 |
210 | // // translate the reslut code here
211 |
212 | // return res;
213 |
214 | // case DEV_USB :
215 | // // translate the arguments here
216 |
217 | // result = USB_disk_write(buff, sector, count);
218 |
219 | // // translate the reslut code here
220 |
221 | // return res;
222 | // }
223 |
224 | //return RES_PARERR;
225 |
226 | if (pdrv || !count)
227 | {
228 | return RES_PARERR;
229 | }
230 |
231 | res = sdWrite(sector, buff, count);
232 |
233 | if(res == 0)
234 | {
235 | return RES_OK;
236 | }
237 | else
238 | {
239 | return RES_ERROR;
240 | }
241 | }
242 |
243 |
244 |
245 | /*-----------------------------------------------------------------------*/
246 | /* Miscellaneous Functions */
247 | /*-----------------------------------------------------------------------*/
248 |
249 | DRESULT disk_ioctl (
250 | BYTE pdrv, /* Physical drive nmuber (0..) */
251 | BYTE cmd, /* Control code */
252 | void *buff /* Buffer to send/receive control data */
253 | )
254 | {
255 | DRESULT res;
256 | // int result;
257 |
258 | // switch (pdrv) {
259 | // case DEV_RAM :
260 |
261 | // // Process of the command for the RAM drive
262 |
263 | // return res;
264 |
265 | // case DEV_MMC :
266 |
267 | // // Process of the command for the MMC/SD card
268 |
269 | // return res;
270 |
271 | // case DEV_USB :
272 |
273 | // // Process of the command the USB drive
274 |
275 | // return res;
276 | // }
277 |
278 | switch (cmd) {
279 | case CTRL_SYNC:
280 | return RES_OK;
281 | case GET_SECTOR_SIZE:
282 | *(WORD*)buff = 512;
283 | return RES_OK;
284 | case GET_SECTOR_COUNT:
285 | //*(DWORD*)buff = sdGetSectors();
286 | return RES_OK;
287 | case GET_BLOCK_SIZE:
288 | //*(DWORD*)buff = sdGetBlockSize();
289 | return RES_OK;
290 | }
291 |
292 | return RES_PARERR;
293 | }
294 |
295 | DWORD get_fattime (void)
296 | {
297 | //TODO: can we use the V3 RTC?
298 | return 0;
299 | }
300 |
301 |
--------------------------------------------------------------------------------
/src/everdrive.c:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 The Altra64 project contributors
3 | // Portions (c) 2013 saturnu (Alt64) based on libdragon, Neo64Menu, ED64IO, libn64-hkz, libmikmod
4 | // See LICENSE file in the project root for full license information.
5 | //
6 |
7 | #include "everdrive.h"
8 | #include "sys.h"
9 | #include "errors.h"
10 |
11 | #define CMD0 0x40 // software reset
12 | #define CMD1 0x41 // brings card out of idle state
13 | #define CMD2 0x42 // not used in SPI mode
14 | #define CMD3 0x43 // not used in SPI mode
15 | #define CMD4 0x44 // not used in SPI mode
16 | #define CMD5 0x45 // Reserved
17 | #define CMD6 0x46 // Reserved
18 | #define CMD7 0x47 // not used in SPI mode
19 | #define CMD8 0x48 // Reserved
20 | #define CMD9 0x49 // ask card to send card speficic data (CSD)
21 | #define CMD10 0x4A // ask card to send card identification (CID)
22 | #define CMD11 0x4B // not used in SPI mode
23 | #define CMD12 0x4C // stop transmission on multiple block read
24 | #define CMD13 0x4D // ask the card to send it's status register
25 | #define CMD14 0x4E // Reserved
26 | #define CMD15 0x4F // not used in SPI mode
27 | #define CMD16 0x50 // sets the block length used by the memory card
28 | #define CMD17 0x51 // read single block
29 | #define CMD18 0x52 // read multiple block
30 | #define CMD19 0x53 // Reserved
31 | #define CMD20 0x54 // not used in SPI mode
32 | #define CMD21 0x55 // Reserved
33 | #define CMD22 0x56 // Reserved
34 | #define CMD23 0x57 // Reserved
35 | #define CMD24 0x58 // writes a single block
36 | #define CMD25 0x59 // writes multiple blocks
37 | #define CMD26 0x5A // not used in SPI mode
38 | #define CMD27 0x5B // change the bits in CSD
39 | #define CMD28 0x5C // sets the write protection bit
40 | #define CMD29 0x5D // clears the write protection bit
41 | #define CMD30 0x5E // checks the write protection bit
42 | #define CMD31 0x5F // Reserved
43 | #define CMD32 0x60 // Sets the address of the first sector of the erase group
44 | #define CMD33 0x61 // Sets the address of the last sector of the erase group
45 | #define CMD34 0x62 // removes a sector from the selected group
46 | #define CMD35 0x63 // Sets the address of the first group
47 | #define CMD36 0x64 // Sets the address of the last erase group
48 | #define CMD37 0x65 // removes a group from the selected section
49 | #define CMD38 0x66 // erase all selected groups
50 | #define CMD39 0x67 // not used in SPI mode
51 | #define CMD40 0x68 // not used in SPI mode
52 | #define CMD41 0x69 // Reserved
53 | #define CMD42 0x6A // locks a block
54 | // CMD43 ... CMD57 are Reserved
55 | #define CMD58 0x7A // reads the OCR register
56 | #define CMD59 0x7B // turns CRC off
57 | // CMD60 ... CMD63 are not used in SPI mode
58 |
59 |
60 |
61 |
62 |
63 |
64 | #define ED_STATE_DMA_BUSY 0
65 | #define ED_STATE_DMA_TOUT 1
66 | #define ED_STATE_TXE 2
67 | #define ED_STATE_RXF 3
68 | #define ED_STATE_SPI 4
69 |
70 | #define SPI_CFG_SPD0 0
71 | #define SPI_CFG_SPD1 1
72 | #define SPI_CFG_SS 2
73 | #define SPI_CFG_RD 3
74 | #define SPI_CFG_DAT 4
75 | #define SPI_CFG_1BIT 5
76 |
77 | #define SAV_EEP_ON 0
78 | #define SAV_SRM_ON 1
79 | #define SAV_EEP_SIZE 2
80 | #define SAV_SRM_SIZE 3
81 |
82 | //was missing
83 | //#define BI_SPI_SPD_LO 0
84 |
85 | #define BI_SPI_SPD_LO 2 // around 200khz (only for sd initialization)
86 | #define BI_SPI_SPD_25 1
87 | #define BI_SPI_SPD_50 0
88 |
89 |
90 | void evd_setSpiSpeed(u8 speed);
91 | u8 evd_mmcCmd(u8 cmd, u32 arg);
92 |
93 | u8 sd_mode;
94 | volatile u8 spi_cfg;
95 | volatile u8 evd_cfg;
96 | u8 sd_type;
97 | volatile u32 *regs_ptr = (u32 *) 0xA8040000;
98 |
99 | /*
100 | result[2] <= ad[15:8] == {ad[6], ad[1], ad[0], ad[7], ad[5], ad[4], ad[3], ad[2]} ^ 8'h37 ^ prv[7:0];
101 | prv[7:0] <= ad[15:8];
102 | */
103 | void (*dma_busy_callback)();
104 |
105 |
106 | void evd_setDmaAddr(u32 addr) {
107 |
108 | }
109 |
110 |
111 | inline u32 bi_reg_rd(u32 reg) {
112 |
113 | *(vu32 *) (REGS_BASE);
114 | return *(vu32 *) (REGS_BASE + reg * 4);
115 | }
116 |
117 | inline void bi_reg_wr(u32 reg, u32 data) {
118 |
119 | *(vu32 *) (REGS_BASE);
120 | *(vu32 *) (REGS_BASE + reg * 4) = data;
121 | }
122 |
123 |
124 | void bi_init() {
125 |
126 | evd_cfg = ED_CFG_SDRAM_ON;
127 | spi_cfg = 0 | BI_SPI_SPD_LO;
128 | bi_reg_wr(REG_KEY, 0x1234);
129 | bi_reg_wr(REG_CFG, evd_cfg);
130 | bi_reg_wr(REG_SPI_CFG, spi_cfg);
131 | }
132 |
133 | void bi_speed50() {
134 |
135 | spi_cfg = 0 | BI_SPI_SPD_50;
136 | bi_reg_wr(REG_KEY, 0x1234);
137 | bi_reg_wr(REG_SPI_CFG, spi_cfg);
138 | }
139 |
140 | void bi_speed25() {
141 |
142 | spi_cfg = 0 | BI_SPI_SPD_25;
143 | bi_reg_wr(REG_KEY, 0x1234);
144 | bi_reg_wr(REG_SPI_CFG, spi_cfg);
145 | }
146 |
147 | void bi_load_firmware(u8 *firm) {
148 |
149 | u32 i;
150 | u16 f_ctr = 0;
151 |
152 | evd_cfg &= ~ED_CFG_SDRAM_ON;
153 | bi_reg_wr(REG_CFG, evd_cfg);
154 |
155 | bi_reg_wr(REG_CFG_CNT, 0);
156 | sleep(10);
157 | bi_reg_wr(REG_CFG_CNT, 1);
158 | sleep(10);
159 |
160 | i = 0;
161 | for (;;) {
162 |
163 | bi_reg_wr(REG_CFG_DAT, *(u16 *) & firm[i]);
164 | while ((bi_reg_rd(REG_CFG_CNT) & 8) != 0);
165 |
166 | f_ctr = firm[i++] == 0xff ? f_ctr + 1 : 0;
167 | if (f_ctr >= 47)break;
168 | f_ctr = firm[i++] == 0xff ? f_ctr + 1 : 0;
169 | if (f_ctr >= 47)break;
170 | }
171 |
172 | while ((bi_reg_rd(REG_CFG_CNT) & 4) == 0) {
173 | bi_reg_wr(REG_CFG_DAT, 0xffff);
174 | while ((bi_reg_rd(REG_CFG_CNT) & 8) != 0);
175 | }
176 |
177 | sleep(20);
178 |
179 | bi_init();
180 | }
181 |
182 |
183 | void evd_init() {
184 |
185 | volatile u8 val;
186 | sd_mode = 0;
187 | dma_busy_callback = 0;
188 |
189 | sleep(1);
190 | val = regs_ptr[0];
191 |
192 | spi_cfg = (0 << SPI_CFG_SPD0) | (1 << SPI_CFG_SPD1) | (1 << SPI_CFG_SS);
193 | evd_cfg = (1 << ED_CFG_SDRAM_ON);
194 |
195 | val = regs_ptr[0];
196 | regs_ptr[REG_KEY] = 0x1234;
197 |
198 | val = regs_ptr[0];
199 | regs_ptr[REG_CFG] = evd_cfg;
200 | val = regs_ptr[0];
201 | regs_ptr[REG_SPI_CFG] = spi_cfg;
202 |
203 | evd_fifoRxf();
204 | if (!evd_fifoRxf()) {
205 |
206 | val = regs_ptr[0];
207 | regs_ptr[REG_DMA_LEN] = 7; //clean 16k
208 | val = regs_ptr[0];
209 | regs_ptr[REG_DMA_RAM_ADDR] = (ROM_LEN - 0x200000) / 2048;
210 | val = regs_ptr[0];
211 | regs_ptr[REG_DMA_CFG] = DCFG_FIFO_TO_RAM;
212 | while (evd_isDmaBusy());
213 | }
214 | }
215 |
216 | void evd_ulockRegs(){
217 |
218 | volatile u8 val;
219 |
220 | val = regs_ptr[0];
221 | regs_ptr[REG_KEY] = 0x1234;
222 | }
223 |
224 | void evd_lockRegs() {
225 |
226 | volatile u8 val;
227 |
228 | val = regs_ptr[0];
229 | regs_ptr[REG_KEY] = 0;
230 | }
231 |
232 | u8 evd_fifoRxf() {
233 |
234 | u16 val;
235 | //regs_ptr[REG_STATE]++;
236 | val = regs_ptr[REG_STATUS];
237 |
238 | return (val >> ED_STATE_RXF) & 1;
239 | }
240 |
241 | u8 evd_fifoTxe() {
242 |
243 | u16 val;
244 | //regs_ptr[REG_STATE]++;
245 | val = regs_ptr[REG_STATUS];
246 |
247 | return (val >> ED_STATE_TXE) & 1;
248 | }
249 |
250 | u8 evd_isDmaBusy() {
251 |
252 | u16 val;
253 | //volatile u32 i;
254 | sleep(1);
255 | if(dma_busy_callback != 0)dma_busy_callback();
256 | //regs_ptr[REG_STATE]++;
257 | val = regs_ptr[REG_STATUS];
258 |
259 | return (val >> ED_STATE_DMA_BUSY) & 1;
260 | }
261 |
262 | u8 evd_isDmaTimeout() {
263 |
264 | u16 val;
265 | //regs_ptr[REG_STATE]++;
266 | val = regs_ptr[REG_STATUS];
267 |
268 | return (val >> ED_STATE_DMA_TOUT) & 1;
269 | }
270 |
271 | u8 evd_fifoRdToCart(u32 cart_addr, u16 blocks) {
272 |
273 | volatile u8 val;
274 | cart_addr /= 2048;
275 |
276 | val = regs_ptr[0];
277 | regs_ptr[REG_DMA_LEN] = (blocks - 1);
278 | val = regs_ptr[0];
279 | regs_ptr[REG_DMA_RAM_ADDR] = cart_addr;
280 | val = regs_ptr[0];
281 | regs_ptr[REG_DMA_CFG] = DCFG_FIFO_TO_RAM;
282 |
283 | while (evd_isDmaBusy());
284 | if (evd_isDmaTimeout())return EVD_ERROR_FIFO_TIMEOUT;
285 |
286 | return 0;
287 | }
288 |
289 | u8 evd_fifoWrFromCart(u32 cart_addr, u16 blocks) {
290 |
291 | volatile u8 val;
292 | cart_addr /= 2048;
293 |
294 | val = regs_ptr[0];
295 | regs_ptr[REG_DMA_LEN] = (blocks - 1);
296 | val = regs_ptr[0];
297 | regs_ptr[REG_DMA_RAM_ADDR] = cart_addr;
298 | val = regs_ptr[0];
299 | regs_ptr[REG_DMA_CFG] = DCFG_RAM_TO_FIFO;
300 |
301 | while (evd_isDmaBusy());
302 | if (evd_isDmaTimeout())return EVD_ERROR_FIFO_TIMEOUT;
303 |
304 | return 0;
305 | }
306 |
307 | u8 evd_fifoRd(void *buff, u16 blocks) {
308 |
309 | volatile u8 val;
310 | u32 len = blocks == 0 ? 65536 * 512 : blocks * 512;
311 | u32 ram_buff_addr = DMA_BUFF_ADDR / 2048; //(ROM_LEN - len - 65536 * 4) / 2048;
312 |
313 | val = regs_ptr[0];
314 | regs_ptr[REG_DMA_LEN] = (blocks - 1);
315 | val = regs_ptr[0];
316 | regs_ptr[REG_DMA_RAM_ADDR] = ram_buff_addr;
317 | val = regs_ptr[0];
318 | regs_ptr[REG_DMA_CFG] = DCFG_FIFO_TO_RAM;
319 |
320 | while (evd_isDmaBusy());
321 | dma_read_s(buff, (0xb0000000 + ram_buff_addr * 2048), len);
322 | if (evd_isDmaTimeout())return EVD_ERROR_FIFO_TIMEOUT;
323 |
324 | return 0;
325 | }
326 |
327 |
328 |
329 | u8 evd_fifoWr(void *buff, u16 blocks) {
330 |
331 | volatile u8 val;
332 | u32 len = blocks == 0 ? 65536 * 512 : blocks * 512;
333 | u32 ram_buff_addr = DMA_BUFF_ADDR / 2048; //(ROM_LEN - len - 65536 * 4) / 2048;
334 |
335 | dma_write_s(buff, (0xb0000000 + ram_buff_addr * 1024 * 2), len);
336 |
337 | val = regs_ptr[0];
338 | regs_ptr[REG_DMA_LEN] = (blocks - 1);
339 | val = regs_ptr[0];
340 | regs_ptr[REG_DMA_RAM_ADDR] = ram_buff_addr;
341 | val = regs_ptr[0];
342 | regs_ptr[REG_DMA_CFG] = DCFG_RAM_TO_FIFO;
343 |
344 | while (evd_isDmaBusy());
345 | if (evd_isDmaTimeout())return EVD_ERROR_FIFO_TIMEOUT;
346 |
347 | return 0;
348 | }
349 |
350 | u8 evd_isSpiBusy() {
351 |
352 | volatile u16 val;
353 |
354 | regs_ptr[REG_STATUS];
355 | val = regs_ptr[REG_STATUS];
356 |
357 | return (val >> ED_STATE_SPI) & 1;
358 | }
359 |
360 | u8 evd_SPI(u8 dat) {
361 |
362 | volatile u8 val;
363 |
364 | val = regs_ptr[0];
365 | regs_ptr[REG_SPI] = dat;
366 | while (evd_isSpiBusy());
367 | //osInvalICache((u32*) & regs_ptr[REG_SPI], 1);
368 | val = regs_ptr[REG_SPI];
369 |
370 | return val;
371 | }
372 |
373 | void evd_spiSSOn() {
374 |
375 | volatile u8 val;
376 |
377 | if (sd_mode)return;
378 | spi_cfg &= ~(1 << SPI_CFG_SS);
379 | val = regs_ptr[0];
380 | regs_ptr[REG_SPI_CFG] = spi_cfg;
381 | }
382 |
383 | void evd_spiSSOff() {
384 |
385 | volatile u8 val;
386 |
387 | spi_cfg |= (1 << SPI_CFG_SS);
388 | val = regs_ptr[0];
389 | regs_ptr[REG_SPI_CFG] = spi_cfg;
390 | }
391 |
392 | void evd_enableSDMode() {
393 |
394 | sd_mode = 1;
395 | }
396 |
397 | void evd_enableSPIMode() {
398 |
399 | sd_mode = 0;
400 | }
401 |
402 | u8 evd_isSDMode() {
403 |
404 | return sd_mode;
405 | }
406 |
407 | void evd_SDcmdWriteMode(u8 bit1_mode) {
408 |
409 | volatile u8 val;
410 |
411 | if (!sd_mode)return;
412 | spi_cfg &= ~((1 << SPI_CFG_RD) | (1 << SPI_CFG_DAT));
413 | if (bit1_mode) {
414 | spi_cfg |= (1 << SPI_CFG_1BIT);
415 | } else {
416 | spi_cfg &= ~(1 << SPI_CFG_1BIT);
417 | }
418 | val = regs_ptr[0];
419 | regs_ptr[REG_SPI_CFG] = spi_cfg;
420 |
421 | }
422 |
423 | void evd_SDcmdReadMode(u8 bit1_mode) {
424 |
425 | volatile u8 val;
426 |
427 | if (!sd_mode)return;
428 | spi_cfg |= (1 << SPI_CFG_RD);
429 | spi_cfg &= ~(1 << SPI_CFG_DAT);
430 | if (bit1_mode) {
431 | spi_cfg |= (1 << SPI_CFG_1BIT);
432 | } else {
433 | spi_cfg &= ~(1 << SPI_CFG_1BIT);
434 | }
435 | val = regs_ptr[0];
436 | regs_ptr[REG_SPI_CFG] = spi_cfg;
437 | }
438 |
439 | void evd_SDdatWriteMode(u8 bit4_mode) {
440 |
441 | volatile u8 val;
442 |
443 | if (!sd_mode)return;
444 | spi_cfg &= ~(1 << SPI_CFG_RD);
445 | spi_cfg |= (1 << SPI_CFG_DAT);
446 | if (bit4_mode) {
447 | spi_cfg |= (1 << SPI_CFG_1BIT);
448 | } else {
449 | spi_cfg &= ~(1 << SPI_CFG_1BIT);
450 | }
451 | val = regs_ptr[0];
452 | regs_ptr[REG_SPI_CFG] = spi_cfg;
453 | }
454 |
455 | void evd_SDdatReadMode(u8 bit4_mode) {
456 |
457 | volatile u8 val;
458 |
459 | if (!sd_mode)return;
460 | spi_cfg |= (1 << SPI_CFG_RD) | (1 << SPI_CFG_DAT);
461 | if (bit4_mode) {
462 | spi_cfg |= (1 << SPI_CFG_1BIT);
463 | } else {
464 | spi_cfg &= ~(1 << SPI_CFG_1BIT);
465 | }
466 | val = regs_ptr[0];
467 | regs_ptr[REG_SPI_CFG] = spi_cfg;
468 | }
469 |
470 | void evd_setSpiSpeed(u8 speed) {
471 |
472 | volatile u8 val;
473 |
474 | spi_cfg &= ~3; //((1 << SPI_CFG_SPD0) | (1 << SPI_CFG_SPD1));
475 | spi_cfg |= speed & 3;
476 | val = regs_ptr[0];
477 | regs_ptr[REG_SPI_CFG] = spi_cfg;
478 | }
479 |
480 | u8 evd_mmcReadToCart(u32 cart_addr, u32 len) {
481 |
482 | volatile u8 val;
483 | cart_addr /= 2048;
484 |
485 | val = regs_ptr[0];
486 | regs_ptr[REG_DMA_LEN] = (len - 1);
487 | val = regs_ptr[0];
488 | regs_ptr[REG_DMA_RAM_ADDR] = cart_addr;
489 | val = regs_ptr[0];
490 | regs_ptr[REG_DMA_CFG] = DCFG_SD_TO_RAM;
491 |
492 | while (evd_isDmaBusy());
493 | if (evd_isDmaTimeout())return EVD_ERROR_MMC_TIMEOUT;
494 |
495 | return 0;
496 | }
497 |
498 | void evd_setCfgBit(u8 option, u8 state) {
499 |
500 | volatile u8 val;
501 |
502 | if (state)evd_cfg |= (1 << option);
503 | else
504 | evd_cfg &= ~(1 << option);
505 |
506 | val = regs_ptr[0];
507 | regs_ptr[REG_CFG] = evd_cfg;
508 | val = regs_ptr[0];
509 | }
510 |
511 | u16 evd_readReg(u8 reg) {
512 |
513 | volatile u32 tmp;
514 |
515 | tmp = regs_ptr[0];
516 |
517 | return regs_ptr[reg];
518 | }
519 |
520 | void evd_setSaveType(u8 type) {
521 |
522 | u8 eeprom_on, sram_on, eeprom_size, sram_size;
523 | eeprom_on = 0;
524 | sram_on = 0;
525 | eeprom_size = 0;
526 | sram_size = 0;
527 |
528 | switch (type) {
529 | case SAVE_TYPE_EEP16k:
530 | eeprom_on = 1;
531 | eeprom_size = 1;
532 | break;
533 | case SAVE_TYPE_EEP4k:
534 | eeprom_on = 1;
535 | break;
536 | case SAVE_TYPE_SRAM:
537 | sram_on = 1;
538 | break;
539 | case SAVE_TYPE_SRAM128:
540 | sram_on = 1;
541 | sram_size = 1;
542 | break;
543 | case SAVE_TYPE_FLASH:
544 | sram_on = 0;
545 | sram_size = 1;
546 | break;
547 | case SAVE_TYPE_SRAM768:
548 | sram_on = 1;
549 | sram_size = 1;
550 | break;
551 | default:
552 | sram_on = 0;
553 | sram_size = 0;
554 | break;
555 | }
556 |
557 | volatile u8 val;
558 | val = regs_ptr[0];
559 | regs_ptr[REG_SAV_CFG] = (eeprom_on << SAV_EEP_ON | sram_on << SAV_SRM_ON | eeprom_size << SAV_EEP_SIZE | sram_size << SAV_SRM_SIZE);
560 | }
561 |
562 | void evd_writeReg(u8 reg, u16 val) {
563 |
564 | volatile u8 tmp;
565 | tmp = regs_ptr[0];
566 | regs_ptr[reg] = val;
567 | }
568 |
569 | void evd_mmcSetDmaSwap(u8 state) {
570 |
571 | evd_setCfgBit(ED_CFG_SWAP, state);
572 | }
573 |
574 | void evd_writeMsg(u8 dat) {
575 |
576 | evd_writeReg(REG_MSG, dat);
577 | }
578 |
579 | u8 evd_readMsg() {
580 |
581 | return evd_readReg(REG_MSG);
582 | }
583 |
584 | u16 evd_getFirmVersion() {
585 |
586 | return evd_readReg(REG_VER);
587 | }
588 |
589 |
590 | void evd_setDmaCallback(void (*callback)()) {
591 |
592 | dma_busy_callback = callback;
593 | }
594 |
--------------------------------------------------------------------------------
/src/ffsystem.c:
--------------------------------------------------------------------------------
1 | /*------------------------------------------------------------------------*/
2 | /* A Sample Code of User Provided OS Dependent Functions for FatFs */
3 | /*------------------------------------------------------------------------*/
4 |
5 | #include "ff.h"
6 |
7 |
8 | #if FF_USE_LFN == 3 /* Use dynamic memory allocation */
9 |
10 | /*------------------------------------------------------------------------*/
11 | /* Allocate/Free a Memory Block */
12 | /*------------------------------------------------------------------------*/
13 |
14 | #include /* with POSIX API */
15 |
16 |
17 | void* ff_memalloc ( /* Returns pointer to the allocated memory block (null if not enough core) */
18 | UINT msize /* Number of bytes to allocate */
19 | )
20 | {
21 | return malloc((size_t)msize); /* Allocate a new memory block */
22 | }
23 |
24 |
25 | void ff_memfree (
26 | void* mblock /* Pointer to the memory block to free (no effect if null) */
27 | )
28 | {
29 | free(mblock); /* Free the memory block */
30 | }
31 |
32 | #endif
33 |
34 |
35 |
36 |
37 | #if FF_FS_REENTRANT /* Mutal exclusion */
38 | /*------------------------------------------------------------------------*/
39 | /* Definitions of Mutex */
40 | /*------------------------------------------------------------------------*/
41 |
42 | #define OS_TYPE 0 /* 0:Win32, 1:uITRON4.0, 2:uC/OS-II, 3:FreeRTOS, 4:CMSIS-RTOS */
43 |
44 |
45 | #if OS_TYPE == 0 /* Win32 */
46 | #include
47 | static HANDLE Mutex[FF_VOLUMES + 1]; /* Table of mutex handle */
48 |
49 | #elif OS_TYPE == 1 /* uITRON */
50 | #include "itron.h"
51 | #include "kernel.h"
52 | static mtxid Mutex[FF_VOLUMES + 1]; /* Table of mutex ID */
53 |
54 | #elif OS_TYPE == 2 /* uc/OS-II */
55 | #include "includes.h"
56 | static OS_EVENT *Mutex[FF_VOLUMES + 1]; /* Table of mutex pinter */
57 |
58 | #elif OS_TYPE == 3 /* FreeRTOS */
59 | #include "FreeRTOS.h"
60 | #include "semphr.h"
61 | static SemaphoreHandle_t Mutex[FF_VOLUMES + 1]; /* Table of mutex handle */
62 |
63 | #elif OS_TYPE == 4 /* CMSIS-RTOS */
64 | #include "cmsis_os.h"
65 | static osMutexId Mutex[FF_VOLUMES + 1]; /* Table of mutex ID */
66 |
67 | #endif
68 |
69 |
70 |
71 | /*------------------------------------------------------------------------*/
72 | /* Create a Mutex */
73 | /*------------------------------------------------------------------------*/
74 | /* This function is called in f_mount function to create a new mutex
75 | / or semaphore for the volume. When a 0 is returned, the f_mount function
76 | / fails with FR_INT_ERR.
77 | */
78 |
79 | int ff_mutex_create ( /* Returns 1:Function succeeded or 0:Could not create the mutex */
80 | int vol /* Mutex ID: Volume mutex (0 to FF_VOLUMES - 1) or system mutex (FF_VOLUMES) */
81 | )
82 | {
83 | #if OS_TYPE == 0 /* Win32 */
84 | Mutex[vol] = CreateMutex(NULL, FALSE, NULL);
85 | return (int)(Mutex[vol] != INVALID_HANDLE_VALUE);
86 |
87 | #elif OS_TYPE == 1 /* uITRON */
88 | T_CMTX cmtx = {TA_TPRI,1};
89 |
90 | Mutex[vol] = acre_mtx(&cmtx);
91 | return (int)(Mutex[vol] > 0);
92 |
93 | #elif OS_TYPE == 2 /* uC/OS-II */
94 | OS_ERR err;
95 |
96 | Mutex[vol] = OSMutexCreate(0, &err);
97 | return (int)(err == OS_NO_ERR);
98 |
99 | #elif OS_TYPE == 3 /* FreeRTOS */
100 | Mutex[vol] = xSemaphoreCreateMutex();
101 | return (int)(Mutex[vol] != NULL);
102 |
103 | #elif OS_TYPE == 4 /* CMSIS-RTOS */
104 | osMutexDef(cmsis_os_mutex);
105 |
106 | Mutex[vol] = osMutexCreate(osMutex(cmsis_os_mutex));
107 | return (int)(Mutex[vol] != NULL);
108 |
109 | #endif
110 | }
111 |
112 |
113 | /*------------------------------------------------------------------------*/
114 | /* Delete a Mutex */
115 | /*------------------------------------------------------------------------*/
116 | /* This function is called in f_mount function to delete a mutex or
117 | / semaphore of the volume created with ff_mutex_create function.
118 | */
119 |
120 | void ff_mutex_delete ( /* Returns 1:Function succeeded or 0:Could not delete due to an error */
121 | int vol /* Mutex ID: Volume mutex (0 to FF_VOLUMES - 1) or system mutex (FF_VOLUMES) */
122 | )
123 | {
124 | #if OS_TYPE == 0 /* Win32 */
125 | CloseHandle(Mutex[vol]);
126 |
127 | #elif OS_TYPE == 1 /* uITRON */
128 | del_mtx(Mutex[vol]);
129 |
130 | #elif OS_TYPE == 2 /* uC/OS-II */
131 | OS_ERR err;
132 |
133 | OSMutexDel(Mutex[vol], OS_DEL_ALWAYS, &err);
134 |
135 | #elif OS_TYPE == 3 /* FreeRTOS */
136 | vSemaphoreDelete(Mutex[vol]);
137 |
138 | #elif OS_TYPE == 4 /* CMSIS-RTOS */
139 | osMutexDelete(Mutex[vol]);
140 |
141 | #endif
142 | }
143 |
144 |
145 | /*------------------------------------------------------------------------*/
146 | /* Request a Grant to Access the Volume */
147 | /*------------------------------------------------------------------------*/
148 | /* This function is called on enter file functions to lock the volume.
149 | / When a 0 is returned, the file function fails with FR_TIMEOUT.
150 | */
151 |
152 | int ff_mutex_take ( /* Returns 1:Succeeded or 0:Timeout */
153 | int vol /* Mutex ID: Volume mutex (0 to FF_VOLUMES - 1) or system mutex (FF_VOLUMES) */
154 | )
155 | {
156 | #if OS_TYPE == 0 /* Win32 */
157 | return (int)(WaitForSingleObject(Mutex[vol], FF_FS_TIMEOUT) == WAIT_OBJECT_0);
158 |
159 | #elif OS_TYPE == 1 /* uITRON */
160 | return (int)(tloc_mtx(Mutex[vol], FF_FS_TIMEOUT) == E_OK);
161 |
162 | #elif OS_TYPE == 2 /* uC/OS-II */
163 | OS_ERR err;
164 |
165 | OSMutexPend(Mutex[vol], FF_FS_TIMEOUT, &err));
166 | return (int)(err == OS_NO_ERR);
167 |
168 | #elif OS_TYPE == 3 /* FreeRTOS */
169 | return (int)(xSemaphoreTake(Mutex[vol], FF_FS_TIMEOUT) == pdTRUE);
170 |
171 | #elif OS_TYPE == 4 /* CMSIS-RTOS */
172 | return (int)(osMutexWait(Mutex[vol], FF_FS_TIMEOUT) == osOK);
173 |
174 | #endif
175 | }
176 |
177 |
178 |
179 | /*------------------------------------------------------------------------*/
180 | /* Release a Grant to Access the Volume */
181 | /*------------------------------------------------------------------------*/
182 | /* This function is called on leave file functions to unlock the volume.
183 | */
184 |
185 | void ff_mutex_give (
186 | int vol /* Mutex ID: Volume mutex (0 to FF_VOLUMES - 1) or system mutex (FF_VOLUMES) */
187 | )
188 | {
189 | #if OS_TYPE == 0 /* Win32 */
190 | ReleaseMutex(Mutex[vol]);
191 |
192 | #elif OS_TYPE == 1 /* uITRON */
193 | unl_mtx(Mutex[vol]);
194 |
195 | #elif OS_TYPE == 2 /* uC/OS-II */
196 | OSMutexPost(Mutex[vol]);
197 |
198 | #elif OS_TYPE == 3 /* FreeRTOS */
199 | xSemaphoreGive(Mutex[vol]);
200 |
201 | #elif OS_TYPE == 4 /* CMSIS-RTOS */
202 | osMutexRelease(Mutex[vol]);
203 |
204 | #endif
205 | }
206 |
207 | #endif /* FF_FS_REENTRANT */
208 |
209 |
--------------------------------------------------------------------------------
/src/hashtable.c:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 The Altra64 project contributors
3 | // Portions (c) 2011 @marekweb https://github.com/marekweb/datastructs-c
4 | // See LICENSE file in the project root for full license information.
5 | //
6 |
7 | /**
8 | * Hashtable implementation
9 | * Uses dynamic addressing with linear probing.
10 | */
11 |
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include "hashtable.h"
17 |
18 | /*
19 | * Interface section used for `makeheaders`.
20 | */
21 | #if INTERFACE
22 | struct hashtable_entry {
23 | char* key;
24 | void* value;
25 | };
26 |
27 | struct hashtable {
28 | unsigned int size;
29 | unsigned int capacity;
30 | hashtable_entry* body;
31 | };
32 | #endif
33 |
34 | #define HASHTABLE_INITIAL_CAPACITY 2
35 |
36 | /**
37 | * Compute the hash value for the given string.
38 | * Implements the djb k=33 hash function.
39 | */
40 | unsigned long hashtable_hash(char* str)
41 | {
42 | unsigned long hash = 5381;
43 | int c;
44 | while ((c = *str++))
45 | hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
46 | return hash;
47 | }
48 |
49 | /**
50 | * Find an available slot for the given key, using linear probing.
51 | */
52 | unsigned int hashtable_find_slot(hashtable* t, char* key)
53 | {
54 | int index = hashtable_hash(key) % t->capacity;
55 | while (t->body[index].key != NULL && strcmp(t->body[index].key, key) != 0) {
56 | index = (index + 1) % t->capacity;
57 | }
58 | return index;
59 | }
60 |
61 | /**
62 | * Return the item associated with the given key, or NULL if not found.
63 | */
64 | void* hashtable_get(hashtable* t, char* key)
65 | {
66 | int index = hashtable_find_slot(t, key);
67 | if (t->body[index].key != NULL) {
68 | return t->body[index].value;
69 | } else {
70 | return NULL;
71 | }
72 | }
73 |
74 | /**
75 | * Assign a value to the given key in the table.
76 | */
77 | void hashtable_set(hashtable* t, char* key, void* value)
78 | {
79 | int index = hashtable_find_slot(t, key);
80 | if (t->body[index].key != NULL) {
81 | /* Entry exists; update it. */
82 | t->body[index].value = value;
83 | } else {
84 | t->size++;
85 | /* Create a new entry */
86 | if ((float)t->size / t->capacity > 0.8) {
87 | /* Resize the hash table */
88 | hashtable_resize(t, t->capacity * 2);
89 | index = hashtable_find_slot(t, key);
90 | }
91 | t->body[index].key = key;
92 | t->body[index].value = value;
93 | }
94 | }
95 |
96 | /**
97 | * Remove a key from the table
98 | */
99 | void hashtable_remove(hashtable* t, char* key)
100 | {
101 | int index = hashtable_find_slot(t, key);
102 | if (t->body[index].key != NULL) {
103 | t->body[index].key = NULL;
104 | t->body[index].value = NULL;
105 | t->size--;
106 | }
107 | }
108 |
109 | /**
110 | * Create a new, empty hashtable
111 | */
112 | hashtable* hashtable_create()
113 | {
114 | hashtable* new_ht = malloc(sizeof(hashtable));
115 | new_ht->size = 0;
116 | new_ht->capacity = HASHTABLE_INITIAL_CAPACITY;
117 | new_ht->body = hashtable_body_allocate(new_ht->capacity);
118 | return new_ht;
119 | }
120 |
121 | #if 0
122 | /**
123 | * Adds all items from another table.
124 | */
125 | hashtable* hashtable_merge(hashtable* ht, hashtable* other)
126 | {
127 | }
128 | #endif
129 |
130 | /**
131 | * Allocate a new memory block with the given capacity.
132 | */
133 | hashtable_entry* hashtable_body_allocate(unsigned int capacity)
134 | {
135 | return (hashtable_entry*)calloc(capacity, sizeof(hashtable_entry));
136 | }
137 |
138 | /**
139 | * Resize the allocated memory.
140 | * Warning: clears the table of all entries.
141 | */
142 | void hashtable_resize(hashtable* t, unsigned int capacity)
143 | {
144 | assert(capacity >= t->size);
145 | unsigned int old_capacity = t->capacity;
146 | hashtable_entry* old_body = t->body;
147 | t->body = hashtable_body_allocate(capacity);
148 | t->capacity = capacity;
149 | for (int i = 0; i < old_capacity; i++) {
150 | if (old_body[i].key != NULL) {
151 | hashtable_set(t, old_body[i].key, old_body[i].value);
152 | }
153 | }
154 | }
155 |
156 | /**
157 | * Destroy the table and deallocate it from memory. This does not deallocate the contained items.
158 | */
159 | void hashtable_destroy(hashtable* t)
160 | {
161 | free(t->body);
162 | free(t);
163 | }
164 |
--------------------------------------------------------------------------------
/src/image.c:
--------------------------------------------------------------------------------
1 |
2 | #include
3 | #include "types.h"
4 | #include "image.h"
5 |
6 | //#define STBI_HEADER_FILE_ONLY
7 | #define STB_IMAGE_IMPLEMENTATION
8 | #include "stb_image.h"
9 |
10 |
11 | /*
12 | * Load an image from the rom filesystem, returning a pointer to the
13 | * sprite that hold the image.
14 | */
15 | sprite_t *loadImageDFS(char *fname) {
16 | int size, x, y, n, fd;
17 | u8 *tbuf;
18 | u8 *ibuf;
19 | sprite_t *sbuf;
20 |
21 | fd = dfs_open(fname);
22 | if (fd < 0)
23 | return 0; // couldn't open image
24 |
25 | size = dfs_size(fd);
26 | tbuf = malloc(size);
27 | if (!tbuf) {
28 | dfs_close(fd);
29 | return 0; // out of memory
30 | }
31 |
32 | dfs_read(tbuf, 1, size, fd);
33 | dfs_close(fd);
34 |
35 | ibuf = stbi_load_from_memory(tbuf, size, &x, &y, &n, 4);
36 | free(tbuf);
37 | if (!ibuf)
38 | return 0; // couldn't decode image
39 |
40 | sbuf = (sprite_t*)malloc(sizeof(sprite_t) + x * y * 2);
41 | if (!sbuf) {
42 | stbi_image_free(ibuf);
43 | return 0; // out of memory
44 | }
45 | sbuf->width = x;
46 | sbuf->height = y;
47 | sbuf->bitdepth = 2;
48 | sbuf->format = 0;
49 | sbuf->hslices = x / 32;
50 | sbuf->vslices = y / 16;
51 |
52 | color_t *src = (color_t*)ibuf;
53 | u16 *dst = (u16*)((u32)sbuf + sizeof(sprite_t));
54 |
55 | for (int j=0; jdata, sbuf->width * sbuf->height * sbuf->bitdepth );
61 |
62 | stbi_image_free(ibuf);
63 | return sbuf;
64 | }
65 |
66 |
67 | sprite_t *loadImage32(u8 *png, int size) {
68 | int x, y, n, fd;
69 | u8 *tbuf;
70 | u32 *ibuf;
71 | sprite_t *sbuf;
72 |
73 | tbuf = malloc(size);
74 | memcpy(tbuf,png,size);
75 |
76 | ibuf = (u32*)stbi_load_from_memory(tbuf, size, &x, &y, &n, 4);
77 | free(tbuf);
78 | if (!ibuf)
79 | return 0; // couldn't decode image
80 |
81 | sbuf = (sprite_t*)malloc(sizeof(sprite_t) + x * y * 4);
82 | if (!sbuf) {
83 | stbi_image_free(ibuf);
84 | return 0; // out of memory
85 | }
86 |
87 | sbuf->width = x;
88 | sbuf->height = y;
89 | sbuf->bitdepth = 4;
90 | sbuf->format = 0;
91 | sbuf->hslices = x / 32;
92 | sbuf->vslices = y / 32;
93 |
94 | // color_t *src = (color_t*)ibuf;
95 | u32 *dst = (u32*)((u32)sbuf + sizeof(sprite_t));
96 |
97 | for (int j=0; jdata, sbuf->width * sbuf->height * sbuf->bitdepth );
103 |
104 | stbi_image_free(ibuf);
105 | return sbuf;
106 | }
107 |
108 | sprite_t *loadImage32DFS(char *fname) {
109 | int size, x, y, n, fd;
110 | u8 *tbuf;
111 | u32 *ibuf;
112 | sprite_t *sbuf;
113 |
114 | fd = dfs_open(fname);
115 | if (fd < 0)
116 | return 0; // couldn't open image
117 |
118 | size = dfs_size(fd);
119 | tbuf = malloc(size);
120 | if (!tbuf) {
121 | dfs_close(fd);
122 | return 0; // out of memory
123 | }
124 |
125 | dfs_read(tbuf, 1, size, fd);
126 | dfs_close(fd);
127 |
128 | ibuf = (u32*)stbi_load_from_memory(tbuf, size, &x, &y, &n, 4);
129 | free(tbuf);
130 | if (!ibuf)
131 | return 0; // couldn't decode image
132 |
133 | sbuf = (sprite_t*)malloc(sizeof(sprite_t) + x * y * 4);
134 | if (!sbuf) {
135 | stbi_image_free(ibuf);
136 | return 0; // out of memory
137 | }
138 |
139 | sbuf->width = x;
140 | sbuf->height = y;
141 | sbuf->bitdepth = 4;
142 | sbuf->format = 0;
143 | sbuf->hslices = x / 32;
144 | sbuf->vslices = y / 32;
145 |
146 | // color_t *src = (color_t*)ibuf;
147 | u32 *dst = (u32*)((u32)sbuf + sizeof(sprite_t));
148 |
149 | for (int j=0; jdata, sbuf->width * sbuf->height * sbuf->bitdepth );
155 |
156 | stbi_image_free(ibuf);
157 | return sbuf;
158 | }
159 |
160 | /*
161 | * Draw an image to the screen using the sprite passed.
162 | */
163 | void drawImage(display_context_t dcon, sprite_t *sprite) {
164 | int x, y = 0;
165 |
166 | rdp_sync(SYNC_PIPE);
167 | rdp_set_default_clipping();
168 | rdp_enable_texture_copy();
169 | rdp_attach_display(dcon);
170 | // Draw image
171 | for (int j=0; jvslices; j++) {
172 | x = 0;
173 | for (int i=0; ihslices; i++) {
174 | rdp_sync(SYNC_PIPE);
175 | rdp_load_texture_stride(0, 0, MIRROR_DISABLED, sprite, j*sprite->hslices + i);
176 | rdp_draw_sprite(0, x, y);
177 | x += 32;
178 | }
179 | y += 16;
180 | }
181 | rdp_detach_display();
182 | }
--------------------------------------------------------------------------------
/src/ini.c:
--------------------------------------------------------------------------------
1 | /* inih -- simple .INI file parser
2 |
3 | inih is released under the New BSD license (see LICENSE.txt). Go to the project
4 | home page for more info:
5 |
6 | http://code.google.com/p/inih/
7 |
8 | */
9 |
10 | #include
11 | #include
12 | #include
13 |
14 |
15 | #include "ini.h"
16 |
17 | #if !INI_USE_STACK
18 | #include
19 | #endif
20 |
21 | #define MAX_SECTION 50
22 | #define MAX_NAME 50
23 |
24 |
25 | /* Strip whitespace chars off end of given string, in place. Return s. */
26 | static char* rstrip(char* s)
27 | {
28 | char* p = s + strlen(s);
29 | while (p > s && isspace((unsigned char)(*--p)))
30 | *p = '\0';
31 | return s;
32 | }
33 |
34 | /* Return pointer to first non-whitespace char in given string. */
35 | static char* lskip(const char* s)
36 | {
37 | while (*s && isspace((unsigned char)(*s)))
38 | s++;
39 | return (char*)s;
40 | }
41 |
42 | /* Return pointer to first char c or ';' comment in given string, or pointer to
43 | null at end of string if neither found. ';' must be prefixed by a whitespace
44 | character to register as a comment. */
45 | static char* find_char_or_comment(const char* s, char c)
46 | {
47 | int was_whitespace = 0;
48 | while (*s && *s != c && !(was_whitespace && *s == ';')) {
49 | was_whitespace = isspace((unsigned char)(*s));
50 | s++;
51 | }
52 | return (char*)s;
53 | }
54 |
55 | /* Version of strncpy that ensures dest (size bytes) is null-terminated. */
56 | static char* strncpy0(char* dest, const char* src, size_t size)
57 | {
58 | strncpy(dest, src, size);
59 | dest[size - 1] = '\0';
60 | return dest;
61 | }
62 |
63 |
64 | /* See documentation in header file. */
65 | int ini_parse_str(char* ini_string,
66 | int (*handler)(void*, const char*, const char*,
67 | const char*),
68 | void* user)
69 | {
70 | /* Uses a fair bit of stack (use heap instead if you need to) */
71 | #if INI_USE_STACK
72 | char line[INI_MAX_LINE];
73 | #else
74 | char* line;
75 | #endif
76 | char section[MAX_SECTION] = "";
77 | char prev_name[MAX_NAME] = "";
78 |
79 | char* start;
80 | char* end;
81 | char* name;
82 | char* value;
83 | int lineno = 0;
84 | int error = 0;
85 |
86 | #if !INI_USE_STACK
87 | line = (char*)malloc(INI_MAX_LINE);
88 | if (!line) {
89 | return -2;
90 | }
91 | #endif
92 |
93 |
94 | int i=1;
95 | char *ptr;
96 |
97 | // initialisieren und ersten Abschnitt erstellen
98 | ptr = strtok(ini_string, "\n");
99 |
100 |
101 | /* Scan through file line by line */
102 | while(ptr != NULL) {
103 |
104 | sprintf(line, "%s\n",ptr);
105 | ptr = strtok(NULL, "\n");
106 | // while (line=gets( ini_string) != NULL) {
107 | lineno++;
108 |
109 | start = line;
110 | #if INI_ALLOW_BOM
111 | if (lineno == 1 && (unsigned char)start[0] == 0xEF &&
112 | (unsigned char)start[1] == 0xBB &&
113 | (unsigned char)start[2] == 0xBF) {
114 | start += 3;
115 | }
116 | #endif
117 | start = lskip(rstrip(start));
118 |
119 | if (*start == ';' || *start == '#') {
120 | /* Per Python ConfigParser, allow '#' comments at start of line */
121 | }
122 | #if INI_ALLOW_MULTILINE
123 | else if (*prev_name && *start && start > line) {
124 | /* Non-black line with leading whitespace, treat as continuation
125 | of previous name's value (as per Python ConfigParser). */
126 | if (!handler(user, section, prev_name, start) && !error)
127 | error = lineno;
128 | }
129 | #endif
130 | else if (*start == '[') {
131 | /* A "[section]" line */
132 | end = find_char_or_comment(start + 1, ']');
133 | if (*end == ']') {
134 | *end = '\0';
135 | strncpy0(section, start + 1, sizeof(section));
136 | *prev_name = '\0';
137 | }
138 | else if (!error) {
139 | /* No ']' found on section line */
140 | error = lineno;
141 | }
142 | }
143 | else if (*start && *start != ';') {
144 | /* Not a comment, must be a name[=:]value pair */
145 | end = find_char_or_comment(start, '=');
146 | if (*end != '=') {
147 | end = find_char_or_comment(start, ':');
148 | }
149 | if (*end == '=' || *end == ':') {
150 | *end = '\0';
151 | name = rstrip(start);
152 | value = lskip(end + 1);
153 | end = find_char_or_comment(value, '\0');
154 | if (*end == ';')
155 | *end = '\0';
156 | rstrip(value);
157 |
158 | /* Valid name[=:]value pair found, call handler */
159 | strncpy0(prev_name, name, sizeof(prev_name));
160 | if (!handler(user, section, name, value) && !error)
161 | error = lineno;
162 | }
163 | else if (!error) {
164 | /* No '=' or ':' found on name[=:]value line */
165 | error = lineno;
166 | }
167 | }
168 | }
169 |
170 | #if !INI_USE_STACK
171 | free(line);
172 | #endif
173 |
174 | return error;
175 | }
176 |
177 |
178 |
179 | /* See documentation in header file. */
180 | int ini_parse_file(FILE* file,
181 | int (*handler)(void*, const char*, const char*,
182 | const char*),
183 | void* user)
184 | {
185 | /* Uses a fair bit of stack (use heap instead if you need to) */
186 | #if INI_USE_STACK
187 | char line[INI_MAX_LINE];
188 | #else
189 | char* line;
190 | #endif
191 | char section[MAX_SECTION] = "";
192 | char prev_name[MAX_NAME] = "";
193 |
194 | char* start;
195 | char* end;
196 | char* name;
197 | char* value;
198 | int lineno = 0;
199 | int error = 0;
200 |
201 | #if !INI_USE_STACK
202 | line = (char*)malloc(INI_MAX_LINE);
203 | if (!line) {
204 | return -2;
205 | }
206 | #endif
207 |
208 | /* Scan through file line by line */
209 | while (fgets(line, INI_MAX_LINE, file) != NULL) {
210 | lineno++;
211 |
212 | start = line;
213 | #if INI_ALLOW_BOM
214 | if (lineno == 1 && (unsigned char)start[0] == 0xEF &&
215 | (unsigned char)start[1] == 0xBB &&
216 | (unsigned char)start[2] == 0xBF) {
217 | start += 3;
218 | }
219 | #endif
220 | start = lskip(rstrip(start));
221 |
222 | if (*start == ';' || *start == '#') {
223 | /* Per Python ConfigParser, allow '#' comments at start of line */
224 | }
225 | #if INI_ALLOW_MULTILINE
226 | else if (*prev_name && *start && start > line) {
227 | /* Non-black line with leading whitespace, treat as continuation
228 | of previous name's value (as per Python ConfigParser). */
229 | if (!handler(user, section, prev_name, start) && !error)
230 | error = lineno;
231 | }
232 | #endif
233 | else if (*start == '[') {
234 | /* A "[section]" line */
235 | end = find_char_or_comment(start + 1, ']');
236 | if (*end == ']') {
237 | *end = '\0';
238 | strncpy0(section, start + 1, sizeof(section));
239 | *prev_name = '\0';
240 | }
241 | else if (!error) {
242 | /* No ']' found on section line */
243 | error = lineno;
244 | }
245 | }
246 | else if (*start && *start != ';') {
247 | /* Not a comment, must be a name[=:]value pair */
248 | end = find_char_or_comment(start, '=');
249 | if (*end != '=') {
250 | end = find_char_or_comment(start, ':');
251 | }
252 | if (*end == '=' || *end == ':') {
253 | *end = '\0';
254 | name = rstrip(start);
255 | value = lskip(end + 1);
256 | end = find_char_or_comment(value, '\0');
257 | if (*end == ';')
258 | *end = '\0';
259 | rstrip(value);
260 |
261 | /* Valid name[=:]value pair found, call handler */
262 | strncpy0(prev_name, name, sizeof(prev_name));
263 | if (!handler(user, section, name, value) && !error)
264 | error = lineno;
265 | }
266 | else if (!error) {
267 | /* No '=' or ':' found on name[=:]value line */
268 | error = lineno;
269 | }
270 | }
271 | }
272 |
273 | #if !INI_USE_STACK
274 | free(line);
275 | #endif
276 |
277 | return error;
278 | }
279 |
280 | /* See documentation in header file. */
281 | int ini_parse(const char* filename,
282 | int (*handler)(void*, const char*, const char*, const char*),
283 | void* user)
284 | {
285 | FILE* file;
286 | int error;
287 |
288 | // file = fopen(filename, "r");
289 |
290 |
291 | fputs(filename, file);
292 |
293 |
294 |
295 |
296 | if (!file)
297 | return -1;
298 | error = ini_parse_file(file, handler, user);
299 | fclose(file);
300 | return error;
301 | }
302 |
--------------------------------------------------------------------------------
/src/mem.c:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 The Altra64 project contributors
3 | // Portions (c) 2013 saturnu (Alt64) based on libdragon, Neo64Menu, ED64IO, libn64-hkz, libmikmod
4 | // See LICENSE file in the project root for full license information.
5 | //
6 |
7 | #include "everdrive.h"
8 | #include "sys.h"
9 | #include "errors.h"
10 | #include "mem.h"
11 |
12 | u8 spi_dma;
13 |
14 | u8 memSpiReadDma(void *dst, u16 slen);
15 | u8 memSpiReadPio(void *dst, u16 slen);
16 | u8 mem_buff[512];
17 |
18 | void memSpiSetDma(u8 mode) {
19 | spi_dma = mode;
20 | }
21 |
22 | void memcopy(void *src, void *dst, u16 len) {
23 |
24 | u8 *s = (u8 *) src;
25 | u8 *d = (u8 *) dst;
26 | while (len--)*d++ = *s++;
27 | }
28 |
29 | void memfill(void *dst, u8 val, u16 len) {
30 | u8 *d = (u8 *) dst;
31 | while (len--)*d++ = val;
32 | }
33 |
34 |
35 | // buff len
36 | u8 memSpiRead(void *dst, u16 slen) {
37 |
38 | u8 copy_to_rom = 0;
39 | u32 addr = (u32) dst; //if ROM_ADDR 0xb0000000
40 | if (addr >= ROM_ADDR && addr < ROM_END_ADDR)copy_to_rom = 1;
41 |
42 | //if (copy_to_rom || spi_dma) {
43 | if ((copy_to_rom || spi_dma) && addr % 4 == 0) {
44 | return memSpiReadDma(dst, slen);
45 | } else {
46 | return memSpiReadPio(dst, slen);
47 |
48 | }
49 |
50 | }
51 |
52 | u8 memSpiReadPio(void *dst, u16 slen) {
53 |
54 | u16 i;
55 | u16 u;
56 | u8 *ptr8 = (u8 *) dst;
57 |
58 |
59 |
60 | for (i = 0; i < slen; i++) {
61 |
62 | evd_SDdatReadMode(1);
63 | for (u = 0; u < 65535; u++)if ((evd_SPI(0xff) & 0xf1) == 0xf0)break;
64 | evd_SDdatReadMode(0);
65 | if (u == 65535) {
66 | evd_spiSSOff();
67 | return DISK_RD_FE_TOUT;
68 | }
69 |
70 | for (u = 0; u < 512; u++)*ptr8++ = evd_SPI(0xff);
71 |
72 | u = evd_isSDMode() ? 8 : 2;
73 |
74 | while (u--) {
75 | // console_printf("XRC: %02X", evd_SPI(0xff));
76 | //console_printf("%02X\n", evd_SPI(0xff));
77 | u--;
78 | evd_SPI(0xff);
79 | evd_SPI(0xff);
80 | }
81 | //evd_SPI(0xff);
82 | //evd_SPI(0xff);
83 | }
84 |
85 |
86 | return 0;
87 | }
88 |
89 | u8 memSpiReadDma(void *dst, u16 slen) {
90 |
91 | u8 resp = 0;
92 | u8 copy_to_rom = 0;
93 | u32 addr = (u32) dst;
94 |
95 | evd_SDdatReadMode(0);
96 | // console_printf("dma\n");
97 | if (addr >= ROM_ADDR && addr < ROM_END_ADDR)copy_to_rom = 1;
98 |
99 | if (copy_to_rom) {
100 |
101 | return evd_mmcReadToCart(addr, slen);
102 |
103 | } else {
104 |
105 | resp = evd_mmcReadToCart(0, slen);
106 | dma_read_s(dst, ROM_ADDR, slen * 512);
107 | }
108 |
109 |
110 | return resp;
111 | }
112 |
113 | u8 memSpiWrite(const void *src) {
114 |
115 | u16 i;
116 |
117 | u8 *ptr8 = (u8 *) src;
118 |
119 | if ((u32) src >= ROM_ADDR && (u32) src < ROM_END_ADDR) {
120 | dma_read_s(mem_buff, (u32) src, 512);
121 | for (i = 0; i < 512; i++)mem_spi(mem_buff[i]);
122 | } else {
123 | for (i = 0; i < 512; i++)mem_spi(*ptr8++);
124 | }
125 |
126 |
127 | return 0;
128 | }
129 |
130 | void memSpiBusy() {
131 |
132 | while (evd_isSpiBusy());
133 |
134 | }
135 |
136 | void memRomWrite32(u32 addr, u32 val) {
137 |
138 | vu32 *ptr = (u32 *) (addr + ROM_ADDR);
139 | vu8 tmp;
140 |
141 | tmp = *ptr;
142 | *ptr = val;
143 | tmp = *ptr;
144 | }
145 |
146 | u32 memRomRead32(u32 addr) {
147 |
148 | vu32 *ptr = (u32 *) (addr + ROM_ADDR);
149 | vu8 tmp;
150 | vu32 val;
151 |
152 | tmp = *ptr;
153 | val = *ptr;
154 |
155 | return val;
156 | }
157 |
158 |
159 | /*
160 | u8 mem_spi(u8 dat) {
161 | return evd_SPI(dat);
162 | }
163 | */
--------------------------------------------------------------------------------
/src/memorypak.c:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 The Altra64 project contributors
3 | // Portions (c) 2013 saturnu (Alt64) based on libdragon, Neo64Menu, ED64IO, libn64-hkz, libmikmod
4 | // See LICENSE file in the project root for full license information.
5 | //
6 |
7 | #include
8 | #include
9 | #include
10 | #include "types.h"
11 | #include "mempak.h"
12 | #include "memorypak.h"
13 | #include "ff.h"
14 | #include "menu.h"
15 | #include "debug.h"
16 | #include "strlib.h"
17 | #include "sys.h"
18 | #include "localevar.h"
19 | #include "constants.h"
20 |
21 | enum MemoryPakFormat
22 | {
23 | None,
24 | DexDrive,
25 | Z64
26 | };
27 |
28 | static uint8_t mempak_data[128 * 256];
29 | char *mempak_path;
30 |
31 | char ___TranslateNotes(uint8_t *bNote, char *Text)
32 | {
33 | #pragma warning(disable : 4305 4309)
34 | char cReturn = 0x00;
35 | const char aSpecial[] = {0x21, 0x22, 0x23, 0x60, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x3A, 0x3D, 0x3F, 0x40, 0x74, 0xA9, 0xAE};
36 | // { '!' , '\"', '#' , '`' , '*' , '+' , ',' , '-' , '.' , '/' , ':' , '=' , '?' , '>' , 'tm', '(r)','(c)' };
37 | #pragma warning(default : 4305 4309)
38 | int i = 16;
39 | do
40 | {
41 | char b = bNote[i];
42 | if ((b > 0) && i < 32)
43 | {
44 | if (b <= 0x0F) // translate Icons as Spaces
45 | *Text = 0x20;
46 | else if (b <= 0x19) // Numbers
47 | *Text = 0x20 + b;
48 | else if (b <= 0x33) // Characters
49 | *Text = 0x47 + b;
50 | else if (b <= 0x44) // special Symbols
51 | *Text = aSpecial[b - 0x34];
52 | else if (b <= 0x94) // Japan
53 | *Text = 0xC0 + (b % 40);
54 | else // unknown
55 | *Text = (char)0xA4;
56 |
57 | ++i;
58 | ++Text;
59 | }
60 | else
61 | {
62 | *Text = '\0';
63 | if (b)
64 | {
65 | i = 12;
66 | Text = &cReturn;
67 | }
68 | else
69 | i = 13;
70 | }
71 | } while (i != 13);
72 |
73 | return cReturn;
74 | }
75 |
76 | char ___CountBlocks(uint8_t *bMemPakBinary, char *aNoteSizes)
77 | {
78 | int wRemainingBlocks = 123;
79 | char bNextIndex;
80 | int i = 0;
81 | while (i < 16 && wRemainingBlocks <= 123)
82 | {
83 | aNoteSizes[i] = 0;
84 | bNextIndex = bMemPakBinary[0x307 + (i * 0x20)];
85 | while ((bNextIndex >= 5) && (aNoteSizes[i] < wRemainingBlocks))
86 | {
87 | aNoteSizes[i]++;
88 | bNextIndex = bMemPakBinary[0x101 + (bNextIndex * 2)];
89 | }
90 |
91 | if (aNoteSizes[i] > wRemainingBlocks)
92 | wRemainingBlocks = 0xFF;
93 | else
94 | wRemainingBlocks -= aNoteSizes[i];
95 |
96 | i++;
97 | }
98 | return wRemainingBlocks;
99 | }
100 |
101 | //old method to write a file to the mempak at controller 1
102 | int file_to_mpk(display_context_t disp, u8 *filename)
103 | {
104 | enum MemoryPakFormat memorypak_format;
105 | u8 buff[64];
106 |
107 | FRESULT result;
108 | FIL file;
109 | UINT bytesread;
110 | result = f_open(&file, filename, FA_READ);
111 |
112 | if (result == FR_OK)
113 | {
114 | //int fsize = f_size(&file);
115 |
116 | u8 *pch;
117 | pch = strrchr(filename, '.');
118 | sprintf(buff, "%s", (pch + 2));
119 |
120 | if (strcmp(buff, "64") == 0)
121 | {
122 | TRACE(disp, "Dexdrive format");
123 | memorypak_format = DexDrive;
124 | //skip header
125 | result = f_lseek (
126 | &file, /* [IN] File object */
127 | 4160 /* [IN] File read/write pointer */
128 | );
129 | }
130 |
131 | TRACE(disp, "Z64 format");
132 | memorypak_format = Z64;
133 |
134 | result =
135 | f_read (
136 | &file, /* [IN] File object */
137 | mempak_data, /* [OUT] Buffer to store read data */
138 | 32768, /* [IN] Number of bytes to read */
139 | &bytesread /* [OUT] Number of bytes read */
140 | );
141 |
142 | f_close(&file);
143 |
144 | int err = 0;
145 | for (int j = 0; j < 128; j++)
146 | {
147 | err |= write_mempak_sector(0, j, &mempak_data[j * MEMPAK_BLOCK_SIZE]);
148 | }
149 | }
150 | else
151 | {
152 | memorypak_format = None;
153 | }
154 |
155 | return (int)memorypak_format; //TODO: should return enum
156 | }
157 |
158 | void view_mpk_file(display_context_t disp, char *mpk_filename)
159 | {
160 | u8 buff[64];
161 |
162 | FRESULT result;
163 | FIL file;
164 | UINT bytesread;
165 | result = f_open(&file, mpk_filename, FA_READ);
166 |
167 | if (result == FR_OK)
168 | {
169 | //int fsize = f_size(&file);
170 |
171 | u8 *pch;
172 | pch = strrchr(mpk_filename, '.');
173 | sprintf(buff, "%s", (pch + 2));
174 |
175 | if (strcmp(buff, "64") == 0) //DEXDRIVE format
176 | {
177 | //skip header
178 | result = f_lseek (
179 | &file, /* [IN] File object */
180 | 4160 /* [IN] File read/write pointer */
181 | );
182 | }
183 |
184 | result =
185 | f_read (
186 | &file, /* [IN] File object */
187 | mempak_data, /* [OUT] Buffer to store read data */
188 | 32768, /* [IN] Number of bytes to read */
189 | &bytesread /* [OUT] Number of bytes read */
190 | );
191 |
192 |
193 | f_close(&file);
194 |
195 | printText(fcontents, 11, 5, disp);
196 | printText(" ", 11, -1, disp);
197 |
198 | int notes_c = 0;
199 |
200 | char szBuffer[58],
201 | cAppendix;
202 | int bFirstChar;
203 |
204 | int i = 0,
205 | nNotes = 0,
206 | iSum = 0,
207 | iRemainingBlocks;
208 |
209 | char aNoteSizes[16];
210 |
211 | for (i = 0x10A; i < 0x200; i++)
212 | iSum += mempak_data[i];
213 |
214 | if (((iSum % 256) == mempak_data[0x101]))
215 | {
216 | iRemainingBlocks = ___CountBlocks(mempak_data, aNoteSizes);
217 |
218 | if (iRemainingBlocks <= 123)
219 | {
220 | for (notes_c = 0; notes_c < 16; notes_c++)
221 | {
222 | if (mempak_data[0x300 + (notes_c * 32)] ||
223 | mempak_data[0x301 + (notes_c * 32)] ||
224 | mempak_data[0x302 + (notes_c * 32)])
225 | {
226 | cAppendix = ___TranslateNotes(&mempak_data[0x300 + (notes_c * 32)], szBuffer);
227 |
228 | if (cAppendix != '\0')
229 | {
230 | char *buf = szBuffer;
231 |
232 | int strLength = snprintf(0, 0, "%s. %c", buf, cAppendix);
233 | //assert(strLength >= 0); // TODO add proper error handling
234 | //szBuffer = malloc(sizeof(char) * (strLength + 1));
235 | snprintf(szBuffer, strLength+1, "%s. %c", buf, cAppendix);
236 | }
237 |
238 | bFirstChar = 1;
239 | for (i = 0; i < (int)strlen(szBuffer); i++)
240 | {
241 | if (szBuffer[i] == ' ')
242 | bFirstChar = 1;
243 | else
244 | {
245 | if (bFirstChar && (szBuffer[i] >= 'a') && (szBuffer[i] <= 'z'))
246 | {
247 | bFirstChar = 0;
248 | szBuffer[i] -= 0x20;
249 | }
250 | }
251 | }
252 | printText(szBuffer, 11, -1, disp);
253 |
254 | switch (mempak_data[0x303 + (notes_c * 32)])
255 | {
256 | case 0x00:
257 | sprintf(szBuffer, "None");
258 | break;
259 | case 0x37:
260 | sprintf(szBuffer, "Beta");
261 | break;
262 | case 0x41:
263 | sprintf(szBuffer, "NTSC");
264 | break;
265 | case 0x44:
266 | sprintf(szBuffer, "Germany");
267 | break;
268 | case 0x45:
269 | sprintf(szBuffer, "USA");
270 | break;
271 | case 0x46:
272 | sprintf(szBuffer, "France");
273 | break;
274 | case 0x49:
275 | sprintf(szBuffer, "Italy");
276 | break;
277 | case 0x4A:
278 | sprintf(szBuffer, "Japan");
279 | break;
280 | case 0x50:
281 | sprintf(szBuffer, "Europe");
282 | break;
283 | case 0x53:
284 | sprintf(szBuffer, "Spain");
285 | break;
286 | case 0x55:
287 | sprintf(szBuffer, "Australia");
288 | break;
289 | case 0x58:
290 | case 0x59:
291 | sprintf(szBuffer, "PAL");
292 | break;
293 | default:
294 | sprintf(szBuffer, "Unknown(%02X)", mempak_data[0x303 + (notes_c * 32)]);
295 | }
296 |
297 | sprintf(szBuffer, "%i", aNoteSizes[notes_c]);
298 | nNotes++;
299 | }
300 | }
301 | }
302 |
303 | int free_c = 0;
304 | for (free_c = nNotes; free_c < 16; free_c++)
305 | printText(freebock, 11, -1, disp);
306 |
307 | char buff[512];
308 | printText(" ", 11, -1, disp);
309 | printText(freespace, 11, -1, disp);
310 | sprintf(buff, blocks, iRemainingBlocks);
311 | printText(buff, 11, -1, disp);
312 | }
313 | else
314 | {
315 | printText(emptyfile, 11, -1, disp);
316 | }
317 | }
318 | }
319 |
320 | void view_mpk(display_context_t disp)
321 | {
322 | int err;
323 |
324 | printText("Mempak content:", 11, 5, disp);
325 | struct controller_data output;
326 | get_accessories_present( &output);
327 |
328 | /* Make sure they don't have a rumble pak inserted instead */
329 | switch (identify_accessory(0))
330 | {
331 | case ACCESSORY_NONE:
332 |
333 | printText(" ", 11, -1, disp);
334 | printText("no Mempak", 11, -1, disp);
335 | break;
336 |
337 | case ACCESSORY_MEMPAK:
338 | if ((err = validate_mempak(0)))
339 | {
340 | if (err == -3)
341 | {
342 | printText(" ", 11, -1, disp);
343 |
344 | printText("not formatted", 11, -1, disp);
345 | }
346 | else
347 | {
348 | printText(" ", 11, -1, disp);
349 | printText("read error", 11, -1, disp);
350 | }
351 | }
352 | else
353 | {
354 | printText(" ", 11, -1, disp);
355 | for (int j = 0; j < 16; j++)
356 | {
357 | entry_structure_t entry;
358 |
359 | get_mempak_entry(0, j, &entry);
360 |
361 | if (entry.valid)
362 | {
363 | char tmp[512];
364 | sprintf(tmp, "%s", entry.name);
365 | printText(tmp, 11, -1, disp);
366 | }
367 | else
368 | {
369 | printText("[free]", 11, -1, disp);
370 | }
371 | }
372 |
373 | char buff[512];
374 | printText(" ", 11, -1, disp);
375 | printText("Free space:", 11, -1, disp);
376 | sprintf(buff, "%d blocks", get_mempak_free_space(0));
377 | printText(buff, 11, -1, disp);
378 | }
379 | break;
380 |
381 | case ACCESSORY_RUMBLEPAK:
382 | printText("RumblePak inserted", 11, -1, disp);
383 | break;
384 |
385 | default:
386 | break;
387 | }
388 | }
389 |
390 | //old function to dump a mempak to a file
391 | void mpk_to_file(display_context_t disp, char *mpk_filename, int quick)
392 | {
393 | u8 buff[MAX_SUPPORTED_PATH_LEN];
394 | u8 v = 0;
395 |
396 | if (quick)
397 | sprintf(buff,"/"ED64_FIRMWARE_PATH"/%s/%s", mempak_path, mpk_filename);
398 | else
399 | sprintf(buff, "/"ED64_FIRMWARE_PATH"/%s/%s.MPK", mempak_path, mpk_filename);
400 |
401 | FRESULT fr;
402 | FILINFO fno;
403 |
404 | fr = f_stat(buff, &fno);
405 | if(fr == FR_OK)
406 | {
407 | printText(filexist, 9, -1, disp);
408 | if (quick)
409 | printText(overridefile, 9, -1, disp);
410 | else
411 | while (fr == FR_OK)
412 | {
413 | sprintf(buff, "/"ED64_FIRMWARE_PATH"/%s/%s.%i.MPK", mempak_path, mpk_filename, v);
414 |
415 | fr = f_stat(buff, &fno);
416 | if (fr == FR_OK)
417 | v++;
418 | else
419 | break;
420 | }
421 | }
422 |
423 | FRESULT result;
424 | FIL file;
425 | result = f_open(&file, buff, FA_WRITE | FA_OPEN_ALWAYS);
426 |
427 | if (result == FR_OK)
428 | {
429 | controller_init();
430 |
431 | int err = 0;
432 | for (int j = 0; j < 128; j++)
433 | {
434 | err |= read_mempak_sector(0, j, &mempak_data[j * 256]);
435 | }
436 |
437 | UINT bw;
438 | result =
439 | f_write (
440 | &file, /* [IN] Pointer to the file object structure */
441 | mempak_data, /* [IN] Pointer to the data to be written */
442 | 32768, /* [IN] Number of bytes to write */
443 | &bw /* [OUT] Pointer to the variable to return number of bytes written */
444 | );
445 |
446 | f_close(&file);
447 |
448 |
449 | sprintf(buff, fileMPK, mpk_filename, v);
450 |
451 | printText(buff, 9, -1, disp);
452 | printText(backupdone, 9, -1, disp);
453 | }
454 | }
--------------------------------------------------------------------------------
/src/menu.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include "types.h"
3 | #include "debug.h"
4 |
5 | short int gCursorX;
6 | short int gCursorY;
7 |
8 | int text_offset = 0;
9 |
10 | void printText(char *msg, int x, int y, display_context_t dcon)
11 | {
12 | x = x + text_offset;
13 |
14 | if (x != -1)
15 | gCursorX = x;
16 | if (y != -1)
17 | gCursorY = y;
18 |
19 | if (dcon)
20 | graphics_draw_text(dcon, gCursorX * 8, gCursorY * 8, msg);
21 |
22 | gCursorY++;
23 | if (gCursorY > 29)
24 | {
25 | gCursorY = 0;
26 | gCursorX++;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/menu_about.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include "types.h"
4 | #include "menu.h"
5 | #include "version.h"
6 | #include "main.h"
7 | #include "everdrive.h"
8 | #include "localevar.h"
9 |
10 |
11 | void menu_about(display_context_t disp)
12 | {
13 | char version_str[32];
14 | char firmware_str[32];
15 |
16 | sprintf(version_str, "Altra 64: v%s", Altra64_GetVersionString());
17 | printText(version_str, 9, 8, disp); //1
18 | sprintf(firmware_str, "ED64 firmware: v%03x", evd_getFirmVersion()); //2
19 | printText(firmware_str, 9, -1, disp);
20 | printText("by JonesAlmighty", 9, -1, disp); //3
21 | printText("Based on ALT64", 9, -1, disp); //4
22 | printText("Credits to:", 9, -1, disp); //5
23 | printText("Altra 64 Contibutors", 9, -1, disp); //6
24 | printText("", 9, -1, disp); //7
25 | printText("Libraries:", 9, -1, disp); //8
26 | printText("Libdragon", 9, -1, disp); //9
27 | printText("Libmikmod-N64", 9, -1, disp); //10
28 | printText("Libmad-N64", 9, -1, disp); //11
29 | printText("Libyaml", 9, -1, disp); //12
30 | printText(" ", 9, -1, disp); //13
31 | printText(znpage, 9, -1, disp); //14
32 |
33 | } //TODO: make scrolling text, should include libraries used.
34 |
--------------------------------------------------------------------------------
/src/menu_controls.c:
--------------------------------------------------------------------------------
1 |
2 | #include
3 | #include
4 | #include "types.h"
5 | #include "menu.h"
6 | #include "version.h"
7 | #include "main.h"
8 | #include "everdrive.h"
9 | #include "localevar.h"
10 |
11 | void menu_controls(display_context_t disp)
12 | {
13 | printText(controlsmenucon, 4, 4, disp);
14 | printText(" ", 4, -1, disp);
15 | printText(showmpkmenu, 4, -1, disp);
16 | printText(" ", 4, -1, disp);
17 | printText(aboutscreen, 4, -1, disp);
18 | printText(" ", 4, -1, disp);
19 | printText(Astartromdirectory, 4, -1, disp);
20 | printText(Amempak, 4, -1, disp);
21 | printText(" ", 4, -1, disp);
22 | printText(Bbackcancel, 4, -1, disp);
23 | printText(" ", 4, -1, disp);
24 | printText(Startlastrom, 4, -1, disp);
25 | printText(" ", 4, -1, disp);
26 | printText(CLEFT, 4, -1, disp);
27 | printText(CLEFTVIEMPK, 4, -1, disp);
28 | printText(" ", 4, -1, disp);
29 | printText(CRIGHT, 4, -1, disp);
30 | printText(" ", 4, -1, disp);
31 | printText(CUP, 4, -1, disp);
32 | printText(" ", 4, -1, disp);
33 | printText(CDOWN, 4, -1, disp);
34 | printText(" ", 4, -1, disp);
35 | printText(LplusR, 4, -1, disp);
36 | }
37 |
--------------------------------------------------------------------------------
/src/menu_delete.c:
--------------------------------------------------------------------------------
1 |
2 | #include
3 | #include
4 | #include "types.h"
5 | #include "menu.h"
6 | #include "version.h"
7 | #include "main.h"
8 | #include "everdrive.h"
9 | #include "localevar.h"
10 |
11 |
12 | void menu_delete(display_context_t disp, bool isdir)
13 | {
14 | if (isdir)
15 | {
16 | printText(directoriesNO, 7, 14, disp);
17 | printText(bexit, 13, 16, disp);
18 | }
19 | else
20 | {
21 | printText(deletefile, 10, 14, disp);
22 | printText(aconfirm, 13, 16, disp);
23 | printText(bcancel, 13, 17, disp);
24 | }
25 | }
--------------------------------------------------------------------------------
/src/mp3.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include "mp3.h"
7 | #include "ff.h"
8 |
9 |
10 | static struct mad_stream Stream;
11 | static struct mad_header Header;
12 | static struct mad_frame Frame;
13 | static struct mad_synth Synth;
14 | static mad_timer_t Timer;
15 |
16 | typedef struct {
17 | short left;
18 | short right;
19 | } Sample;
20 |
21 | static int eos;
22 |
23 | #define INPUT_BUFFER_SIZE 2048
24 | static unsigned char fileBuffer[INPUT_BUFFER_SIZE];
25 | static unsigned char readBuffer[INPUT_BUFFER_SIZE];
26 | static int useReadBuffer;
27 | static int readPos;
28 | static UINT readLen;
29 | static int samplesRead;
30 |
31 | static FIL mp3File;
32 | static FRESULT mp3Fd;
33 |
34 |
35 | static int mp3_seek(int offset, int whence)
36 | {
37 | DWORD offs = 0;
38 | switch (whence)
39 | {
40 | case SEEK_SET:
41 | offs = offset;
42 | break;
43 | case SEEK_CUR:
44 | offs = mp3File.fptr + offset;
45 | break;
46 | case SEEK_END:
47 | offs = f_size(&mp3File) + offset;
48 | break;
49 | }
50 | f_lseek(&mp3File, offs);
51 | return offs;
52 | }
53 |
54 | static int mp3_size()
55 | {
56 | return f_size(&mp3File);
57 | }
58 |
59 | static int mp3_read(unsigned char *ptr, int size)
60 | {
61 | UINT ts;
62 | if (useReadBuffer)
63 | {
64 | int total = 0;
65 | while (size)
66 | {
67 | if (!readLen)
68 | {
69 | f_read (
70 | &mp3File, /* [IN] File object */
71 | readBuffer, /* [OUT] Buffer to store read data */
72 | INPUT_BUFFER_SIZE, /* [IN] Number of bytes to read */
73 | &readLen /* [OUT] Number of bytes read */
74 | );
75 | readPos = 0;
76 | if (readLen == 0)
77 | return total; // EOF
78 | }
79 | int rlen = (size= MAD_F_ONE)
214 | return (32767);
215 | if (Fixed <= -MAD_F_ONE)
216 | return (-32768);
217 |
218 | /* Conversion. */
219 | Fixed = Fixed >> (MAD_F_FRACBITS - 15);
220 |
221 | return ((short)Fixed);
222 | }
223 |
224 | static int fillFileBuffer()
225 | {
226 | int leftOver = Stream.bufend - Stream.next_frame;
227 | int want = INPUT_BUFFER_SIZE - leftOver;
228 |
229 | // move left-over bytes
230 | if (leftOver > 0)
231 | memmove(fileBuffer, fileBuffer + want, leftOver);
232 |
233 | // fill remainder of buffer
234 | unsigned char* bufferPos = fileBuffer + leftOver;
235 | while (want > 0)
236 | {
237 | int got = mp3_read(bufferPos, want);
238 | if (got <= 0)
239 | return 1; // EOF
240 |
241 | want -= got;
242 | bufferPos += got;
243 | }
244 | return 0;
245 | }
246 |
247 | static void decode()
248 | {
249 | while (mad_frame_decode(&Frame, &Stream) == -1)
250 | {
251 | if ((Stream.error == MAD_ERROR_BUFLEN) || (Stream.error == MAD_ERROR_BUFPTR))
252 | {
253 | if (fillFileBuffer())
254 | {
255 | eos = 1;
256 | break;
257 | }
258 | mad_stream_buffer(&Stream, fileBuffer, INPUT_BUFFER_SIZE);
259 | }
260 | else if (Stream.error == MAD_ERROR_LOSTSYNC)
261 | {
262 | /* LOSTSYNC - due to ID3 tags? */
263 | int tagsize = id3_tag_size(Stream.this_frame, Stream.bufend - Stream.this_frame);
264 | if (tagsize > 0)
265 | {
266 | mad_stream_skip (&Stream, tagsize);
267 | continue;
268 | }
269 | }
270 | }
271 |
272 | mad_timer_add(&Timer, Frame.header.duration);
273 | mad_synth_frame(&Synth, &Frame);
274 | }
275 |
276 | static void convertLeftSamples(Sample* first, Sample* last, const mad_fixed_t* src)
277 | {
278 | for (Sample *dst = first; dst != last; ++dst)
279 | dst->left = convertSample(*src++);
280 | }
281 |
282 | static void convertRightSamples(Sample* first, Sample* last, const mad_fixed_t* src)
283 | {
284 | for (Sample *dst = first; dst != last; ++dst)
285 | dst->right = convertSample(*src++);
286 | }
287 |
288 | static void MP3_Callback(void *buffer, unsigned int samplesToWrite)
289 | {
290 | Sample *destination = (Sample*)buffer;
291 |
292 | while (samplesToWrite > 0)
293 | {
294 | while (!eos && (Synth.pcm.length == 0))
295 | decode();
296 |
297 | if (eos)
298 | {
299 | // done
300 | memset(destination, 0, samplesToWrite*4);
301 | break;
302 | }
303 |
304 | unsigned int samplesAvailable = Synth.pcm.length - samplesRead;
305 | if (samplesAvailable > samplesToWrite)
306 | {
307 | convertLeftSamples(destination, destination + samplesToWrite, &Synth.pcm.samples[0][samplesRead]);
308 | convertRightSamples(destination, destination + samplesToWrite, &Synth.pcm.samples[1][samplesRead]);
309 |
310 | samplesRead += samplesToWrite;
311 | samplesToWrite = 0;
312 | }
313 | else
314 | {
315 | convertLeftSamples(destination, destination + samplesAvailable, &Synth.pcm.samples[0][samplesRead]);
316 | convertRightSamples(destination, destination + samplesAvailable, &Synth.pcm.samples[1][samplesRead]);
317 |
318 | destination += samplesAvailable;
319 | samplesToWrite -= samplesAvailable;
320 |
321 | samplesRead = 0;
322 | decode();
323 | }
324 | }
325 | }
326 |
327 | static void MP3_Init()
328 | {
329 | /* First the structures used by libmad must be initialized. */
330 | mad_stream_init(&Stream);
331 | mad_header_init(&Header);
332 | mad_frame_init(&Frame);
333 | mad_synth_init(&Synth);
334 | mad_timer_reset(&Timer);
335 | }
336 |
337 | static void MP3_Exit()
338 | {
339 | mad_synth_finish(&Synth);
340 | mad_header_finish(&Header);
341 | mad_frame_finish(&Frame);
342 | mad_stream_finish(&Stream);
343 | }
344 |
345 | static void MP3_GetInfo(long long *samples, int *rate)
346 | {
347 | unsigned long FrameCount = 0;
348 | int bufferSize = 1024*512;
349 | unsigned char *localBuffer;
350 | long bytesread = 0;
351 | double totalBitrate = 0.0;
352 | double mediumBitrate = 0.0;
353 | struct mad_stream stream;
354 | struct mad_header header;
355 | long size = mp3_size();
356 | long count = size;
357 |
358 | mad_stream_init (&stream);
359 | mad_header_init (&header);
360 |
361 | localBuffer = (unsigned char *)malloc(bufferSize);
362 |
363 | for (int i=0; i<3; i++)
364 | {
365 | memset(localBuffer, 0, bufferSize);
366 |
367 | if (count > bufferSize)
368 | bytesread = mp3_read(localBuffer, bufferSize);
369 | else
370 | bytesread = mp3_read(localBuffer, count);
371 | count -= bytesread;
372 | if (!bytesread)
373 | break; // ran out of data
374 |
375 | mad_stream_buffer (&stream, localBuffer, bytesread);
376 |
377 | for ( ;; )
378 | {
379 | if (mad_header_decode(&header, &stream) == -1)
380 | {
381 | if (stream.buffer == NULL || stream.error == MAD_ERROR_BUFLEN)
382 | break;
383 | else if (MAD_RECOVERABLE(stream.error))
384 | {
385 | continue;
386 | }
387 | else
388 | {
389 | break;
390 | }
391 | }
392 | if (FrameCount++ == 0)
393 | *rate = header.samplerate;
394 | totalBitrate += header.bitrate;
395 | }
396 | }
397 |
398 | mediumBitrate = totalBitrate / (double)FrameCount;
399 | int secs = size * 8 / mediumBitrate;
400 | *samples = *rate * secs;
401 |
402 | mad_header_finish (&header);
403 | mad_stream_finish (&stream);
404 |
405 | if (localBuffer)
406 | free(localBuffer);
407 |
408 | mp3_seek(0, SEEK_SET);
409 | }
410 |
411 |
412 | void mp3_Start(char *fname, long long *samples, int *rate, int *channels)
413 | {
414 |
415 | mp3Fd = f_open(&mp3File, fname, FA_READ);
416 |
417 | if (mp3Fd == FR_OK)
418 | {
419 | useReadBuffer = 0;
420 | MP3_GetInfo(samples, rate);
421 | *channels = 2;
422 |
423 | MP3_Init();
424 | MP3_SkipHdr();
425 | eos = readLen = readPos = 0;
426 | useReadBuffer = 1;
427 | return;
428 | }
429 |
430 | *samples = 0;
431 | return;
432 | }
433 |
434 | void mp3_Stop(void)
435 | {
436 | MP3_Exit();
437 | if (mp3Fd == FR_OK)
438 | {
439 | f_close(&mp3File);
440 | }
441 | mp3Fd = FR_NO_FILE;
442 | }
443 |
444 | int mp3_Update(char *buf, int bytes)
445 | {
446 | MP3_Callback(buf, bytes/4);
447 | return eos ? 0 : 1;
448 | }
--------------------------------------------------------------------------------
/src/rom.c:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2017 The Altra64 project contributors
2 | // Portions (c) 2013 saturnu (Alt64) based on libdragon, Neo64Menu, ED64IO, libn64-hkz, libmikmod
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | #include "sram.h"
7 | #include "everdrive.h"
8 | #include "sys.h"
9 | #include "rom.h"
10 | #include "cic.h"
11 | #include
12 | #include
13 |
14 | void pif_boot()
15 | {
16 | //TODO: implement
17 | }
18 |
19 |
20 |
21 | int is_valid_rom(unsigned char *buffer) {
22 | /* Test if rom is a native .z64 image with header 0x80371240. [ABCD] */
23 | if((buffer[0]==0x80)&&(buffer[1]==0x37)&&(buffer[2]==0x12)&&(buffer[3]==0x40))
24 | return 0;
25 | /* Test if rom is a byteswapped .v64 image with header 0x37804012. [BADC] */
26 | else if((buffer[0]==0x37)&&(buffer[1]==0x80)&&(buffer[2]==0x40)&&(buffer[3]==0x12))
27 | return 1;
28 | /* Test if rom is a wordswapped .n64 image with header 0x40123780. [DCBA] */
29 | else if((buffer[0]==0x40)&&(buffer[1]==0x12)&&(buffer[2]==0x37)&&(buffer[3]==0x80))
30 | return 2;
31 | else
32 | return 0;
33 | }
34 |
35 | void swap_header(unsigned char* header, int loadlength) {
36 | unsigned char temp;
37 | int i;
38 |
39 | /* Btyeswap if .v64 image. */
40 | if( header[0]==0x37) {
41 | for (i = 0; i < loadlength; i+=2) {
42 | temp= header[i];
43 | header[i]= header[i+1];
44 | header[i+1]=temp;
45 | }
46 | }
47 | /* Wordswap if .n64 image. */
48 | else if( header[0]==0x40) {
49 | for (i = 0; i < loadlength; i+=4) {
50 | temp= header[i];
51 | header[i]= header[i+3];
52 | header[i+3]=temp;
53 | temp= header[i+1];
54 | header[i+1]= header[i+2];
55 | header[i+2]=temp;
56 | }
57 | }
58 | }
59 |
60 | u8 getCicType(u8 bios_cic) {
61 | u8 cic_buff[2048];
62 | volatile u8 cic_chip;
63 | volatile u32 val;
64 | if (bios_cic) {
65 | evd_setCfgBit(ED_CFG_SDRAM_ON, 0);
66 | sleep(10);
67 | val = *(u32 *) 0xB0000170;
68 | dma_read_s(cic_buff, 0xB0000040, 1024);
69 | cic_chip = get_cic(cic_buff);
70 | evd_setCfgBit(ED_CFG_SDRAM_ON, 1);
71 | sleep(10);
72 | }
73 | else {
74 | val = *(u32 *) 0xB0000170;
75 | dma_read_s(cic_buff, 0xB0000040, 1024);
76 | cic_chip = get_cic(cic_buff);
77 | }
78 |
79 | return cic_chip;
80 | }
81 |
82 | //send game id for n64digital hdmi mod
83 | //source: https://gitlab.com/pixelfx-public/n64-game-id
84 | void send_game_id(uint8_t* crc_hi, uint8_t* crc_lo, uint8_t media_format, uint8_t country_id)
85 | {
86 | #define N64_CONTROLLER_PORT 0
87 | #define GAME_ID_COMMAND 0x1D
88 |
89 | uint8_t out[10];
90 | uint8_t dummy[1];
91 |
92 | memcpy(out, crc_hi, 4);
93 | memcpy(&out[4], crc_lo, 4);
94 |
95 | out[8] = media_format;
96 | out[9] = country_id;
97 |
98 | execute_raw_command(N64_CONTROLLER_PORT, GAME_ID_COMMAND, sizeof(out), sizeof(dummy), out, dummy);
99 | }
100 |
101 | // get the country and region string from country code "headerdata[0x3E]" (region type via www.bubblevision.com/PAL-NTSC.htm)
102 | // NTSC, PAL, MPAL or unknown
103 | void get_country_and_region(unsigned char ccode, char* region_string)
104 | {
105 | switch (ccode)
106 | {
107 | case '7': strcpy(region_string, "Beta"); break;
108 | case 'A': strcpy(region_string, "Asia-NTSC"); break;
109 | case 'B': strcpy(region_string, "Brazil-MPAL"); break;
110 | case 'C': strcpy(region_string, "China-PAL"); break;
111 | case 'D': strcpy(region_string, "Germany-PAL"); break;
112 | case 'E': strcpy(region_string, "NorthAmerica-NTSC"); break;
113 | case 'F': strcpy(region_string, "France-PAL"); break;
114 | case 'G': strcpy(region_string, "Gateway64-NTSC"); break;
115 | case 'H': strcpy(region_string, "Netherlands-PAL"); break;
116 | case 'I': strcpy(region_string, "Italy-PAL"); break;
117 | case 'J': strcpy(region_string, "Japan-NTSC"); break;
118 | case 'K': strcpy(region_string, "Korea-NTSC"); break;
119 | case 'L': strcpy(region_string, "Gateway64-PAL"); break;
120 | case 'N': strcpy(region_string, "Canada-NTSC"); break;
121 | case 'P': strcpy(region_string, "Europe-PAL"); break;
122 | case 'S': strcpy(region_string, "Spain-PAL"); break;
123 | case 'U': strcpy(region_string, "Australia-PAL"); break;
124 | case 'W': strcpy(region_string, "Scandinavia-PAL"); break;
125 | case 'X': strcpy(region_string, "Europe-PAL"); break;
126 | case 'Y': strcpy(region_string, "Europe-PAL"); break;
127 | case 'Z': strcpy(region_string, "Europe-PAL"); break;
128 | default: strcpy(region_string, "No Country");
129 | }
130 | }
131 |
132 | // get the region from country code "headerdata[0x3E]" (region type via www.bubblevision.com/PAL-NTSC.htm)
133 | unsigned char get_region(unsigned char ccode)
134 | {
135 | switch (ccode)
136 | {
137 | case '7': return REGION_UNKNOWN;
138 | case 'A': return REGION_NTSC;
139 | case 'B': return REGION_PAL_M;
140 | case 'C': return REGION_PAL;
141 | case 'D': return REGION_PAL;
142 | case 'E': return REGION_NTSC;
143 | case 'F': return REGION_PAL;
144 | case 'G': return REGION_NTSC;
145 | case 'H': return REGION_PAL;
146 | case 'I': return REGION_PAL;
147 | case 'J': return REGION_NTSC;
148 | case 'K': return REGION_NTSC;
149 | case 'L': return REGION_PAL;
150 | case 'N': return REGION_NTSC;
151 | case 'P': return REGION_PAL;
152 | case 'S': return REGION_PAL;
153 | case 'U': return REGION_PAL;
154 | case 'W': return REGION_PAL;
155 | case 'X': return REGION_PAL;
156 | case 'Y': return REGION_PAL;
157 | case 'Z': return REGION_PAL;
158 | default: return REGION_UNKNOWN;
159 | }
160 | return REGION_UNKNOWN;
161 | }
--------------------------------------------------------------------------------
/src/sound.c:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 The Altra64 project contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 | #define SOUND_ENABLED
6 | #if !defined(SOUND_ENABLED)
7 |
8 | void sndInit(void)
9 | {
10 | }
11 |
12 | void sndPlayBGM(char* filename)
13 | {
14 | }
15 |
16 | void sndStopAll(void)
17 | {
18 | }
19 |
20 | void sndPlaySFX(char* filename)
21 | {
22 | }
23 |
24 | void sndUpdate(void)
25 | {
26 | }
27 |
28 | #else
29 |
30 | #include
31 | #include //needed for audio_get_frequency()
32 | #include "hashtable.h"
33 |
34 | MODULE *moduleBGM = NULL;
35 |
36 | /* sound effects */
37 | hashtable* samples = NULL;
38 |
39 | /* voices */
40 | SBYTE voiceSFX;
41 |
42 | void sndInit(void)
43 | {
44 | samples = hashtable_create();
45 |
46 | /* register all the drivers */
47 | MikMod_RegisterAllDrivers();
48 | MikMod_RegisterAllLoaders();
49 |
50 | /* initialize the library */
51 | md_mode = 0;
52 | md_mode |= DMODE_16BITS;
53 | md_mode |= DMODE_SOFT_MUSIC;
54 | md_mode |= DMODE_SOFT_SNDFX;
55 | md_mode |= DMODE_INTERP;
56 |
57 | md_mixfreq = audio_get_frequency();
58 |
59 | MikMod_Init("");
60 |
61 | /* reserve 2 voices for sound effects */
62 | MikMod_SetNumVoices(-1, 2);
63 |
64 | /* get ready to play */
65 | MikMod_EnableOutput();
66 |
67 |
68 | }
69 |
70 | void sndPlayBGM(char* filename)
71 | {
72 | if (Player_Active())
73 | {
74 | Player_Stop();
75 | }
76 | Player_Free(moduleBGM);
77 | moduleBGM = NULL;
78 |
79 | moduleBGM = Player_Load(filename, 64, 0);
80 |
81 | if (moduleBGM)
82 | {
83 | Player_Start(moduleBGM);
84 | Player_SetVolume(80);
85 | }
86 | }
87 |
88 | void sndStopAll(void)
89 | {
90 | Voice_Stop(voiceSFX);
91 | Player_Stop();
92 | MikMod_DisableOutput();
93 |
94 | int index = 0;
95 | while (index < samples->capacity) {
96 | Sample_Free(samples->body[index].value);
97 | index = index + 1;
98 | }
99 |
100 | hashtable_destroy(samples);
101 |
102 | Player_Free(moduleBGM);
103 | moduleBGM = NULL;
104 |
105 | samples = hashtable_create();
106 | //MikMod_Exit(); //I dont think we should ever exit as that would mean reinitialising?!
107 | }
108 |
109 | void sndPlaySFX(char* filename)
110 | {
111 | if (!Voice_Stopped(voiceSFX))
112 | {
113 | Voice_Stop(voiceSFX);
114 | }
115 |
116 |
117 | if (hashtable_get(samples, filename) == NULL)
118 | {
119 | hashtable_set(samples, filename, Sample_Load(filename));
120 | }
121 |
122 | //audio_write_silence();
123 | Voice_SetVolume(voiceSFX, 800);
124 | voiceSFX = Sample_Play(hashtable_get(samples, filename), 0, 0);
125 |
126 | MikMod_Update(); //force an update so that the voice is registered as playing!
127 |
128 | }
129 |
130 | void sndUpdate(void)
131 | {
132 | if (!Voice_Stopped(voiceSFX) || Player_Active())
133 | {
134 | MikMod_Update();
135 |
136 | }
137 | }
138 | #endif
139 |
--------------------------------------------------------------------------------
/src/sram.c:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 The Altra64 project contributors
3 | // Portions (c) 2013 saturnu (Alt64) based on libdragon, Neo64Menu, ED64IO, libn64-hkz, libmikmod
4 | // See LICENSE file in the project root for full license information.
5 | //
6 |
7 | #include
8 | #include
9 |
10 | #include "sys.h"
11 | #include "utils.h"
12 | #include "sram.h"
13 | #include "rom.h"
14 |
15 |
16 | void PI_Init(void) {
17 | PI_DMAWait();
18 | IO_WRITE(PI_STATUS_REG, 0x03);
19 | }
20 |
21 | // Inits PI for sram transfer
22 | void PI_Init_SRAM(void) {
23 |
24 |
25 | IO_WRITE(PI_BSD_DOM2_LAT_REG, 0x05);
26 | IO_WRITE(PI_BSD_DOM2_PWD_REG, 0x0C);
27 | IO_WRITE(PI_BSD_DOM2_PGS_REG, 0x0D);
28 | IO_WRITE(PI_BSD_DOM2_RLS_REG, 0x02);
29 |
30 | }
31 |
32 | void PI_DMAWait(void) {
33 |
34 |
35 | /*PI DMA wait
36 |
37 | 1. Read PI_STATUS_REG then AND it with 0x3, if its true... then wait until
38 | it is not true.
39 | */
40 |
41 | while (IO_READ(PI_STATUS_REG) & (PI_STATUS_IO_BUSY | PI_STATUS_DMA_BUSY));
42 | }
43 |
44 |
45 | void PI_DMAFromSRAM(void *dest, u32 offset, u32 size) {
46 |
47 |
48 | IO_WRITE(PI_DRAM_ADDR_REG, K1_TO_PHYS(dest));
49 | IO_WRITE(PI_CART_ADDR_REG, (0xA8000000 + offset));
50 | asm volatile ("" : : : "memory");
51 | IO_WRITE(PI_WR_LEN_REG, (size - 1));
52 | asm volatile ("" : : : "memory");
53 |
54 |
55 | /*
56 | PI_DMAWait();
57 |
58 | IO_WRITE(PI_STATUS_REG, 0x03);
59 | IO_WRITE(PI_DRAM_ADDR_REG, K1_TO_PHYS(dest));
60 | IO_WRITE(PI_CART_ADDR_REG, (0xA8000000 + offset));
61 | _data_cache_invalidate_all();
62 | IO_WRITE(PI_WR_LEN_REG, (size - 1));
63 | */
64 | }
65 |
66 |
67 | void PI_DMAToSRAM(void *src, u32 offset, u32 size) { //void*
68 | PI_DMAWait();
69 |
70 | IO_WRITE(PI_STATUS_REG, 2);
71 | IO_WRITE(PI_DRAM_ADDR_REG, K1_TO_PHYS(src));
72 | IO_WRITE(PI_CART_ADDR_REG, (0xA8000000 + offset));
73 | _data_cache_invalidate_all();
74 | //data_cache_hit_writeback_invalidate(src,size);
75 |
76 | /* Write back . nusys - only writeback
77 | osWritebackDCache((void*)buf_ptr, (s32)size);
78 | */
79 | //libdragon equivalent
80 | // data_cache_hit_writeback (src, size);
81 |
82 | IO_WRITE(PI_RD_LEN_REG, (size - 1));
83 | }
84 |
85 | void PI_DMAFromCart(void* dest, void* src, u32 size) {
86 | PI_DMAWait();
87 |
88 | IO_WRITE(PI_STATUS_REG, 0x03);
89 | IO_WRITE(PI_DRAM_ADDR_REG, K1_TO_PHYS(dest));
90 | IO_WRITE(PI_CART_ADDR_REG, K0_TO_PHYS(src));
91 | //_data_cache_invalidate_all();
92 | IO_WRITE(PI_WR_LEN_REG, (size - 1));
93 | }
94 |
95 |
96 | void PI_DMAToCart(void* dest, void* src, u32 size) {
97 | PI_DMAWait();
98 |
99 | IO_WRITE(PI_STATUS_REG, 0x02);
100 | IO_WRITE(PI_DRAM_ADDR_REG, K1_TO_PHYS(src));
101 | IO_WRITE(PI_CART_ADDR_REG, K0_TO_PHYS(dest));
102 | //_data_cache_invalidate_all();
103 | IO_WRITE(PI_RD_LEN_REG, (size - 1));
104 | }
105 |
106 |
107 | // Wrapper to support unaligned access to memory
108 | void PI_SafeDMAFromCart(void *dest, void *src, u32 size) {
109 | if (!dest || !src || !size) return;
110 |
111 | u32 unalignedSrc = ((u32)src) % 2;
112 | u32 unalignedDest = ((u32)dest) % 8;
113 |
114 | //FIXME: Do i really need to check if size is 16bit aligned?
115 | if (!unalignedDest && !unalignedSrc && !(size % 2)) {
116 | PI_DMAFromCart(dest, src, size);
117 | PI_DMAWait();
118 |
119 | return;
120 | }
121 |
122 | void* newSrc = (void*)(((u32)src) - unalignedSrc);
123 | u32 newSize = (size + unalignedSrc) + ((size + unalignedSrc) % 2);
124 |
125 | u8 *buffer = memalign(8, newSize);
126 | PI_DMAFromCart(buffer, newSrc, newSize);
127 | PI_DMAWait();
128 |
129 | memcpy(dest, (buffer + unalignedSrc), size);
130 |
131 | free(buffer);
132 | }
133 |
134 |
--------------------------------------------------------------------------------
/src/strlib.c:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 The Altra64 project contributors
3 | // Portions (c) 2013 saturnu (Alt64) based on libdragon, Neo64Menu, ED64IO, libn64-hkz, libmikmod
4 | // See LICENSE file in the project root for full license information.
5 | //
6 |
7 | #include "strlib.h"
8 | #include "types.h"
9 |
10 | char *strcpytrim(char *d, // destination
11 | char *s, // source
12 | int mode,
13 | char *delim
14 | ) {
15 | char *o = d; // save orig
16 | char *e = 0; // end space ptr.
17 | char dtab[256] = {0};
18 | if (!s || !d) return 0;
19 |
20 | if (!delim) delim = " \t\n\f";
21 | while (*delim)
22 | dtab[*delim++] = 1;
23 |
24 | while ( (*d = *s++) != 0 ) {
25 | if (!dtab[*d]) { // Not a match char
26 | e = 0; // Reset end pointer
27 | } else {
28 | if (!e) e = d; // Found first match.
29 |
30 | if ( mode == STRLIB_MODE_ALL || ((mode != STRLIB_MODE_RIGHT) && (d == o)) )
31 | continue;
32 | }
33 | d++;
34 | }
35 | if (mode != STRLIB_MODE_LEFT && e) { // for everything but trim_left, delete trailing matches.
36 | *e = 0;
37 | }
38 | return o;
39 | }
40 |
41 | // perhaps these could be inlined in strlib.h
42 | char *strtriml(char *d, char *s) { return strcpytrim(d, s, STRLIB_MODE_LEFT, 0); }
43 | char *strtrimr(char *d, char *s) { return strcpytrim(d, s, STRLIB_MODE_RIGHT, 0); }
44 | char *strtrim(char *d, char *s) { return strcpytrim(d, s, STRLIB_MODE_BOTH, 0); }
45 | char *strstrlibkill(char *d, char *s) { return strcpytrim(d, s, STRLIB_MODE_ALL, 0); }
46 |
47 | char *triml(char *s) { return strcpytrim(s, s, STRLIB_MODE_LEFT, 0); }
48 | char *trimr(char *s) { return strcpytrim(s, s, STRLIB_MODE_RIGHT, 0); }
49 | char *trim(char *s) { return strcpytrim(s, s, STRLIB_MODE_BOTH, 0); }
50 | char *strlibkill(char *s) { return strcpytrim(s, s, STRLIB_MODE_ALL, 0); }
51 |
52 | u16 strcon(u8 *str1, u8 *str2, u8 *dst, u16 max_len) {
53 |
54 | u16 len = 0;
55 | max_len -= 1;
56 |
57 | while (*str1 != 0 && len < max_len) {
58 | *dst++ = *str1++;
59 | len++;
60 | }
61 |
62 | while (*str2 != 0 && len < max_len) {
63 | *dst++ = *str2++;
64 | len++;
65 | }
66 | *dst++ = 0;
67 | return len;
68 |
69 | }
70 |
71 | u8 streq(u8 *str1, u8 *str2) {
72 |
73 | u8 s1;
74 | u8 s2;
75 |
76 | for (;;) {
77 | s1 = *str1++;
78 | s2 = *str2++;
79 | if (s1 >= 'a' && s1 <= 'z')s1 -= 0x20;
80 | if (s2 >= 'a' && s2 <= 'z')s2 -= 0x20;
81 |
82 | if (s1 != s2) return 0;
83 |
84 | if (*str1 == 0 && *str2 == 0)return 1;
85 | }
86 | }
87 |
88 | u8 streql(u8 *str1, u8 *str2, u8 len) {
89 |
90 | u8 s1;
91 | u8 s2;
92 | while (len--) {
93 |
94 | s1 = *str1++;
95 | s2 = *str2++;
96 | if (s1 >= 'a' && s1 <= 'z')s1 -= 0x20;
97 | if (s2 >= 'a' && s2 <= 'z')s2 -= 0x20;
98 |
99 | if (s1 != s2) return 0;
100 | }
101 |
102 | return 1;
103 | }
104 |
105 | u16 strContain(u8 *target, u8 *str) {
106 |
107 | u16 targ_len = slen(target);
108 | u16 eq_len;
109 |
110 |
111 | for (eq_len = 0; eq_len < targ_len;) {
112 |
113 | if (*str == 0)return 0;
114 | if (*str++ == target[eq_len]) {
115 | eq_len++;
116 | } else {
117 | eq_len = 0;
118 | }
119 | }
120 |
121 | if (eq_len != targ_len)return 0;
122 | return 1;
123 |
124 | }
125 |
126 | u8 slen(u8 *str) {
127 |
128 | u8 len = 0;
129 | while (*str++)len++;
130 | return len;
131 | }
132 |
133 | u8 scopy(u8 *src, u8 *dst) {
134 |
135 | u8 len = 0;
136 | while (*src != 0) {
137 | *dst++ = *src++;
138 | len++;
139 | }
140 | *dst = 0;
141 | return len;
142 | }
143 |
144 | void strhicase(u8 *str, u8 len) {
145 |
146 | if (len) {
147 | while (len--) {
148 | if (*str >= 'a' && *str <= 'z')*str -= 0x20;
149 | str++;
150 | }
151 | } else {
152 | while (*str != 0) {
153 | if (*str >= 'a' && *str <= 'z')*str -= 0x20;
154 | str++;
155 | }
156 | }
157 |
158 | }
--------------------------------------------------------------------------------
/src/sys.c:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 The Altra64 project contributors
3 | // Portions (c) 2013 saturnu (Alt64) based on libdragon, Neo64Menu, ED64IO, libn64-hkz, libmikmod
4 | // See LICENSE file in the project root for full license information.
5 | //
6 |
7 | #include
8 | #include
9 | #include
10 | #include "sys.h"
11 | #include "rom.h"
12 |
13 |
14 | u32 asm_date;
15 |
16 | Options_st options;
17 |
18 | u32 native_tv_mode;
19 |
20 | void dma_read_s(void * ram_address, unsigned long pi_address, unsigned long len) {
21 |
22 | u32 buff[256];
23 |
24 | u32 *bptr;
25 |
26 | u32 *rptr = (u32 *) ram_address;
27 |
28 | // if(len==32768)
29 | // rptr = (u32 *) 0x803F7988;
30 |
31 | u16 i;
32 |
33 | //u16 blen = 512;
34 | //if (len < 512)blen = len;
35 | //*(volatile u32*) 0x1FC007FC = 0x08;
36 |
37 | IO_WRITE(PI_STATUS_REG, 3);
38 | while (len) {
39 | dma_read(buff, pi_address, 512);
40 | while ((IO_READ(PI_STATUS_REG) & 3) != 0);
41 | //while ((*((volatile u32*) PI_STATUS_REG) & 0x02) != 1);
42 | data_cache_hit_invalidate(buff, 512);
43 | bptr = buff;
44 | for (i = 0; i < 512 && i < len; i += 4)*rptr++ = *bptr++;
45 | len = len < 512 ? 0 : len - 512;
46 | pi_address += 512;
47 | }
48 | }
49 |
50 | void dma_write_s(void * ram_address, unsigned long pi_address, unsigned long len) {
51 |
52 |
53 | //if(len==32768)
54 | //ram_address = (u32 *) 0x803F7988;
55 |
56 |
57 | data_cache_hit_writeback(ram_address, len);
58 | dma_write(ram_address, pi_address, len);
59 |
60 |
61 |
62 | }
63 |
64 |
65 | /*
66 | void showError(char *str, u32 code) {
67 |
68 |
69 | console_printf("%s%u\n", str, code);
70 | joyWait();
71 |
72 |
73 | }
74 | */
75 | void sleep(u32 ms) {
76 |
77 | u32 current_ms = get_ticks_ms();
78 |
79 | while (get_ticks_ms() - current_ms < ms);
80 |
81 | }
82 |
83 | void dma_read_sram(void *dest, u32 offset, u32 size) {
84 | /*
85 | PI_DMAWait();
86 |
87 | IO_WRITE(PI_STATUS_REG, 0x03);
88 | IO_WRITE(PI_DRAM_ADDR_REG, K1_TO_PHYS(dest));
89 | IO_WRITE(PI_CART_ADDR_REG, (0xA8000000 + offset));
90 | // data_cache_invalidate_all();
91 | IO_WRITE(PI_WR_LEN_REG, (size - 1));
92 | */
93 | /* 0xA8000000
94 | * 0xb0000000
95 | * 0x4000000
96 | * */
97 | dma_read_s(dest, 0xA8000000 + offset, size);
98 | //data_cache_invalidate(dest,size);
99 |
100 | }
101 |
102 | void dma_write_sram(void* src, u32 offset, u32 size) {
103 | /*
104 | PI_DMAWait();
105 |
106 | IO_WRITE(PI_STATUS_REG, 0x02);
107 | IO_WRITE(PI_DRAM_ADDR_REG, K1_TO_PHYS(src));
108 | IO_WRITE(PI_CART_ADDR_REG, (0xA8000000 + offset));
109 | // data_cache_invalidate_all();
110 | IO_WRITE(PI_RD_LEN_REG, (size - 1));
111 | */
112 | dma_write_s(src, 0xA8000000 + offset, size);
113 |
114 | }
115 |
116 |
117 |
118 |
119 |
120 |
121 | u32 ii;
122 | volatile u32 *pt;
123 | void clean();
124 |
125 | #define MEM32(addr) *((volatile u32 *)addr)
126 |
127 |
128 | u8 STR_intToDecString(u32 val, u8 *str) {
129 |
130 | int len;
131 |
132 | if (val < 10)len = 1;
133 | else
134 | if (val < 100)len = 2;
135 | else
136 | if (val < 1000)len = 3;
137 | else
138 | if (val < 10000)len = 4;
139 | else
140 | if (val < 100000)len = 5;
141 | else
142 | if (val < 1000000)len = 6;
143 | else
144 | if (val < 10000000)len = 7;
145 | else
146 | if (val < 100000000)len = 8;
147 | else
148 | if (val < 1000000000)len = 9;
149 | else len = 10;
150 |
151 | str += len;
152 | str[0] = 0;
153 | if (val == 0)*--str = '0';
154 | while (val) {
155 |
156 | *--str = '0' + val % 10;
157 | val /= 10;
158 | }
159 |
160 |
161 | return len;
162 | }
163 |
164 | void STR_intToDecStringMin(u32 val, u8 *str, u8 min_size) {
165 |
166 | int len;
167 | u8 i;
168 |
169 | if (val < 10)len = 1;
170 | else
171 | if (val < 100)len = 2;
172 | else
173 | if (val < 1000)len = 3;
174 | else
175 | if (val < 10000)len = 4;
176 | else
177 | if (val < 100000)len = 5;
178 | else
179 | if (val < 1000000)len = 6;
180 | else
181 | if (val < 10000000)len = 7;
182 | else
183 | if (val < 100000000)len = 8;
184 | else
185 | if (val < 1000000000)len = 9;
186 | else len = 10;
187 |
188 | if (len < min_size) {
189 |
190 | i = min_size - len;
191 | while (i--)str[i] = '0';
192 | len = min_size;
193 | }
194 | str += len;
195 | str[0] = 0;
196 | if (val == 0)*--str = '0';
197 | while (val) {
198 |
199 | *--str = '0' + val % 10;
200 | val /= 10;
201 | }
202 | }
203 |
204 |
205 |
206 |
--------------------------------------------------------------------------------
/src/usb.c:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 The Altra64 project contributors
3 | // Portions (c) 2013 saturnu (Alt64) based on libdragon, Neo64Menu, ED64IO, libn64-hkz, libmikmod
4 | // See LICENSE file in the project root for full license information.
5 | //
6 |
7 | #include "everdrive.h"
8 | #include "sys.h"
9 | #include "rom.h"
10 |
11 | u8 cmdTest();
12 | u8 cmdFill();
13 | u8 cmdReadRom();
14 | u8 cmdWriteRom();
15 |
16 | u64 usb_buff[128];
17 | u8 *usb_buff8; // = (u8 *) usb_buff;
18 |
19 |
20 | #define PI_BSD_DOM1_LAT_REG (PI_BASE_REG+0x14)
21 |
22 | /* PI dom1 pulse width (R/W): [7:0] domain 1 device R/W strobe pulse width */
23 | #define PI_BSD_DOM1_PWD_REG (PI_BASE_REG+0x18)
24 |
25 | /* PI dom1 page size (R/W): [3:0] domain 1 device page size */
26 | #define PI_BSD_DOM1_PGS_REG (PI_BASE_REG+0x1C) /* page size */
27 |
28 | /* PI dom1 release (R/W): [1:0] domain 1 device R/W release duration */
29 | #define PI_BSD_DOM1_RLS_REG (PI_BASE_REG+0x20)
30 | /* PI dom2 latency (R/W): [7:0] domain 2 device latency */
31 | #define PI_BSD_DOM2_LAT_REG (PI_BASE_REG+0x24) /* Domain 2 latency */
32 |
33 | /* PI dom2 pulse width (R/W): [7:0] domain 2 device R/W strobe pulse width */
34 | #define PI_BSD_DOM2_PWD_REG (PI_BASE_REG+0x28) /* pulse width */
35 |
36 | /* PI dom2 page size (R/W): [3:0] domain 2 device page size */
37 | #define PI_BSD_DOM2_PGS_REG (PI_BASE_REG+0x2C) /* page size */
38 |
39 | /* PI dom2 release (R/W): [1:0] domain 2 device R/W release duration */
40 | #define PI_BSD_DOM2_RLS_REG (PI_BASE_REG+0x30) /* release duration */
41 |
42 | #define PHYS_TO_K1(x) ((u32)(x)|0xA0000000) /* physical to kseg1 */
43 | #define IO_WRITE(addr,data) (*(volatile u32*)PHYS_TO_K1(addr)=(u32)(data))
44 | #define PI_BASE_REG 0x04600000
45 |
46 | extern u8 system_cic;
47 |
48 | u8 usbListener() {
49 |
50 | volatile u16 resp;
51 | volatile u8 cmd;
52 | usb_buff8 = (u8 *) usb_buff;
53 |
54 |
55 | if (evd_fifoRxf())return 0;
56 |
57 | resp = evd_fifoRd(usb_buff, 1);
58 |
59 | if (resp != 0) return 1;
60 |
61 | if (usb_buff8[0] != 'C' || usb_buff8[1] != 'M' || usb_buff8[2] != 'D')return 2;
62 |
63 | cmd = usb_buff8[3];
64 |
65 |
66 | switch (cmd) {
67 |
68 | case 'R':
69 | resp = cmdReadRom();
70 | if (resp)return 10;
71 | break;
72 | case 'W':
73 | resp = cmdWriteRom();
74 | if (resp)return 11;
75 | break;
76 | case 'T':
77 | resp = cmdTest();
78 | if (resp)return 12;
79 | break;
80 | case 'F':
81 | resp = cmdFill();
82 | if (resp)return 13;
83 | break;
84 | case 'S':
85 | //IO_WRITE(PI_BSD_DOM1_PGS_REG, 0x0c);
86 | //IO_WRITE(PI_BSD_DOM1_PGS_REG, 0x80);
87 | //evdSetESaveType(SAVE_TYPE_EEP16k);
88 | //system_cic = CIC_6102; //TODO: re-enable
89 | evd_lockRegs();
90 | IO_WRITE(PI_STATUS_REG, 3);
91 | sleep(2);
92 | pif_boot();
93 | break;
94 | case 'D':
95 | //TODO: initiate debug session
96 | break;
97 | default:
98 | break;
99 |
100 | }
101 |
102 |
103 | return 0;
104 | }
105 |
106 | u8 cmdTest() {
107 |
108 | u16 resp;
109 | usb_buff8[3] = 'k';
110 | resp = evd_fifoWr(usb_buff, 1);
111 | if (resp)return 1;
112 |
113 | return 0;
114 |
115 | }
116 |
117 | u8 cmdFill() {
118 |
119 | u16 resp;
120 | u32 i;
121 | //console_printf("fill...\n");
122 |
123 | for (i = 0; i < 512; i++) {
124 | usb_buff8[i] = 0;
125 | }
126 | //console_printf("buff prepared\n");
127 | //romFill(0, 0x200000, 0); //TODO: re-enable
128 | //console_printf("fill done\n");
129 |
130 | usb_buff8[3] = 'k';
131 | resp = evd_fifoWr(usb_buff, 1);
132 |
133 | if (resp)return 1;
134 | //console_printf("resp sent ok\n");
135 |
136 | return 0;
137 | }
138 |
139 | u8 cmdReadRom() {
140 |
141 | u16 resp;
142 | u16 ptr;
143 | u16 len;
144 | u32 addr;
145 | ptr = 4;
146 |
147 |
148 | addr = usb_buff8[ptr++];
149 | addr <<= 8;
150 | addr |= usb_buff8[ptr++];
151 | addr *= 2048;
152 |
153 | len = usb_buff8[ptr++];
154 | len <<= 8;
155 | len |= usb_buff8[ptr++];
156 |
157 |
158 | resp = evd_fifoWrFromCart(addr, len);
159 | if (resp)return 1;
160 |
161 |
162 | return 0;
163 | }
164 |
165 | u8 cmdWriteRom() {
166 |
167 | u16 resp;
168 | u16 ptr;
169 | u16 len;
170 | u32 addr;
171 | ptr = 4;
172 |
173 | addr = usb_buff8[ptr++];
174 | addr <<= 8;
175 | addr |= usb_buff8[ptr++];
176 | addr *= 2048;
177 |
178 | len = usb_buff8[ptr++];
179 | len <<= 8;
180 | len |= usb_buff8[ptr++];
181 |
182 | resp = evd_fifoRdToCart(addr, len);
183 | if (resp)return 1;
184 |
185 | return 0;
186 |
187 | }
188 |
--------------------------------------------------------------------------------
/src/version.c:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2017 The Altra64 project contributors
3 | // See LICENSE file in the project root for full license information.
4 | //
5 |
6 | #include "version.h"
7 |
8 | #define ALTRA64_VERSION "3.8.1"
9 |
10 | const char* Altra64_GetVersionString(void)
11 | {
12 | return ALTRA64_VERSION;
13 | }
14 |
--------------------------------------------------------------------------------
/tools/deploy-sd.sh:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (c) 2017 The Altra64 project contributors
3 | # Portions (c) 2013 saturnu (Alt64) based on libdragon, Neo64Menu, ED64IO, libn64-hkz, libmikmod
4 | # See LICENSE file in the project root for full license information.
5 | #
6 |
7 | #! /bin/bash
8 | sudo mount /dev/sdb1 /mnt
9 | file=/mnt/ED64/OS64.v64
10 | if [ -e $file ]
11 | then
12 | echo -e "File $file exists - mount ok"
13 | echo -e "copy..."
14 | sudo cp ../bin/OS64.v64 /mnt/ED64/
15 | sudo cp ../res/ALT64.INI /mnt/ED64/
16 | echo -e "umounting..."
17 | sudo umount /mnt
18 | echo -e "done..."
19 | else
20 | echo -e "File $file doesnt exists - sdcard problem?"
21 | fi
22 |
--------------------------------------------------------------------------------
/tools/extract-firmware.cmd:
--------------------------------------------------------------------------------
1 | ::
2 | :: Copyright (c) 2017 The Altra64 project contributors
3 | :: See LICENSE file in the project root for full license information.
4 | ::
5 |
6 | @echo off
7 | cd ..
8 | set "fs=%cd%\res\filesystem\firmware"
9 | set "lfs=%fs%"
10 |
11 | set "drive=%lfs:~0,1%"
12 |
13 | set lfs=%lfs:~2%
14 | set "lfs=%lfs:\=/%"
15 |
16 | if %drive%==A set "drive=a"
17 | if %drive%==B set "drive=b"
18 | if %drive%==C set "drive=c"
19 | if %drive%==D set "drive=d"
20 | if %drive%==E set "drive=e"
21 | if %drive%==F set "drive=f"
22 | if %drive%==G set "drive=g"
23 | if %drive%==H set "drive=h"
24 | if %drive%==I set "drive=i"
25 | if %drive%==J set "drive=j"
26 | if %drive%==K set "drive=k"
27 | if %drive%==L set "drive=l"
28 | if %drive%==M set "drive=m"
29 | if %drive%==N set "drive=n"
30 | if %drive%==O set "drive=o"
31 | if %drive%==P set "drive=p"
32 | if %drive%==Q set "drive=q"
33 | if %drive%==R set "drive=r"
34 | if %drive%==S set "drive=s"
35 | if %drive%==T set "drive=t"
36 | if %drive%==U set "drive=u"
37 | if %drive%==V set "drive=v"
38 | if %drive%==W set "drive=w"
39 | if %drive%==X set "drive=x"
40 | if %drive%==Y set "drive=y"
41 | if %drive%==Z set "drive=z"
42 |
43 | set "lfs=/mnt/%drive%%lfs%"
44 |
45 | echo "Windows dir is %fs%"
46 | echo "Linux dir is %lfs%"
47 |
48 | :: del old firmware dir in ../res/filesystem
49 | RD /S /Q "%fs%"
50 | :: mk firmware dir in ../res/filesystem
51 | MKDIR "%fs%"
52 |
53 | SET "rom=%1"
54 | IF %1.==. (
55 | SET /P rom="Please enter full path to OS64.v64 V2.12:"
56 | )
57 |
58 | set "drive=%rom:~0,1%"
59 |
60 | set rom=%rom:~2%
61 | set "rom=%rom:\=/%"
62 |
63 | if %drive%==A set "drive=a"
64 | if %drive%==B set "drive=b"
65 | if %drive%==C set "drive=c"
66 | if %drive%==D set "drive=d"
67 | if %drive%==E set "drive=e"
68 | if %drive%==F set "drive=f"
69 | if %drive%==G set "drive=g"
70 | if %drive%==H set "drive=h"
71 | if %drive%==I set "drive=i"
72 | if %drive%==J set "drive=j"
73 | if %drive%==K set "drive=k"
74 | if %drive%==L set "drive=l"
75 | if %drive%==M set "drive=m"
76 | if %drive%==N set "drive=n"
77 | if %drive%==O set "drive=o"
78 | if %drive%==P set "drive=p"
79 | if %drive%==Q set "drive=q"
80 | if %drive%==R set "drive=r"
81 | if %drive%==S set "drive=s"
82 | if %drive%==T set "drive=t"
83 | if %drive%==U set "drive=u"
84 | if %drive%==V set "drive=v"
85 | if %drive%==W set "drive=w"
86 | if %drive%==X set "drive=x"
87 | if %drive%==Y set "drive=y"
88 | if %drive%==Z set "drive=z"
89 |
90 | set "rom=/mnt/%drive%%rom%"
91 |
92 | echo "Linux rom dir is %rom%"
93 |
94 |
95 |
96 | ::echo. "This script is not yet ready and will now exit."
97 | ::GOTO exit
98 |
99 | @echo ON
100 |
101 | :: OS64.V64 - Version 2.12 firmware offsets:
102 | :: cart offset (hex) offset (dec) length
103 | :: v2_old 0x25070 151664 61552
104 | :: v2 0x15930 88368 63276
105 | :: v2.5 0x340F0 213232 69911
106 | :: v3 0x45210 283152 71187
107 |
108 | :: Count = lengh / blocksize
109 | :: Seek = offset converted to decimal / blocksize
110 |
111 | :: ED rev 2_old
112 | bash --verbose -c "dd skip=9479 count=3847 if=%rom% of=%lfs%/firmware_v2_old.bin bs=16"
113 |
114 | :: ED rev 2.0 (default should return 0x214)
115 | bash --verbose -c "dd skip=5523 count=3954 if=%rom% of=%lfs%/firmware_v2.bin bs=16"
116 |
117 | :: ED rev 2.5 (default should return 0x250)
118 | bash --verbose -c "dd skip=13327 count=4369 if=%rom% of=%lfs%/firmware_v2_5.bin bs=16"
119 |
120 | :: ED rev 3 (default should return 0x300)
121 | bash --verbose -c "dd skip=17697 count=4449 if=%rom% of=%lfs%/firmware_v3.bin bs=16"
122 |
123 |
124 | pause
125 | :exit
--------------------------------------------------------------------------------
/tools/release-deploy.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | EXEC_DIR=$(pwd)
3 | RELEASE_ARTIFACT="ALTRA64.zip"
4 | docker run --rm -v "$EXEC_DIR:/build" ${REGISTRY}/${IMAGE_NAME}:master make
5 |
6 | # make the release dirs
7 |
8 | if [ ! -f "$EXEC_DIR/bin/OS64P.v64" ]; then
9 | echo "$EXEC_DIR/bin/OS64P.v64 doesnt exists, build failed."
10 | exit 1
11 | fi
12 |
13 | mkdir -p "$EXEC_DIR/release/ED64P/CFG" "$EXEC_DIR/release/ED64P/CHEATS" "$EXEC_DIR/release/ED64P/SDSAVE" "$EXEC_DIR/release/ED64P/WALLPAPER" "$EXEC_DIR/release/ED64P/MEMPAKS" "$EXEC_DIR/release/EMULATORS" "$EXEC_DIR/release/ROMS/"
14 | cp "$EXEC_DIR/bin/OS64P.v64" "$EXEC_DIR/release/ED64P/"
15 | cp "$EXEC_DIR/res/ALT64.INI" "$EXEC_DIR/release/ED64P/"
16 | cp "$EXEC_DIR/res/WALLPAPER/bg.bmp" "$EXEC_DIR/release/ED64P/WALLPAPER"
17 | cp "$EXEC_DIR/res/emulators/gb.v64" "$EXEC_DIR/release/EMULATORS"
18 | cp "$EXEC_DIR/res/emulators/neon64bu.rom" "$EXEC_DIR/release/EMULATORS"
19 | cp "$EXEC_DIR/res/emulators/ultraMSX2.z64" "$EXEC_DIR/release/EMULATORS"
20 | cp "$EXEC_DIR/res/emulators/UltraSMS.z64" "$EXEC_DIR/release/EMULATORS"
21 | cd "$EXEC_DIR/release"
22 |
23 | zip -9 -r $RELEASE_ARTIFACT .
24 |
--------------------------------------------------------------------------------
/tools/reset-wsfl.cmd:
--------------------------------------------------------------------------------
1 | ::::::::::::::::::::::::::::::::::::::::::::
2 | :: Elevate.cmd - Version 2
3 | :: Automatically check & get admin rights
4 | ::::::::::::::::::::::::::::::::::::::::::::
5 | @echo off
6 | CLS
7 | ECHO.
8 | ECHO =============================
9 | ECHO Running Admin shell
10 | ECHO =============================
11 |
12 | :init
13 | setlocal DisableDelayedExpansion
14 | set "batchPath=%~0"
15 | for %%k in (%0) do set batchName=%%~nk
16 | set "vbsGetPrivileges=%temp%\OEgetPriv_%batchName%.vbs"
17 | setlocal EnableDelayedExpansion
18 |
19 | :checkPrivileges
20 | NET FILE 1>NUL 2>NUL
21 | if '%errorlevel%' == '0' ( goto gotPrivileges ) else ( goto getPrivileges )
22 |
23 | :getPrivileges
24 | if '%1'=='ELEV' (echo ELEV & shift /1 & goto gotPrivileges)
25 | ECHO.
26 | ECHO **************************************
27 | ECHO Invoking UAC for Privilege Escalation
28 | ECHO **************************************
29 |
30 | ECHO Set UAC = CreateObject^("Shell.Application"^) > "%vbsGetPrivileges%"
31 | ECHO args = "ELEV " >> "%vbsGetPrivileges%"
32 | ECHO For Each strArg in WScript.Arguments >> "%vbsGetPrivileges%"
33 | ECHO args = args ^& strArg ^& " " >> "%vbsGetPrivileges%"
34 | ECHO Next >> "%vbsGetPrivileges%"
35 | ECHO UAC.ShellExecute "!batchPath!", args, "", "runas", 1 >> "%vbsGetPrivileges%"
36 | "%SystemRoot%\System32\WScript.exe" "%vbsGetPrivileges%" %*
37 | exit /B
38 |
39 | :gotPrivileges
40 | setlocal & pushd .
41 | cd /d %~dp0
42 | if '%1'=='ELEV' (del "%vbsGetPrivileges%" 1>nul 2>nul & shift /1)
43 |
44 | ::::::::::::::::::::::::::::
45 | ::START
46 | ::::::::::::::::::::::::::::
47 | @echo on
48 |
49 | lxrun /uninstall /full
50 |
51 | pause
--------------------------------------------------------------------------------
/tools/setup-linux.sh:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (c) 2017 The Altra64 project contributors
3 | # See LICENSE file in the project root for full license information.
4 | #
5 |
6 | #!/bin/bash
7 | # Download and install latest updates for the system [sudo req.]
8 | apt-get update
9 | apt-get -y upgrade
10 |
11 | # Install essential packages [sudo req.]
12 | apt-get -y install wget build-essential git texinfo libc6 libgmp-dev libmpfr-dev libmpc-dev libpng-dev zlib1g-dev libtool autoconf
13 |
14 | # change to the users root directory
15 | cd ~/
16 |
17 | # add a system variable and make it perminent
18 | # echo 'N64_INST=/usr/local/libdragon' >> /etc/environment
19 | # echo 'export N64_INST=/usr/local/libdragon' >> ~/.bashrc
20 | export N64_INST=/usr/local/libdragon
21 | # source ~/.bashrc
22 |
23 | # Pull the latest libdragon source code and make a build directory
24 | git clone https://github.com/dragonminded/libdragon.git
25 | # set to correct commit
26 | cd libdragon && git checkout b26fce6 && cd ..
27 |
28 | # fix issues with the build scripts
29 | sed -i -- 's|${N64_INST:-/usr/local}|/usr/local/libdragon|g' libdragon/tools/build
30 | sed -i -- 's|--with-newlib|--with-newlib --with-system-zlib|g' libdragon/tools/build
31 |
32 | sed -i -- 's| -lpng|\nLDLIBS = -lpng|g' libdragon/tools/mksprite/Makefile
33 | sed -i -- 's| -Werror| -w|g' libdragon/tools/mksprite/Makefile
34 |
35 | # make a build folder for libdragon
36 | mkdir libdragon/build_gcc
37 | cp libdragon/tools/build libdragon/build_gcc
38 |
39 | # run the build script (this will take a while! and if not sudo, will ask for password mid flow!)
40 | cd libdragon/build_gcc
41 | ./build
42 |
43 | cd ..
44 | # run the install script [sudo req]
45 | make
46 | make install
47 | make tools
48 | make tools-install
49 |
50 | cd ..
51 | # install libmikmod (custom version)
52 | git clone https://github.com/n64-tools/libmikmod
53 | cd libmikmod/n64
54 | make
55 | make install
56 | cd .. # we have are in a subfolder, this is not a duplicate...
57 |
58 | cd ..
59 | # install libyaml
60 | git clone https://github.com/yaml/libyaml
61 | cd libyaml
62 | ./bootstrap
63 | #$(N64_INST) converterd to $N64_INST below otherwise it will not run on WSFL
64 | export PATH=$PATH:$N64_INST/bin
65 | CFLAGS="-std=gnu99 -march=vr4300 -mtune=vr4300" \
66 | LDFLAGS="-L$N64_INST/lib -Tn64ld.x" \
67 | LIBS="-ldragon -lc -ldragonsys -lnosys" \
68 | ./configure --host=mips64-elf --prefix=$N64_INST
69 | make
70 | make install
71 |
72 | cd ..
73 | # install libmad (custom version)
74 | git clone https://github.com/n64-tools/libmad
75 | cd libmad
76 | export PATH=$PATH:$N64_INST/bin
77 | CFLAGS="-std=gnu99 -march=vr4300 -mtune=vr4300" \
78 | LDFLAGS="-L$N64_INST/lib -Tn64ld.x" \
79 | LIBS="-ldragon -lc -ldragonsys -lnosys" \
80 | ./configure --host=mips64-elf --prefix=$N64_INST
81 | make
82 | make install
83 |
84 | cd ..
85 |
86 | # Perform cleanup
87 | apt-get -y autoremove
88 | apt-get autoclean
89 |
--------------------------------------------------------------------------------
/tools/setup-wsfl.cmd:
--------------------------------------------------------------------------------
1 | ::::::::::::::::::::::::::::::::::::::::::::
2 | :: Elevate.cmd - Version 2
3 | :: Automatically check & get admin rights
4 | ::::::::::::::::::::::::::::::::::::::::::::
5 | @echo off
6 | CLS
7 | ECHO.
8 | ECHO =============================
9 | ECHO Running Admin shell
10 | ECHO =============================
11 |
12 | :init
13 | setlocal DisableDelayedExpansion
14 | set "batchPath=%~0"
15 | for %%k in (%0) do set batchName=%%~nk
16 | set "vbsGetPrivileges=%temp%\OEgetPriv_%batchName%.vbs"
17 | setlocal EnableDelayedExpansion
18 |
19 | :checkPrivileges
20 | NET FILE 1>NUL 2>NUL
21 | if '%errorlevel%' == '0' ( goto gotPrivileges ) else ( goto getPrivileges )
22 |
23 | :getPrivileges
24 | if '%1'=='ELEV' (echo ELEV & shift /1 & goto gotPrivileges)
25 | ECHO.
26 | ECHO **************************************
27 | ECHO Invoking UAC for Privilege Escalation
28 | ECHO **************************************
29 |
30 | ECHO Set UAC = CreateObject^("Shell.Application"^) > "%vbsGetPrivileges%"
31 | ECHO args = "ELEV " >> "%vbsGetPrivileges%"
32 | ECHO For Each strArg in WScript.Arguments >> "%vbsGetPrivileges%"
33 | ECHO args = args ^& strArg ^& " " >> "%vbsGetPrivileges%"
34 | ECHO Next >> "%vbsGetPrivileges%"
35 | ECHO UAC.ShellExecute "!batchPath!", args, "", "runas", 1 >> "%vbsGetPrivileges%"
36 | "%SystemRoot%\System32\WScript.exe" "%vbsGetPrivileges%" %*
37 | exit /B
38 |
39 | :gotPrivileges
40 | setlocal & pushd .
41 | cd /d %~dp0
42 | if '%1'=='ELEV' (del "%vbsGetPrivileges%" 1>nul 2>nul & shift /1)
43 |
44 | ::::::::::::::::::::::::::::
45 | ::START
46 | ::::::::::::::::::::::::::::
47 | @echo on
48 |
49 | lxrun /install /y
50 | bash -c "echo 'export N64_INST=/usr/local/libdragon' >> ~/.bashrc; source ~/.bashrc"
51 | bash -c "chmod +x ./setup-linux.sh"
52 | bash --verbose -c "source ./setup-linux.sh"
53 |
54 | ::bash
55 |
56 | pause
57 |
--------------------------------------------------------------------------------