> ROMBox/s + Provides emulated ROMBox for Spectrum . Memory at &0000-&3FFF paged at OUT &xxFD ( 2, 23-Mar-2002 v1.00 JGH: Initial version <5 09-Nov-2005 v1.05 JGH: Added ROMBoxPort command F P : : Z: dioport%=&00FD n: x mcode% &8000:ver$="1.05" sp=13:link=14:pc=15 p=0 1 P%=0:O%=mcode% [OPT p*3+4 EQUD 0:\start EQUD Initialise EQUD Finalise EQUD Service EQUD TitleStr EQUD HelpStr EQUD CommandTable EQUD 0:\ SWI chunk number EQUD 0:\ SWI chunk handler EQUD 0:\ SWI decoding table EQUD 0:\ SWI decoding code : " .TitleStr ,EQUS "ROMBox" 6 EQUB 0 @ ALIGN J .HelpStr THEQUS "Spectrum ROMBox"+9+ver$+" ("+$,5,11)+") 2002 J.G.Harston" ^ EQUB 0 h ALIGN r: |.CommandTable iEQUS "ROMBox":EQUB 0:ALIGN:EQUD ROMBoxInit:EQUD &00010001:EQUD ROMBoxInit_Syntax:EQUD ROMBoxInit_Help mEQUS "ROMBoxLoad":EQUB 0:ALIGN:EQUD ROMBoxLoad:EQUD &00020002:EQUD ROMBoxLoad_Syntax:EQUD ROMBoxLoad_Help mEQUS "ROMBoxList":EQUB 0:ALIGN:EQUD ROMBoxList:EQUD &00000000:EQUD ROMBoxList_Syntax:EQUD ROMBoxList_Help mEQUS "ROMBoxPort":EQUB 0:ALIGN:EQUD ROMBoxPort:EQUD &00000000:EQUD ROMBoxPort_Syntax:EQUD ROMBoxPort_Help \ ROMBoxRAM \ ROMBoxROM \ ? EQUB 0:ALIGN : .ROMBoxInit_Help @EQUS "Registers a module or application with ROMBox":EQUB 13 .ROMBoxInit_Syntax 1EQUS "Syntax: ROMBox |
" EQUB 0:ALIGN : .ROMBoxLoad_Help &7EQUS "Loads a ROM image into a ROMBox slot":EQUB 13 0.ROMBoxLoad_Syntax :5EQUS "Syntax: ROMBoxLoad " DEQUB 0:ALIGN N: X.ROMBoxList_Help b+EQUS "Lists loaded ROMBox ROMs":EQUB 13 l.ROMBoxList_Syntax vEQUS "Syntax: ROMBoxList" EQUB 0:ALIGN : .ROMBoxPort_Help 3EQUS "Sets or displays ROMBox I/O port":EQUB 13 .ROMBoxPort_Syntax &EQUS "Syntax: ROMBoxPort ()" EQUB 0:ALIGN : : .Initialise stmfd (sp)!,{link} ldr r0,[r12] orrs r0,r0,#0 5bne Reinitialise ; We already have workspace  mov r0,#6 ,mov r3,#10*4 ; We want 10 words  swi "XOS_Module" */ldmvsfd (sp)!,{pc} ; Memory claim failed 40str r2,[r12] ; Store in w/s pointer >.mov r0,#0 ; Clear ROM pointers Hmov r1,#0 R.InitClear \str r0,[r2,r1] fadd r1,r1,#4 pDcmp r1,#10*4 ; 8 ROM pointers, module pointer, OUT copy zbcc InitClear .Reinitialise ldmfd (sp)!,{pc} : :  .Finalise stmfd (sp)!,{link} =ldr r3,[r12] ; Get pointer to module's workspace orrs r3,r3,#0 Mbeq Finalised ; No workspace (shouldn't ever get called this way) 1mov r4,#0 ; Loop from workspace+0 .FinalLoop 4ldr r2,[r3,r4] ; Get pointer to ROM space 'orrs r2,r2,#0 ; Is is zero? 1add r4,r4,#4 ; Point to next pointer movne r0,#7 :swine "XOS_Module" ; Release ROM space if it exists $cmp r4,#4*8 .*bcc FinalLoop ; 8 ROM pointers 89ldr r2,[r12] ; Pointer to module's workspace Bmov r0,#7 L&swi "XOS_Module" ; Release it V.Finalised `ldmfd (sp)!,{pc} j: t: ~;.ROMBoxInit ; *ROMBox |
mov pc,link : : ?.ROMBoxLoad ; *ROMBoxLoad stmfd (sp)!,{link} 7bl ROMNumber ; r6=ROM number, r0=>filename (mov r7,r0 ; r7=>filename mov r1,r7 mov r0,#5 -swi "OS_File" ; Read info on file )cmp r0,#1 ; File present? bne ROMNotFound /cmp r4,#&4000 ; Check file's length  beq ROMLoadOk 3bcs ROMFileTooLong ; Can only load up to 16k .ROMLoadOk (4ldr r12,[r12] ; Get address of workspace 20ldr r2,[r12,r6,lsl #2] ; Get ROM's address <orrs r2,r2,#0 F5moveq r0,#6 ; If zero, claim 16k of RMA Pmoveq r3,#&4000 Zfilename ; r3=index into ROM memory ; r2=>ROM memory-12 ; r1=index into filename  ; r0=byte 1mov r3,#0 ; index into ROM memory /mov r1,#0 ; index into filename 4.ROMLoadScan ; Look for end of filename ldrb r0,[r7,r1] add r1,r1,#1 cmp r0,#"!" bcs ROMLoadScan .ROMLoadScan2 subs r1,r1,#1 ;beq ROMLoadName ; Moved back to start of filename ldrb r0,[r7,r1] cmp r0,#"." "6cmpne r0,#":" ; Loop back until dot or colon ,bne ROMLoadScan2 6add r1,r1,#1 @.ROMLoadName Jldrb r0,[r7,r1] Tstrb r0,[r2,r3] ^add r1,r1,#1 hadd r3,r3,#1 rcmp r3,#11 |bcs ROMLoadLeaf cmp r0,#"!" bcs ROMLoadName sub r3,r3,#1 .ROMLoadLeaf mov r0,#0 +strb r0,[r2,r3] ; zero terminator ; 4add r2,r2,#12 ; Point to ROM image start  mov r0,#&FF ; 'Ǖ' mov r1,r7 1mov r3,#0 ; Load to address in r2 swi "OS_File" 6sub r2,r2,#12 ; Point to before ROM memory ldmfd (sp)!,{pc} : .ROMFileTooLong &ADR r0,ROMFileTooLongErr 0SWI "OS_GenerateError" :.ROMFileTooLongErr D EQUD 255 NEQUS "ROM too long" XEQUB 0:ALIGN b: l.ROMNotFound vADR r0,ROMNotFoundErr SWI "OS_GenerateError" .ROMNotFoundErr  EQUD 214 EQUS "ROM not found" EQUB 0:ALIGN : : ?.ROMBoxSave ; *ROMBoxLoad mov pc,link : : .ROMNumber ;ldrb r6,[r0,#1] ; Look at character after current cmp r6,#" "  addne r0,r0,#1 1bne ROMNumber ; Skip until last digit  ;ldrb r6,[r0],#1 ; Get last digit and inc. pointer **and r6,r6,#7 ; Reduce to 0..7 4.ROMNumberSpc >ldrb r1,[r0] Hcmp r1,#" " Raddeq r0,r0,#1 \3beq ROMNumberSpc ; Skip spaces after digit f.mov pc,link ; r6=ROM number 0..7 p: z: '.ROMBoxList ; *ROMBoxList stmfd (sp)!,{link} 1ldr r12,[r12] ; Get workspace pointer ,mov r3,#0 ; Start with ROM 0 .ROMListLoop ldr r2,[r12,r3,lsl #2] 4orrs r2,r2,#0 ; Get address of ROM image beq ROMListEmpty orr r0,r3,#"0" swi "OS_WriteC" swi 256+":" +swi 256+" " ; Output ROM number 0mov r1,#11 ; Max of 11 characters .ROMListName )ldrb r0,[r2],#1 ; Get character cmp r0,#"!" $+bcc ROMListPad ; End of leafname .swi "OS_WriteC" 8subs r1,r1,#1 Bbne ROMListName L.ROMListPad V+swi 256+32 ; Pad with spaces `add r2,r2,#1 jsubs r1,r1,#1 tbpl ROMListPad ~?add r2,r2,#256 ; Point to near begining of ROM image .ROMListLook add r2,r2,#1 4ldrb r0,[r2,#3] ; Look for four II values $cmp r0,#"!":bcc ROMListLook $cmp r0,#"z":bcs ROMListLook ldrb r0,[r2,#2] $cmp r0,#"!":bcc ROMListLook $cmp r0,#"z":bcs ROMListLook ldrb r0,[r2,#1] $cmp r0,#"!":bcc ROMListLook $cmp r0,#"z":bcs ROMListLook ldrb r0,[r2,#0] $cmp r0,#"!":bcc ROMListLook $cmp r0,#"z":bcs ROMListLook .ROMListTitle swi "OS_WriteC" (add r2,r2,#1 2ldrb r0,[r2] <cmp r0,#" " Fbcc ROMListDone Pcmp r0,#"~"+1 Zbcc ROMListTitle d.ROMListDone nswi "OS_NewLine" x.ROMListEmpty add r3,r3,#1 cmp r3,#8 bcc ROMListLoop ldmfd (sp)!,{pc} : : 2.ROMBoxPort ; *ROMBoxPort () mov pc,link : : .Service \ In r0=mem[0] !\ r1=Srv_Z80Reset - &80AC2 !\ r1=Srv_Z80OUT - &80AC1 \ r2=port \ r3=value "\ r4=Module base ,\ 6movs r2,r3,lsr #5 ; r2=OUT value 32, Cy=OUT value b4 40and r2,r2,#6 ; ROM number = 0,2,4,6 >-orrcs r2,r2,#1 ; ROM number = 0..7 H; R;cmp r2,#8 \;and r2,r2,#13 f.;orrcs r2,r2,#2 ; ROM number = 0..7 pldr r2,[r12,r2,lsl #2] z5orrs r2,r2,#0 ; Get address of ROM memory 3moveq r1,#0 ; No ROM in this slot, so 8moveq pc,link ; claim and exit doing nothing : ; Enter fast quad-word copy loop 5stmfd (sp)!,{r3-r10} ; Save everything for speed Aadd r8,r2,#12 ; Point to quad-aligned ROM image start .mov r9,r0 ; Point to z80mem[0] 0mov r10,#0 ; Copy address pointer ; ; r8=ROM address - src ; r9=z80mem[0] - dst ; r10=loop offset ; .ROMReadLoop 6ldmia r8!,{r0-r7} ; Fetch 8 quad-aligned words @stmia r9!,{r0-r7} ; Store them (may not be quad-aligned) add r10,r10,#32 $(cmp r10,#&4000 ; Loop for 16k .bcc ROMReadLoop 8.ldmfd (sp)!,{r3-r10} ; Get registers back B: L.ROMSelected V*mov r1,#0 ; Claim the call `mov pc,link j: t ALIGN ~] %"SAVE ROMBox "+~mcode%+" "+~O% *SetType ROMBox Module *Stamp ROMBox