Skip to content

Commit 383e5b4

Browse files
authored
Merge branch 'libretro:master' into naive-disk-control
2 parents ca9473d + 5121aa6 commit 383e5b4

9 files changed

+220
-79
lines changed

Diff for: libopera/discdata.h

+95
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
#include "extern_c.h"
2+
3+
#include <stdint.h>
4+
5+
EXTERN_C_BEGIN
6+
7+
/*
8+
Define the position of the primary label on each Opera disc, the
9+
block offset between avatars, and the index of the last avatar
10+
(i.e. the avatar count minus one). The latter figure *must* match
11+
the ROOT_HIGHEST_AVATAR figure from "filesystem.h", as the same
12+
File structure is use to read the label at boot time, and to provide
13+
access to the root directory.
14+
*/
15+
16+
#define DISC_LABEL_RECORD_TYPE 1
17+
#define DISC_BLOCK_SIZE 2048
18+
#define DISC_LABEL_OFFSET 225
19+
#define DISC_LABEL_AVATAR_DELTA 32786
20+
#define DISC_LABEL_HIGHEST_AVATAR 7
21+
#define DISC_TOTAL_BLOCKS 330000
22+
23+
#define ROOT_HIGHEST_AVATAR 7
24+
#define FILESYSTEM_MAX_NAME_LEN 32
25+
26+
#define VOLUME_STRUCTURE_OPERA_READONLY 1
27+
#define VOLUME_STRUCTURE_LINKED_MEM 2
28+
29+
#define NVRAM_VOLUME_UNIQUE_ID -1
30+
#define NVRAM_ROOT_UNIQUE_ID -2
31+
#define VOLUME_SYNC_BYTE 'Z'
32+
#define VOLUME_SYNC_BYTE_LEN 5
33+
#define VOLUME_COM_LEN 32
34+
#define VOLUME_ID_LEN 32
35+
36+
/*
37+
// This disc won't necessarily cause a reboot when inserted. This flag is
38+
// advisory ONLY. Only by checking with cdromdipir can you be really sure.
39+
// Place in dl_VolumeFlags. Note: the first volume gets this flag also.
40+
*/
41+
#define VOLUME_FLAGS_DATADISC 0x01
42+
43+
/*
44+
Data structures written on CD disc (Compact Disc disc?)
45+
*/
46+
typedef struct DiscLabel DiscLabel;
47+
struct DiscLabel
48+
{
49+
uint8_t dl_RecordType; /* Should contain 1 */
50+
uint8_t dl_VolumeSyncBytes[VOLUME_SYNC_BYTE_LEN]; /* Synchronization byte */
51+
uint8_t dl_VolumeStructureVersion; /* Should contain 1 */
52+
uint8_t dl_VolumeFlags; /* Should contain 0 */
53+
uint8_t dl_VolumeCommentary[VOLUME_COM_LEN]; /* Random comments about volume */
54+
uint8_t dl_VolumeIdentifier[VOLUME_ID_LEN]; /* Should contain disc name */
55+
uint32_t dl_VolumeUniqueIdentifier; /* Roll a billion-sided die */
56+
uint32_t dl_VolumeBlockSize; /* Usually contains 2048 */
57+
uint32_t dl_VolumeBlockCount; /* # of blocks on disc */
58+
uint32_t dl_RootUniqueIdentifier; /* Roll a billion-sided die */
59+
uint32_t dl_RootDirectoryBlockCount; /* # of blocks in root */
60+
uint32_t dl_RootDirectoryBlockSize; /* usually same as vol blk size */
61+
uint32_t dl_RootDirectoryLastAvatarIndex; /* should contain 7 */
62+
uint32_t dl_RootDirectoryAvatarList[ROOT_HIGHEST_AVATAR+1];
63+
};
64+
65+
typedef struct DirectoryHeader DirectoryHeader;
66+
struct DirectoryHeader
67+
{
68+
int32_t dh_NextBlock;
69+
int32_t dh_PrevBlock;
70+
uint32_t dh_Flags;
71+
uint32_t dh_FirstFreeByte;
72+
uint32_t dh_FirstEntryOffset;
73+
};
74+
75+
#define DIRECTORYRECORD(AVATARCOUNT) \
76+
uint32_t dir_Flags; \
77+
uint32_t dir_UniqueIdentifier; \
78+
uint32_t dir_Type; \
79+
uint32_t dir_BlockSize; \
80+
uint32_t dir_ByteCount; \
81+
uint32_t dir_BlockCount; \
82+
uint32_t dir_Burst; \
83+
uint32_t dir_Gap; \
84+
char dir_FileName[FILESYSTEM_MAX_NAME_LEN]; \
85+
uint32_t dir_LastAvatarIndex; \
86+
uint32_t dir_AvatarList[AVATARCOUNT];
87+
88+
typedef struct DirectoryRecord {
89+
DIRECTORYRECORD(1)
90+
} DirectoryRecord;
91+
92+
#define DIRECTORY_LAST_IN_DIR 0x80000000
93+
#define DIRECTORY_LAST_IN_BLOCK 0x40000000
94+
95+
EXTERN_C_END

Diff for: libopera/endianness.h

+5
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,14 @@
7575
#if IS_BIG_ENDIAN
7676

7777
#define swap32_if_little_endian(X) (X)
78+
#define swap32_if_le(X) (X)
7879
#define swap32_array_if_little_endian(X,Y)
80+
#define swap32_array_if_le(X,Y)
7981

8082
#else
8183

8284
#define swap32_if_little_endian(X) (SWAP32(X))
85+
#define swap32_if_le(X) (SWAP32(X))
8386

8487
static
8588
INLINE
@@ -93,6 +96,8 @@ swap32_array_if_little_endian(uint32_t *array_,
9396
array_[i] = SWAP32(array_[i]);
9497
}
9598

99+
#define swap32_array_if_le(X,Y) swap32_array_if_little_endian(X,Y)
100+
96101
#endif /* IS_BIG_ENDIAN */
97102

98103
#endif /* LIBOPERA_ENDIANNESS_H_INCLUDED */

Diff for: libopera/linkedmemblock.h

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#pragma once
2+
3+
#include <stdint.h>
4+
5+
/*
6+
LinkedMemDisk defines a high-level "disk" which consists of a
7+
doubly-linked list of storage blocks in memory (RAM, ROM, NVRAM,
8+
or out on a gamesaver cartridge. LinkedMemDisks have a standard
9+
Opera label at offset 0, with a type code of 2. The linked list
10+
normally begins immediately after the label; its offset is given
11+
by the zero'th avatar of the root directory. LinkedMemDisks are,
12+
by definition, flat file systems and cannot contain directories.
13+
*/
14+
15+
#define FINGERPRINT_FILEBLOCK 0xBE4F32A6
16+
#define FINGERPRINT_FREEBLOCK 0x7AA565BD
17+
#define FINGERPRINT_ANCHORBLOCK 0x855A02B6
18+
19+
typedef struct LinkedMemBlock LinkedMemBlock;
20+
struct LinkedMemBlock
21+
{
22+
uint32_t fingerprint;
23+
uint32_t flinkoffset;
24+
uint32_t blinkoffset;
25+
uint32_t blockcount;
26+
uint32_t headerblockcount;
27+
};

Diff for: libopera/opera_clio.c

+16-15
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ static
8787
void
8888
opera_clio_set_rom()
8989
{
90-
opera_mem_rom_select((CLIO.regs[0x84] & 0x4) ? ROM2 : ROM1);
90+
opera_mem_rom_select((CLIO.regs[0x84] & ADBIO_OTHERROM) ? ROM2 : ROM1);
9191
}
9292

9393
uint32_t
@@ -253,17 +253,18 @@ clio_handle_dma(uint32_t val_)
253253

254254
static
255255
void
256-
if_set_set_reset(uint32_t *output_,
257-
uint32_t val_,
258-
uint32_t mask_chk_,
259-
uint32_t mask_set_)
256+
adbio_set(uint32_t *output_,
257+
uint32_t val_,
258+
uint32_t bit_)
260259
{
261-
if((val_ & mask_chk_) == mask_chk_)
262-
{
263-
*output_ = ((val_ & mask_set_) ?
264-
(*output_ | mask_set_) :
265-
(*output_ & ~mask_set_));
266-
}
260+
uint32_t mask;
261+
262+
mask = (1 << bit_);
263+
264+
if((val_ & mask) == 0)
265+
*output_ &= ~mask;
266+
else if(val_ & (mask | (mask << 4)))
267+
*output_ |= mask;
267268
}
268269

269270
int
@@ -360,10 +361,10 @@ opera_clio_poke(uint32_t addr_,
360361
}
361362
else if(addr_ == 0x84)
362363
{
363-
if_set_set_reset(&CLIO.regs[0x84],val_,0x10,0x01);
364-
if_set_set_reset(&CLIO.regs[0x84],val_,0x20,0x02);
365-
if_set_set_reset(&CLIO.regs[0x84],val_,0x40,0x04);
366-
if_set_set_reset(&CLIO.regs[0x84],val_,0x80,0x08);
364+
adbio_set(&CLIO.regs[0x84],val_,0);
365+
adbio_set(&CLIO.regs[0x84],val_,1);
366+
adbio_set(&CLIO.regs[0x84],val_,2);
367+
adbio_set(&CLIO.regs[0x84],val_,3);
367368

368369
opera_clio_set_rom();
369370

Diff for: libopera/opera_clio.h

+3
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@
3535

3636
#include <stdint.h>
3737

38+
#define ADBIO_OTHERROM 0x04
39+
#define ADBIO_OTHERROM_EN (ADBIO_OTHERROM << 4)
40+
3841
EXTERN_C_BEGIN
3942

4043
void opera_clio_init(int reason_);

Diff for: libopera/opera_mem.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ opera_mem_rom2_byteswap32_if_le()
231231
void
232232
opera_mem_rom_select(void *rom_)
233233
{
234-
if((rom_ != ROM1) || (rom_ != ROM2))
234+
if((rom_ != ROM1) && (rom_ != ROM2))
235235
rom_ = ROM1;
236236

237237
ROM = rom_;

Diff for: libopera/opera_nvram.c

+64-62
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,81 @@
1+
#include "discdata.h"
2+
#include "linkedmemblock.h"
3+
14
#include "opera_mem.h"
25

36
#include "endianness.h"
47

8+
#include "boolean.h"
9+
510
#include <stdint.h>
611
#include <string.h>
712

8-
#pragma pack(push,1)
13+
#define NVRAM_BLOCKSIZE 1
14+
#define NVRAM_BLOCKCOUNT (32 * 1024)
915

10-
typedef struct nvram_header_t nvram_header_t;
11-
struct nvram_header_t
16+
bool
17+
opera_nvram_initialized(void *buf_,
18+
const int bufsize_)
1219
{
13-
uint8_t record_type;
14-
uint8_t sync_bytes[5];
15-
uint8_t record_version;
16-
uint8_t flags;
17-
uint8_t comment[32];
18-
uint8_t label[32];
19-
uint32_t id;
20-
uint32_t block_size;
21-
uint32_t block_count;
22-
uint32_t root_dir_id;
23-
uint32_t root_dir_blocks;
24-
uint32_t root_dir_block_size;
25-
uint32_t last_root_dir_copy;
26-
uint32_t root_dir_copies[8];
20+
int i;
21+
DiscLabel *dl;
2722

28-
uint32_t unknown_value0;
29-
uint32_t unknown_value1;
30-
uint32_t unknown_value2;
31-
uint32_t unknown_value3;
32-
uint32_t unknown_value4;
33-
uint32_t unknown_value5;
34-
uint32_t unknown_value6;
35-
uint32_t unknown_value7;
36-
uint32_t blocks_remaining;
37-
uint32_t unknown_value8;
38-
};
23+
dl = (DiscLabel*)buf_;
3924

40-
#pragma pack(pop)
25+
if(dl->dl_RecordType != DISC_LABEL_RECORD_TYPE)
26+
return false;
27+
if(dl->dl_VolumeStructureVersion != VOLUME_STRUCTURE_LINKED_MEM)
28+
return false;
29+
for(i = 0; i < VOLUME_SYNC_BYTE_LEN; i++)
30+
{
31+
if(dl->dl_VolumeSyncBytes[i] != VOLUME_SYNC_BYTE)
32+
return false;
33+
}
34+
35+
return true;
36+
}
4137

38+
// The below code mimics the official 3DO formatting tool "format"
39+
// https://github.com/trapexit/portfolio_os/blob/master/src/filesystem/format.c
40+
// https://github.com/trapexit/portfolio_os/blob/master/src/filesystem/lmadm.c
4241
void
43-
opera_nvram_init(void)
42+
opera_nvram_init(void *buf_,
43+
const int bufsize_)
4444
{
45-
nvram_header_t *nvram_hdr = (nvram_header_t*)NVRAM;
45+
DiscLabel *disc_label;
46+
LinkedMemBlock *anchor_block;
47+
LinkedMemBlock *free_block;
48+
49+
disc_label = (DiscLabel*)buf_;
50+
anchor_block = (LinkedMemBlock*)&disc_label[1];
51+
free_block = &anchor_block[1];
52+
53+
memset(buf_,0,bufsize_);
54+
55+
disc_label->dl_RecordType = DISC_LABEL_RECORD_TYPE;
56+
memset(disc_label->dl_VolumeSyncBytes,VOLUME_SYNC_BYTE,VOLUME_SYNC_BYTE_LEN);
57+
disc_label->dl_VolumeStructureVersion = VOLUME_STRUCTURE_LINKED_MEM;
58+
disc_label->dl_VolumeFlags = 0;
59+
strncpy((char*)disc_label->dl_VolumeCommentary,"opera formatted", VOLUME_COM_LEN);
60+
strncpy((char*)disc_label->dl_VolumeIdentifier,"nvram", VOLUME_ID_LEN);
61+
disc_label->dl_VolumeUniqueIdentifier = swap32_if_le(NVRAM_VOLUME_UNIQUE_ID); // ???
62+
disc_label->dl_VolumeBlockSize = swap32_if_le(NVRAM_BLOCKSIZE);
63+
disc_label->dl_VolumeBlockCount = swap32_if_le(bufsize_);
64+
disc_label->dl_RootUniqueIdentifier = swap32_if_le(NVRAM_ROOT_UNIQUE_ID);
65+
disc_label->dl_RootDirectoryBlockCount = 0;
66+
disc_label->dl_RootDirectoryBlockSize = swap32_if_le(NVRAM_BLOCKSIZE);
67+
disc_label->dl_RootDirectoryLastAvatarIndex = 0;
68+
disc_label->dl_RootDirectoryAvatarList[0] = swap32_if_le(sizeof(DiscLabel));
4669

47-
memset(nvram_hdr,0,sizeof(nvram_header_t));
70+
anchor_block->fingerprint = swap32_if_le(FINGERPRINT_ANCHORBLOCK);
71+
anchor_block->flinkoffset = swap32_if_le(sizeof(DiscLabel) + sizeof(LinkedMemBlock));
72+
anchor_block->blinkoffset = swap32_if_le(sizeof(DiscLabel) + sizeof(LinkedMemBlock));
73+
anchor_block->blockcount = swap32_if_le(sizeof(LinkedMemBlock));
74+
anchor_block->headerblockcount = swap32_if_le(sizeof(LinkedMemBlock));
4875

49-
nvram_hdr->record_type = 0x01;
50-
nvram_hdr->sync_bytes[0] = 'Z';
51-
nvram_hdr->sync_bytes[1] = 'Z';
52-
nvram_hdr->sync_bytes[2] = 'Z';
53-
nvram_hdr->sync_bytes[3] = 'Z';
54-
nvram_hdr->sync_bytes[4] = 'Z';
55-
nvram_hdr->record_version = 0x02;
56-
nvram_hdr->label[0] = 'N';
57-
nvram_hdr->label[1] = 'V';
58-
nvram_hdr->label[2] = 'R';
59-
nvram_hdr->label[3] = 'A';
60-
nvram_hdr->label[4] = 'M';
61-
nvram_hdr->id = swap32_if_little_endian(0xFFFFFFFF);
62-
nvram_hdr->block_size = swap32_if_little_endian(0x00000001);
63-
nvram_hdr->block_count = swap32_if_little_endian(0x00008000);
64-
nvram_hdr->root_dir_id = swap32_if_little_endian(0xFFFFFFFE);
65-
nvram_hdr->root_dir_blocks = swap32_if_little_endian(0x00000000);
66-
nvram_hdr->root_dir_block_size = swap32_if_little_endian(0x00000001);
67-
nvram_hdr->last_root_dir_copy = swap32_if_little_endian(0x00000000);
68-
nvram_hdr->root_dir_copies[0] = swap32_if_little_endian(0x00000084);
69-
nvram_hdr->unknown_value0 = swap32_if_little_endian(0x855A02B6);
70-
nvram_hdr->unknown_value1 = swap32_if_little_endian(0x00000098);
71-
nvram_hdr->unknown_value2 = swap32_if_little_endian(0x00000098);
72-
nvram_hdr->unknown_value3 = swap32_if_little_endian(0x00000014);
73-
nvram_hdr->unknown_value4 = swap32_if_little_endian(0x00000014);
74-
nvram_hdr->unknown_value5 = swap32_if_little_endian(0x7AA565BD);
75-
nvram_hdr->unknown_value6 = swap32_if_little_endian(0x00000084);
76-
nvram_hdr->unknown_value7 = swap32_if_little_endian(0x00000084);
77-
nvram_hdr->blocks_remaining = swap32_if_little_endian(0x00007F68);
78-
nvram_hdr->unknown_value8 = swap32_if_little_endian(0x00000014);
76+
free_block->fingerprint = swap32_if_le(FINGERPRINT_FREEBLOCK);
77+
free_block->flinkoffset = swap32_if_le(sizeof(DiscLabel));
78+
free_block->blinkoffset = swap32_if_le(sizeof(DiscLabel));
79+
free_block->blockcount = swap32_if_le(bufsize_ - sizeof(DiscLabel) - sizeof(LinkedMemBlock));
80+
free_block->headerblockcount = swap32_if_le(sizeof(LinkedMemBlock));
7981
}

Diff for: libopera/opera_nvram.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
#ifndef OPERA_NVRAM_H_INCLUDED
22
#define OPERA_NVRAM_H_INCLUDED
33

4-
void opera_nvram_init(void);
4+
#include "boolean.h"
5+
6+
bool opera_nvram_initialized(void *buf, const int bufsize);
7+
void opera_nvram_init(void *buf, const int bufsize);
58

69
#endif

Diff for: opera_lr_nvram.c

+5
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,8 @@ opera_lr_nvram_save(const char *gamepath_,
377377
}
378378
}
379379

380+
// Try to load. If it fails ensure the NVRAM is initialized.
381+
// Not all games will force a format if the NVRAM is corrupt.
380382
void
381383
opera_lr_nvram_load(const char *gamepath_,
382384
const bool shared_,
@@ -400,4 +402,7 @@ opera_lr_nvram_load(const char *gamepath_,
400402

401403
opera_lr_nvram_load_pergame(NVRAM,NVRAM_SIZE,filename,version_);
402404
}
405+
406+
if(!opera_nvram_initialized(NVRAM,NVRAM_SIZE))
407+
opera_nvram_init(NVRAM,NVRAM_SIZE);
403408
}

0 commit comments

Comments
 (0)