-
Notifications
You must be signed in to change notification settings - Fork 1
/
neoyume_upper.spin2
892 lines (784 loc) · 26 KB
/
neoyume_upper.spin2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
CON ' Header
''
'' ### ### ######### ###### ##### ### #### ### ### ### #########
'' ### # ## # ## ## ## # ## # ### ### ## #
'' # ## # ## # ## ## # ## # ## # # ## # ## ## #
'' # ## # ##### ### ### ### ## # ## # # ## # ## #####
'' # ## # ## # ## ## # ## ## # # ## # ## ## #
'' # ### ## # ## ## ## ## # # ### ## ## #
'' ### ### ######### ###### #### #### ### # #### #########
''
'' MAX 256 MEGA
'' PROP-GEAR SPEC
''
VERSION_MAJOR = 1
VERSION_MINOR = 4
VERSION_RC = 1
#include "config.spin2"
#ifdef _SDHC_45MHZ
#pragma exportdef _SDHC_45MHZ
#endif
MKRAM_BASE = $1_0000
HEAPSIZE = 1024*8
VINT_LOCK = 9
STATIC_LOCKS = decod VINT_LOCK
PATH_MAX = 256
CON
BG_NORMAL = $010101_00
BG_SELECTION = $1111AA_00
FG_NORMAL = $FDFDFD_00
FG_ISSUE = $B0C040_00
FG_BROKEN = $C04040_00
FG_GREY = $606060_00
#0,BIOS_EXPORT,BIOS_JAPAN,BIOS_UNIBIOS,BIOS_MAXNUM
DEFAULT_BIOS = USE_UNIBIOS ? BIOS_UNIBIOS : (USE_JP_BIOS ? BIOS_JAPAN : BIOS_EXPORT)
VAR
long exmem_mailbox[8*3]
long exmem_size
byte lspc_cog,blt_cog,opnb_cog,exmem_cog
byte bios_type
long loadpos
OBJ
video : "NeoVGA"
c : "libc"
a : "fsadapter.c"
padmap: "padmap_parser"
#ifdef USE_PSRAM16
exmem : "psram16drv.spin2"
#elseifdef USE_PSRAM8
exmem : "psram8drv.spin2"
#elseifdef USE_PSRAM4
exmem : "psram4drv-dualCE.spin2"
#elseifdef USE_HYPER
exmem : "hyperdrv.spin2"
#endif
PUB main() | tmp,tmp2
bios_type := DEFAULT_BIOS
org
' allocate all the locks like some sort of maniac
mov pa,#0
rep @.lockmadness,#16
locknew pb wc
if_nc bith pa,pb
.lockmadness
' deallocate all the ones we don't want
andn pa,##STATIC_LOCKS
mov pb,#0
rep @.lockmadness2,#16
shr pa,#1 wc
if_c lockret pb
add pb,#1
.lockmadness2
end
' setup video driver
'video.start($F8,0,long[$20],VIDEO_MODE,VGA_BASEPIN,VGA_VSYNC,VIDEO_SUBMODE) '
video.start(ANALOG_BASEPIN&63 + (DIGITAL_BASEPIN&63)<<8 + (DIGITAL_REVERSED?64<<8:0),VSYNC_PIN,VIDEO_MODE,VIDEO_SUBMODE,long[$20],16*4,2,$F8,$80000,video.CLK_MULTIPLIER*3*4*6*6)
lspc_cog := coginit(COGEXEC_NEW,long[$34],0) ' Start LSPC
blt_cog := coginit(COGEXEC_NEW,long[$38],0) ' Start blitter
coginit(COGEXEC_NEW,long[$44],0) ' Start input cog
opnb_cog := coginit(HUBEXEC_NEW,long[$3C],0) ' Start OPNB
'longmove(long[$24],@menu_palette,16)
gen_gradient_palette(long[$24]+0*16*4,BG_NORMAL,FG_NORMAL)
gen_gradient_palette(long[$24]+1*16*4,BG_NORMAL,FG_ISSUE)
gen_gradient_palette(long[$24]+2*16*4,BG_NORMAL,FG_BROKEN)
gen_gradient_palette(long[$24]+3*16*4,BG_NORMAL,FG_GREY)
gen_gradient_palette(long[$24]+4*16*4,BG_SELECTION,FG_NORMAL)
gen_gradient_palette(long[$24]+5*16*4,BG_SELECTION,FG_ISSUE)
gen_gradient_palette(long[$24]+6*16*4,BG_SELECTION,FG_BROKEN)
gen_gradient_palette(long[$24]+7*16*4,BG_SELECTION,FG_GREY)
wordfill(long[$28]+$E000," ",32*40)
putgfx(256,5,1,30,4)
_mount(@"/sd",c._vfs_open_sdcardx(SDCARD_CLK,SDCARD_SELECT,SDCARD_DI,SDCARD_DO))
exmem_start()
#ifdef INPUT_USE_USB
repeat until long[$68]
tmp := c.fopen(@"/sd/PADMAP.TXT",@"r")
if tmp
padmap.parse(long[$68],long[$6C],@c.fgetc,tmp,@"neoyume")
c.fclose(tmp)
long[$68] := 0
#endif
tmp := c.malloc(64)
c.sprintf(tmp,@"MAX %d MEGA",exmem_size+/$20000)
putstring(tmp,14,6,0)
putstring(@"PROP-GEAR SPEC",13,7,0)
if VERSION_RC < 0
c.sprintf(tmp,@"V%d.%d",VERSION_MAJOR,VERSION_MINOR)
elseif VERSION_RC == 0
c.sprintf(tmp,@"V%d.%d-beta",VERSION_MAJOR,VERSION_MINOR)
else
c.sprintf(tmp,@"V%d.%d-RC%d",VERSION_MAJOR,VERSION_MINOR,VERSION_RC)
putstring(tmp,2,6,0)
c.free(tmp)
{
repeat
repeat tmp2 from 0 to 9
putstring(word[$60].[tmp2] ? @"X" : @"_",20+tmp2,8,0)
'}
#ifdef DIRECT_BOOT
load_game(@DIRECT_BOOT)
#else
if USE_ARGV && long[$FC000] == ("A" + "R"<<8 + "G"<<16 + "v"<<24) && word[$FC004] <> 0
tmp := $FC004 + 1 + strsize($FC004)
if byte[tmp] <> 0
ifnot c.strcasecmp(tmp,@"japan")
bios_type := BIOS_JAPAN
elseifnot c.strcasecmp(tmp,@"export")
bios_type := BIOS_EXPORT
elseifnot c.strcasecmp(tmp,@"unibios")
bios_type := BIOS_UNIBIOS
else
putstring(@"ARGv invalid BIOS",2,10,0)
repeat
repeat tmp from 0 to ((@gamelist_end - @gamelist)/2)-1
ifnot c.strcasecmp($FC004,gamelist[tmp]+@gamedb_base)
load_game(gamelist[tmp]+@gamedb_base)
quit
if tmp == ((@gamelist_end - @gamelist)/2)
putstring(@"ARGv invalid",2,10,0)
repeat
else
tmp := do_gamechoose()
load_game(gamelist[tmp]+@gamedb_base)
#endif
putstring(@"Load ok?",2,10,0)
'repeat
exmem_stop()
coginit(HUBEXEC_NEW,long[$1C],0) ' Start 68000
cogatn(1<<opnb_cog) ' Properly init OPNB
coginit(HUBEXEC_NEW,long[$30],0) ' Start Z80
coginit(COGEXEC+cogid(),long[$40],0) ' Start memory arbiter
PRI putstring(str,x,y,attr) | chr
repeat while chr:=byte[str++]
if x <+ 40 and y <+ 28
word[long[$28]+$E004][y+x<<5] := chr + attr
x++
PRI putgfx(base,x,y,width,height) | ptr
repeat width
ptr := @word[long[$28]+$E004][y+x<<5]
repeat height
word[ptr] := base++
ptr+=2
x++
PRI settiles(x1,x2,y1,y2,tile) | i
if x2 >= x1 and y2 >= y1
repeat i from x1 to x2
wordfill(long[$28]+$E004+(i<<5+y1)<<1,tile,y2-y1+1)
PRI settile(x,y,tile) | i
word[long[$28]+$E004+(x<<5+y)<<1] := tile
PRI is_dualfile(cmd) : r
return cmd == LOAD_CROM || cmd == LOAD_CROM+WITH_OFFSET || cmd == LOAD_SROM_CMC || cmd == LOAD_SROM_CMC+WITH_OFFSET
PRI count_romsize(gameptr,count_all) : size | cmd
gameptr += strsize(gameptr)+1 ' advance to display name
gameptr += strsize(gameptr)+1 ' advance to ROM prefix
gameptr += strsize(gameptr)+1+1 ' advance to script
repeat
case cmd := byte[gameptr++]
0: quit
LOADCMD_FIRST..LOADCMD_LAST,(LOADCMD_FIRST+WITH_OFFSET)..(LOADCMD_LAST+WITH_OFFSET):
gameptr += strsize(gameptr)+1
if is_dualfile(cmd)
gameptr += strsize(gameptr)+1
size += word[gameptr]*4096
gameptr += 2
if cmd >= LOADCMD_FIRST+WITH_OFFSET
gameptr += 2
LOAD_BIOS:
if count_all
size += $20000
LOAD_FILLER:
gameptr += 1
if count_all
size += word[gameptr]*4096
gameptr += 2
(SETCMD_FIRST+WITH_OFFSET)..(SETCMD_LAST+WITH_OFFSET):
gameptr += 2
SET_TILEMASK:
gameptr++
other: ' Do nothing
PRI init_bar(size) | i,j,loadblocks,ramblocks
loadpos := 0
settiles(0,39,LOADBAR_Y,LOADBAR_Y+LOADBAR_SIZE-1," ")
'settiles(4,35,LOADBAR_Y,LOADBAR_Y+LOADBAR_SIZE-1,"."+3<<12)
loadblocks := size/+LOADBAR_BLOCK
ramblocks := exmem_size/+LOADBAR_BLOCK
repeat i from 0 to 11
if ramblocks > 0
settiles(4,4+(ramblocks<#32)-1,LOADBAR_Y+i,LOADBAR_Y+i,15+3<<12)
ramblocks -= 32
if loadblocks > 0
settiles(4,4+(loadblocks<#32)-1,LOADBAR_Y+i,LOADBAR_Y+i,15+0<<12)
loadblocks -= 32
PRI push_bar(bytes) | oldblk,newblk,i
oldblk := loadpos/+LOADBAR_BLOCK
newblk := (loadpos+=bytes)/+LOADBAR_BLOCK
if oldblk <> newblk
repeat
settile(4+(oldblk&31),LOADBAR_Y+(oldblk>>5),14)
while ++oldblk < newblk
PRI load_game(gameptr) | common,cmd,fn1,fn2,len,exptr,tmp
common := __builtin_alloca(PATH_MAX)
fn1 := __builtin_alloca(PATH_MAX)
fn2 := __builtin_alloca(PATH_MAX)
exptr := 0
init_bar(count_romsize(gameptr,true))
c.strcpy(common,@"/sd/NEOYUME/")
c.strncat(common,gameptr,PATH_MAX-1) ' catenate romset name
c.strncat(common,@"/",PATH_MAX-1)
gameptr += strsize(gameptr)+1 ' advance to display name
gameptr += strsize(gameptr)+1 ' advance to ROM prefix
c.strncat(common,gameptr,PATH_MAX-1) ' catenate prefix
gameptr += strsize(gameptr)+1+1 ' advance to script
long[$88] := 0 ' default to no bankswitch
long[$A4] := 31 ' default to no tile masking
' Interpret load script
repeat
case cmd := byte[gameptr++]
0: quit
LOADCMD_FIRST..LOADCMD_LAST,(LOADCMD_FIRST+WITH_OFFSET)..(LOADCMD_LAST+WITH_OFFSET):
c.strcpy(fn1,common)
c.strncat(fn1,gameptr,PATH_MAX-1) ' first file name
c.strncat(fn1,@".BIN",PATH_MAX-1)
gameptr += strsize(gameptr)+1
if is_dualfile(cmd)
c.strcpy(fn2,common)
c.strncat(fn2,gameptr,PATH_MAX-1) ' second file name
c.strncat(fn2,@".BIN",PATH_MAX-1)
gameptr += strsize(gameptr)+1
else
byte[fn2] := 0
len := word[gameptr]*4096
gameptr += 2
if cmd >= LOADCMD_FIRST+WITH_OFFSET
cmd -= WITH_OFFSET
tmp := word[gameptr]*4096
gameptr += 2
else
tmp := 0
load_romdata(exptr,len,tmp,cmd,fn1,fn2)
exptr += len
LOAD_BIOS:
c.strcpy(fn1,@"/sd/NEOYUME/NEOGEO/")
case bios_type
BIOS_EXPORT: c.strncat(fn1,@"NEO-EPO.BIN",PATH_MAX-1)
BIOS_JAPAN: c.strncat(fn1,@"NEO-PO.BIN",PATH_MAX-1)
BIOS_UNIBIOS: c.strncat(fn1,@"UNI-BIOS.BIN",PATH_MAX-1)
load_romdata(exptr,$2_0000,0,LOAD_BSWAP,fn1,0)
exptr += $2_0000
LOAD_FILLER:
tmp := byte[gameptr++]
len := word[gameptr]*4096
gameptr += 2
exmem_fill(exptr,tmp,len,true)
push_bar(len)
exptr += len
SETCMD_FIRST..SETCMD_LAST:
long[$80][cmd-SETCMD_FIRST] := exptr
(SETCMD_FIRST+WITH_OFFSET)..(SETCMD_LAST+WITH_OFFSET):
long[$80][cmd-(SETCMD_FIRST+WITH_OFFSET)] := exptr + (word[gameptr] signx 15)*4096
gameptr += 2
SET_BANKSWITCH_2M:
long[$88] := $10_0000
SET_BANKSWITCH_4M:
long[$88] := $30_0000
SET_BANKSWITCH_8M:
long[$88] := $70_0000
SET_BANKSWITCH_PVC_8M:
long[$88] := 22 + negx
SET_TILEMASK:
long[$A4] := byte[gameptr++]
other:
c.sprintf(fn1,@"bad script: %d !",cmd)
putstring(fn1,2,25,0)
repeat
if exptr > exmem_size
c.sprintf(fn1,@"exptr over: %08X !",exptr)
putstring(fn1,2,25,0)
repeat
if exmem_size>exptr
exmem_fill(exptr,$DB,exmem_size-exptr,false) ' fill remaining memory with pattern
PRI check_filesize(fptr) : r
c.fseek(fptr,0,c.SEEK_END)
r := c.ftell(fptr)
c.fseek(fptr,0,c.SEEK_SET)
PRI load_romdata(target,size,offset,type,path1,path2) | f1,f2,pos,tmp,tmp2,tmp3,i,j,k,l,tmpstr,pushed,memo1
settiles(0,39,22,27," ")
tmpstr := __builtin_alloca(64)
c.sprintf(tmpstr,@"Loading %d bytes, type %d",size,type)
putstring(tmpstr,2,23,0)
putstring(path1,3,24,0)
if path2
putstring(path2,3,25,0)
f1 := c.fopen(path1,@"rb")
ifnot f1
putstring(@"file1: ",2,26,0)
putstring(c.strerror(errno),2+7,26,0)
repeat
if is_dualfile(type)
tmp := size/2 + offset
f2 := c.fopen(path2,@"rb")
ifnot f2
putstring(@"file2: ",2,26,0)
putstring(c.strerror(errno),2+7,26,0)
repeat
else
f2 := 0
tmp := size + offset
if (tmp2:=check_filesize(f1)) < tmp
c.sprintf(tmpstr,@"file1 too short: %d < %d",tmp2,tmp)
putstring(tmpstr,2,26,0)
repeat
if f2 __andthen__ (tmp2:=check_filesize(f2)) < tmp
c.sprintf(tmpstr,@"file2 too short: %d < %d",tmp2,tmp)
putstring(tmpstr,2,26,0)
repeat
if offset
c.fseek(f1,offset,c.SEEK_SET)
if f2
c.fseek(f2,offset,c.SEEK_SET)
pos := 0
repeat while pos < size
case type
LOAD_RAW: ' Only type that can load arbitrary lengths
tmp := $10000 <# size-pos
c.fread(MKRAM_BASE,1,tmp,f1)
exmem_write(target+pos,MKRAM_BASE,tmp,false)
pushed:=tmp
LOAD_BSWAP:
c.fread(MKRAM_BASE,1,$10000,f1)
'repeat i from MKRAM_BASE to MKRAM_BASE+$FFFC step 4
' long[i] := __builtin_movbyts(long[i],%%2301)
org
loc ptrb,#\MKRAM_BASE
rdfast #0,ptrb
rep @.swaplp,##$10000/4
rflong i
movbyts i,#%%2301
wrlong i,ptrb++
.swaplp
end
exmem_write(target+pos,MKRAM_BASE,$1_0000,false)
pushed:=$10000
LOAD_CROM:
c.fread(MKRAM_BASE+$0000,1,$4000,f1)
c.fread(MKRAM_BASE+$4000,1,$4000,f2)
exmem_sync()
org
wrfast #0,##MKRAM_BASE+$8000
loc ptrb,#\MKRAM_BASE
mov tmp,#256
.loop1
rep @.loop2,#8
rdlong i,ptrb[$00/4]
rdlong j,ptrb[$20/4]
bitnot ptrb,#encod $4000
rdlong k,ptrb[$00/4]
rdlong l,ptrb[$20/4]
getword tmp2,l,#1
rolword tmp2,j,#1
mergeb tmp2
getword tmp3,k,#1
rolword tmp3,i,#1
mergeb tmp3
rolword l,j,#0
mergeb l
rolword k,i,#0
mergeb k
wflong l
wflong k
wflong tmp2
wflong tmp3
sub ptrb,##$4000 - 4
.loop2
add ptrb,#$20
djnz tmp,#.loop1
end
exmem_write(target+pos,MKRAM_BASE+$8000,$8000,true)
pushed:=$8000
LOAD_SROM_CMC:
c.fread(MKRAM_BASE+$0000,1,$4000,f1)
c.fread(MKRAM_BASE+$4000,1,$4000,f2)
k := MKRAM_BASE
l := MKRAM_BASE+$8000
repeat 8192
long[l] := __builtin_movbyts(word[k],%%0123) | __builtin_movbyts(word[k+$4000],%%2301)
l+=4
k+=2
exmem_write(target+pos,MKRAM_BASE+$8000,$8000,false)
pushed:=$8000
LOAD_SROM:
c.fread(MKRAM_BASE,1,$10000,f1)
repeat i from $ffff to $0000
j := i
repeat
j.[4..0] := j.[4..2] + (j.[1..0]^2)<<3
while i < j
tmp := byte[MKRAM_BASE+i]
byte[MKRAM_BASE+i] := byte[MKRAM_BASE+j]
byte[MKRAM_BASE+j] := tmp
exmem_write(target+pos,MKRAM_BASE,$10000,false)
pushed:=$10000
LOAD_LSWAP:
c.fread(MKRAM_BASE,1,$10000,f1)
repeat i from MKRAM_BASE+$0000 to MKRAM_BASE+$10000-8 step 8
k := long[i]
long[i] := long[i+4]
long[i+4] := k
exmem_write(target+pos,MKRAM_BASE,$10000,false)
pushed:=$10000
LOAD_WSWAP:
c.fread(MKRAM_BASE,1,$10000,f1)
repeat i from MKRAM_BASE to MKRAM_BASE+$FFFC step 4
long[i] := __builtin_movbyts(long[i],%%1032)
exmem_write(target+pos,MKRAM_BASE,$10000,false)
pushed:=$10000
LOAD_QSWAP:
c.fread(MKRAM_BASE,1,$10000,f1)
repeat i from MKRAM_BASE+$0000 to MKRAM_BASE+$10000-16 step 16
k := long[i]
long[i] := long[i+8]
long[i+8] := k
k := long[i+4]
long[i+4] := long[i+12]
long[i+12] := k
exmem_write(target+pos,MKRAM_BASE,$10000,false)
pushed:=$10000
other:
putstring(@"what??? ",2,25,0)
repeat
pos += pushed
push_bar(pushed)
if f1
c.fclose(f1)
if f2
c.fclose(f2)
exmem_sync()
CON
GAMECHOOSE_SIZE = 12
GAMECHOOSE_Y = 9
GAMECHOOSE_X = 3
GAMECHOOSE_WIDTH = 33 ' Note: game titles are NOT truncated
LOADBAR_Y = 9
LOADBAR_SIZE = 12
LOADBAR_BLOCK = 256*1024
PRI do_gamechoose() : selected | i,games_got,mingot,maxgot,got_count,max_count,dir,ent,name,lptr,tmpstr,tmp,tmp2,input,previnput,drawtop,drawlast,repeatkey,repeatnext
previnput := 0
repeatkey := 0
tmpstr := __builtin_alloca(64)
max_count := (@gamelist_end - @gamelist)/2
games_got := __builtin_alloca(max_count)
bytefill(games_got,0,max_count)
mingot := posx
maxgot := negx
got_count := 0
dir := c.opendir(@"/sd/NEOYUME/")
ifnot dir
putstring(@"Directory error:",2,24,0)
putstring(c.strerror(errno),3,25,0)
repeat
repeat
ent := c.readdir(dir)
ifnot ent
quit
name := a.get_name(ent)
'putstring(name,2,25,0)
repeat i from 0 to max_count-1
ifnot c.strcasecmp(name,gamelist[i]+@gamedb_base) '|| not i.[0]
byte[games_got][i] := 1
got_count++
mingot <#= i
maxgot #>= i
quit
c.closedir(dir)
tmp := 0
repeat i from 0 to max_count-1
if byte[games_got][i]
byte[games_got][i] := ++tmp
ifnot got_count
putstring(@"NO GAMES!",4,14,0)
repeat
selected := mingot
drawtop := mingot
repeat
ent := drawtop
repeat i from GAMECHOOSE_Y to GAMECHOOSE_Y+GAMECHOOSE_SIZE-1
tmp := selected == ent ? 4<<12 : 0
if ent <= maxgot
lptr := gamelist[ent]+@gamedb_base
c.sprintf(tmpstr,@"%dM",(count_romsize(lptr,false)+$1ffff)+/$20000)
name := lptr+strsize(lptr)+1
tmp2 := name+strsize(name)+1
tmp2 += strsize(tmp2)+1
tmp2 := tmp+(count_romsize(lptr,true) > exmem_size ? 3 : byte[tmp2])<<12
settiles(GAMECHOOSE_X,GAMECHOOSE_X+GAMECHOOSE_WIDTH-1,i,i,"."+(3<<12)+tmp)
putstring(tmpstr,GAMECHOOSE_X+GAMECHOOSE_WIDTH-strsize(tmpstr),i,tmp2)
putstring(name,GAMECHOOSE_X,i,tmp2)
drawlast := ent
repeat until byte[games_got][++ent]
else
settiles(GAMECHOOSE_X,GAMECHOOSE_X+GAMECHOOSE_WIDTH-1,i,i," "+tmp)
putstring(string(4),GAMECHOOSE_X+GAMECHOOSE_WIDTH,GAMECHOOSE_Y,drawtop == mingot ? 3<<12 : 0)
putstring(string(5),GAMECHOOSE_X+GAMECHOOSE_WIDTH,GAMECHOOSE_Y+GAMECHOOSE_SIZE-1,drawlast == maxgot ? 3<<12 : 0)
tmp := ((byte[games_got][drawtop]-1)*(GAMECHOOSE_SIZE-2)) / (got_count-GAMECHOOSE_SIZE) <# GAMECHOOSE_SIZE-3
repeat i from GAMECHOOSE_Y+1 to GAMECHOOSE_Y+GAMECHOOSE_SIZE-2
if i-(GAMECHOOSE_Y+1) == tmp && got_count > GAMECHOOSE_SIZE
putstring(string(14),GAMECHOOSE_X+GAMECHOOSE_WIDTH,i,0<<12)
else
putstring(string(58),GAMECHOOSE_X+GAMECHOOSE_WIDTH,i,3<<12)
settiles(GAMECHOOSE_X,GAMECHOOSE_X+GAMECHOOSE_WIDTH-1,GAMECHOOSE_Y+GAMECHOOSE_SIZE+2,GAMECHOOSE_Y+GAMECHOOSE_SIZE+2," ")
c.sprintf(tmpstr,@"Got: %3d/%d",got_count,max_count)
putstring(tmpstr,GAMECHOOSE_X,GAMECHOOSE_Y+GAMECHOOSE_SIZE+1,3<<12)
case bios_type
BIOS_EXPORT: tmp := @"Using international BIOS"
BIOS_JAPAN: tmp := @"Using japanese BIOS"
BIOS_UNIBIOS: tmp := @"Using UniBIOS"
putstring(tmp,GAMECHOOSE_X,GAMECHOOSE_Y+GAMECHOOSE_SIZE+2,0<<12)
putstring(@"Hit D for credits!",GAMECHOOSE_X,27,0<<12)
repeat
previnput := input
input := long[$60]
tmp := input & !previnput
tmp2 := 0
if (getct()-repeatnext) >= 0
tmp2 := repeatkey
repeatnext := clkfreq+/10 + getct()
if tmp
repeatnext := clkfreq+/2 + getct()
ifnot input.[0] xor input.[1]
repeatkey := 0
elseif (tmp.[0]||tmp2==1) && selected > mingot
repeatkey := 1
repeat until byte[games_got][--selected]
if selected == drawtop and drawtop > mingot
repeat until byte[games_got][--drawtop]
quit
elseif (tmp.[1]||tmp2==2) && selected < maxgot
repeatkey := 2
repeat until byte[games_got][++selected]
if selected == drawlast and drawlast < maxgot
repeat until byte[games_got][++drawtop]
quit
if tmp.[5] && ALLOW_BIOS_CHANGE
if bios_type == BIOS_MAXNUM-1
bios_type := 0
else
bios_type++
quit
if tmp.[7]
settiles(0,39,GAMECHOOSE_Y,27," ")
i := print_info(@credits_text,GAMECHOOSE_Y)
#ifdef USE_PSRAM_EITHER
i++
' A kingdom for compile time stringify
c.sprintf(tmpstr,@"Using PSRAM: %2d bit, sysclk/%d", PSRAM_WIDTH, PSRAM_CLKDIV)
putstring(tmpstr,2,i++,3<<12)
c.sprintf(tmpstr,@"WAIT=%2d DELAY=%2d CLK=%-5s DAT=%-5s",PSRAM_WAIT,PSRAM_DELAY,PSRAM_SYNC_CLOCK?@"SYNC":@"ASYNC",PSRAM_SYNC_DATA?@"SYNC":@"ASYNC")
putstring(tmpstr,2,i++,3<<12)
c.sprintf(tmpstr,@"BASE=%2d CLK=%2d(+%d) SELECT=%2d(+%d)",PSRAM_BASE,PSRAM_CLK&63,PSRAM_CLK>>6,PSRAM_SELECT,PSRAM_BANKS-1)
putstring(tmpstr,2,i++,3<<12)
#elseifdef USE_HYPER
i++
c.sprintf(tmpstr,@"Using HyperRAM: %2d bit, sysclk/%d", 8, 2)
putstring(tmpstr,2,i++,3<<12)
c.sprintf(tmpstr,@"WAIT=%2d DELAY=%2d CLK=%-5s DAT=%-5s",HYPER_WAIT,HYPER_DELAY,HYPER_SYNC_CLOCK?@"SYNC":@"ASYNC",HYPER_SYNC_DATA?@"SYNC":@"ASYNC")
putstring(tmpstr,2,i++,3<<12)
c.sprintf(tmpstr,@"BASE=%2d CLK=%2d(+%d) SELECT=%2d(+%d)",HYPER_BASE,HYPER_CLK&63,HYPER_CLK>>6,HYPER_SELECT,HYPER_BANKS-1)
putstring(tmpstr,2,i++,3<<12)
c.sprintf(tmpstr,@"RWDS=%2d RESET=%2d(+%d)",HYPER_RWDS,HYPER_RESET&63,HYPER_RESET>>6)
putstring(tmpstr,2,i++,3<<12)
#endif
input,previnput := anykey(input)
settiles(0,39,GAMECHOOSE_Y,27," ")
i := print_info(@license_text1,GAMECHOOSE_Y)
input,previnput := anykey(input)
settiles(0,39,GAMECHOOSE_Y,27," ")
i := print_info(@license_text2,GAMECHOOSE_Y)
input,previnput := anykey(input)
settiles(0,39,GAMECHOOSE_Y,27," ")
quit
if tmp.[4] or tmp.[8]
return
PRI print_info(text,y) : i | color
i := y
repeat while byte[text] <> 127
color := byte[text++]
putstring(text,2,i++,color<<12)
text += strsize(text)+1
PRI anykey(previnput) : r,s | input,tmp
repeat
input := long[$60]
tmp := input & !previnput
if tmp & %1_1001_0000
return input,previnput
previnput := input
DAT
credits_text
byte 0,"A NeoGeo AES emulator for P2+PSRAM",0
byte 4,"https://github.com/IRQsome/NeoYume",0
byte 1,"Programmed by Ada Gottensträter",0
byte 1," of IRQsome Software non-inc",0
byte 0,"",0
byte 2,"Additional programming:",0
byte 0," Eric Smith: flexspin compiler",0
byte 0," Garry Jordan &",0
byte 0," Marco Maccaferri: USB driver ",0
byte 0," Roger Loh: exmem drivers",0
byte 0,"",0
byte 0,"This program is free software under.",0
byte 0,"the IESL v1. Press any key to view",0
byte 0,"license terms.",0
byte 127
license_text1
byte 1,"IRQsome Ethical Source License (v1)",0
byte 3,"-----------------------------------",0
byte 0,"Permission is granted to any person",0
byte 0,"obtaining a copy of this software",0
byte 0,"(and related materials) to use the",0
byte 0,"software freely in any way the heart",0
byte 0,"desires, under the condition that:",0
byte 0,0
byte 0,"1. This copyleft notice must be",0
byte 0," included with any copy of a sub-",0
byte 0," stantial portion of the software.",0
byte 0,0
byte 0,"2. Modified versions of the software",0
byte 0,"must be marked as such and",0
byte 0,"recipients must also receive the",0
byte 0,"modified source code.",0
byte 0,0
byte 0,"[continued on next page]",0
byte 127
license_text2
byte 0,"3. The software must be used for",0
byte 0,"Good, not Evil. Evil may include any",0
byte 0,"usage contributing or otherwise rel-",0
byte 0,"ating to the development or impleme-",0
byte 0,"ntation of: lethal weaponry or other",0
byte 0,"means of murder, automated behaviour",0
byte 0,"tracking and surveillance systems,",0
byte 0,"'AI' systems designed to unconsen-",0
byte 0,"sually exploit labor and/or produce",0
byte 0,"fake media of any kind.",0
byte 0,0
byte 0,"4. The author(s) of the software",0
byte 0,"must not be held responsible for any",0
byte 0,"damages arising from use of the",0
byte 0,"software.",0
byte 127
PRI gen_gradient_palette(ptr,bg,fg) | i
long[ptr][0]:=0
repeat i from 0 to 14
long[ptr][i+1]:= __blnpix(bg,fg, i frac $e0e0e0e)
PRI __blnpix(a,b,ratio) : r
r := a
asm
setpiv ratio
blnpix r,b
endasm
CON
#1
LOAD_RAW,LOAD_BSWAP,LOAD_WSWAP,LOAD_LSWAP,LOAD_QSWAP,LOAD_CROM,LOAD_SROM_CMC,LOAD_SROM
LOAD_BIOS
LOAD_FILLER
SET_PROG,SET_PORT,SET_UNUSED,SET_BIOS,SET_ADPCM_A,SET_ADPCM_B,SET_CHAR,SET_FIX,SET_Z80
SET_BANKSWITCH_2M,SET_BANKSWITCH_4M,SET_BANKSWITCH_8M,SET_BANKSWITCH_PVC_8M
SET_TILEMASK
LOADCMD_FIRST = LOAD_RAW
LOADCMD_LAST = LOAD_BIOS-1 ' Note: LOAD_BIOS doesn't count
SETCMD_FIRST = SET_PROG
SETCMD_LAST = SET_Z80
#0,GAME_OK,GAME_ISSUE,GAME_BROKEN
WITH_OFFSET = $80
GREYM = $010101_00
DAT
menu_palette
long 0,$01*GREYM,$13*GREYM,$25*GREYM,$37*GREYM,$49*GREYM,$5B*GREYM,$6D*GREYM,$7F*GREYM,$91*GREYM,$A3*GREYM,$B5*GREYM,$C7*GREYM,$D9*GREYM,$EB*GREYM,$FD*GREYM
PRI exmem_start() | tmp,cogs,banks,i,sizelen
tmp := c.malloc(8*4+8*4+32*4)
cogs := tmp+8*4
banks := cogs+8*4
if exmem_cog
return
long[tmp][0] := clkfreq
#ifdef USE_HYPER
long[tmp][1] := (HYPER_SYNC_CLOCK?0:1)<<exmem.UNREGCLK_BIT
long[tmp][2] := (HYPER_RESET < 32 && HYPER_RESET > 0) ? 1<<HYPER_RESET : 0
long[tmp][3] := HYPER_RESET >= 32 ? 1<<(HYPER_RESET-32) : 0
#elseifdef USE_PSRAM_EITHER
long[tmp][1] := (PSRAM_SYNC_CLOCK?0:1)<<exmem.UNREGCLK_BIT
#ifdef USE_PSRAM_SLOW
long[tmp][1] |= 1<<exmem.SLOWCLK_BIT | 1<<exmem.CLKSEL_BIT
#endif
long[tmp][2] := 0
long[tmp][3] := 0
#endif
#ifdef USE_PSRAM_EITHER
long[tmp][4] := PSRAM_BASE
#elseifdef USE_HYPER
long[tmp][4] := HYPER_BASE
#endif
long[tmp][5] := banks
long[tmp][6] := cogs
long[tmp][7] := @exmem_mailbox[0]
long[cogs][0]:=-1<<16 + %1_111<<12
longfill(cogs+4,-1<<16,7)
longfill(banks,negx,32)
#ifdef USE_PSRAM16
exmem_size := 32*1024*1024 * PSRAM_BANKS
sizelen := encod(exmem_size-1)+1
repeat i from 0 to PSRAM_BANKS-1
long[banks][0+i*2] := 512<<16 + (PSRAM_DELAY-10)<<13 + (PSRAM_SYNC_DATA?0:1)<<12 + sizelen
long[banks][1+i*2] := 512<<16 + (PSRAM_DELAY-10)<<13 + (PSRAM_SYNC_DATA?0:1)<<12 + sizelen
long[banks][16+i*2] := PSRAM_SELECT+i + PSRAM_CLK<<8
long[banks][17+i*2] := PSRAM_SELECT+i + PSRAM_CLK<<8
#elseifdef USE_PSRAM8
exmem_size := 16*1024*1024 * PSRAM_BANKS
sizelen := encod(exmem_size-1)+1
repeat i from 0 to PSRAM_BANKS-1
long[banks][0+i] := 256<<16 + (PSRAM_DELAY-10)<<13 + (PSRAM_SYNC_DATA?0:1)<<12 + sizelen
long[banks][16+i] := PSRAM_SELECT+i + PSRAM_CLK<<8
#elseifdef USE_PSRAM4
exmem_size := 8*1024*1024 * PSRAM_BANKS
sizelen := encod(exmem_size-1)+1
repeat i from 0 to (PSRAM_BANKS-1)/2
long[banks][0+i] := 128<<16 + (PSRAM_DELAY-10)<<13 + (PSRAM_SYNC_DATA?0:1)<<12 + sizelen
long[banks][16+i] := PSRAM_SELECT+i*2 + PSRAM_CLK<<8 + (PSRAM_SELECT+i*2+(((PSRAM_BANKS&1)&&(i>=PSRAM_BANKS/2)) ? 0 : 1))<<16
#elseifdef USE_HYPER
exmem_size := 16*1024*1024 * HYPER_BANKS
sizelen := encod(exmem_size-1)+1
repeat i from 0 to HYPER_BANKS-1
long[banks][0+i] := 256<<16 + (HYPER_DELAY-7)<<13 + (HYPER_SYNC_DATA?0:1)<<12 + sizelen
long[banks][16+i] := HYPER_SELECT+i + HYPER_CLK<<8 + HYPER_RWDS<<16 + HYPER_LATENCY<<25 ' Latency????
#endif
exmem_mailbox[0] := -1
cogs := exmem.getDriverAddr()
exmem_cog := coginit(COGEXEC_NEW,cogs,tmp)+1
repeat while exmem_mailbox[0] ' wait for init so data structures can go dead
PRI exmem_stop()
if exmem_cog
exmem_sync()
cogstop((exmem_cog\0)-1)
PRI exmem_sync()
repeat while exmem_mailbox[0]
PRI exmem_write(dst,src,length,async)
exmem_sync()
exmem_mailbox[2] := length
exmem_mailbox[1] := src
exmem_mailbox[0] := exmem.R_WRITEBURST + (dst & $fffffff)
ifnot async
exmem_sync()
PRI exmem_fill(dst,val,length,async)
exmem_sync()
exmem_mailbox[2] := length
exmem_mailbox[1] := val
exmem_mailbox[0] := exmem.R_WRITEBYTE + (dst & $fffffff)
ifnot async
exmem_sync()
PRI exmem_read(dst,src,length,async)
exmem_sync()
exmem_mailbox[2] := length
exmem_mailbox[1] := dst
exmem_mailbox[0] := exmem.R_READBURST + (src & $fffffff)
ifnot async
exmem_sync()
#include "neoyume_gamedb.spin2"