Copying data from File to Vram

بواسطة iamweasel2

Paladin (678)

صورة iamweasel2

02-12-2020, 21:11

Hello,

Can someone give me some light on this issue, please?

The code below is supposed to read a .sc2 file (without the header) to vram, by copying 128 bytes from the file each time. As much as I can see in the debug, the code is copying all the data correctly. Despite that, all I see is garbage on screen. Is there anything I'm doing terrible wrong here or maybe I am copying data wrong (and I couldn't see when debugging) ?

BDOS: equ 00005H
STROUT: EQU 00009H
FOPEN: EQU 0000FH
FCLOSE: EQU 00010H
RDSEQ: EQU 00014H
SETDTA: EQU 0001AH

CHGMOD: EQU 005FH
ldirvm: equ 0x005C
CALSLT: equ 0x001C
EXPTBL: equ 0xFCC1

org 0x100

START:

ld a,2 ;sets screen 2
ld iy,(EXPTBL-1)
ld ix,CHGMOD
call CALSLT

; GETS THE NAME OF THE FILE (WITHOUT EXTENSION)
; AND PUTS in the FCB.

LD HL,082H
LD DE,FCB+1
START0:
LD A,(HL)
CP 0DH
JR Z,START1
LD (DE),A
INC HL
INC DE
JR START0

; Open file
START1:
LD DE,FCB ;
LD C,FOPEN ;
CALL BDOS
INC A
JP Z,ERROR1

; starts reading file, 128 bytes each time.

LD DE,BUFFER
LD HL,080H
LD IX,0

; LOOP that reads 128 bytes each turn and writes in BUFFER
; DE = fist empty position of the buffer
START2:
PUSH IX
PUSH DE
PUSH HL
LD C,SETDTA
CALL BDOS

LD DE,FCB
LD C,RDSEQ

CALL BDOS

DEC A
JR Z,START3

POP DE

POP HL

POP IX
INC IX
ADD HL,DE

EX DE,HL

; copy 128 bytes to VRAM;

push HL
push DE

ld h,d
ld l,e

ld d,0
ld e,80h

SBC HL,DE ; HL = DE - 80H (HL = START OF BUFFER)

pop DE ; DE = FIRST BYTE EMPTY IN BUFFER
push DE

push HL ;

LD DE,BUFFER
SBC HL, DE
ld d, h
ld e, l ;

pop HL

PUSH IX;

ld iy,(EXPTBL-1)
ld ix,ldirvm
call CALSLT

POP IX;

pop DE
pop HL

JR START2

LD DE,FCB
LD C,FCLOSE
CALL BDOS

JP 0

START3:
ERROR1:
RET

ERROR2:
RET

TOTAL: DW 0

FCB: DB 0
DB 32,32,32,32
DB 32,32,32,32
DB 'SC2'
DB 0,0,0,0,0,0,0,0,0,0,0
DB 0,0,0,0,0,0,0,0,0,0,0
DB 0,0,0,0,0,0,0,0,0,0,0
DB 0,0,0,0,0,0,0,0,0,0,0

BUFFER:
end

Login أوregister لوضع تعليقاتك

بواسطة iamweasel2

Paladin (678)

صورة iamweasel2

02-12-2020, 23:03

Never mind, already found it. The code works ok, but I the buffer is below 4000h, so when I change slots to call LDIRVM, I was copying the BIOS code instead of the buffer. Just changed the buffer to a higher address and it fixed the problem.

Can't believe I spent more than 4 hours looking for this bug.... Sad

بواسطة iamweasel2

Paladin (678)

صورة iamweasel2

02-12-2020, 23:05

But I have another question, when reading a file, I want to skip the first 7 bytes of the header. What would be the best way to do that when loading the file in a loop like the one above, when you read the file in blocks of 128 bytes?

بواسطة DamnedAngel

Master (214)

صورة DamnedAngel

03-12-2020, 00:17

Add a routine to read the 7 bytes, throw them away and then begin your loop to read actual data.

بواسطة Sandy Brand

Master (225)

صورة Sandy Brand

03-12-2020, 00:17

You probably need to read or skip the first 7 bytes manually.

If you use BDOS _RDBLK, you can specify an amount of 'records' to read.

The size of the records is something you can set in the FCB (bytes 0Eh and 0Fh) after opening the file. If you just set it to 1, then you can specify the exact amount of bytes you want to read from the file using _RDBLK.

بواسطة gdx

Enlighted (4192)

صورة gdx

03-12-2020, 10:23

Please use the 'CODE' tags to put your programs otherwise it's hard to read.
I modified your code a little. I haven't tested if it works now but at least it's more readable.

BDOS:	equ	00005H
STROUT:	equ	00009H
FOPEN:	equ	0000FH
FCLOSE:	equ	00010H
RDSEQ:	equ	00014H
SETDTA:	equ	0001AH
	
CHGMOD:	equ	005FH
ldirvm:	equ	0005CH
CALSLT:	equ	0001CH
EXPTBL:	equ	0FCC1H

	org	0100H
	
START:
	ld	a,2		; Sets screen 2
	ld	iy,(EXPTBL-1)
	ld	ix,CHGMOD
	call	CALSLT
	
; Gets the name of the file (without extension)
; and puts in the FCB.

	ld	hl,082H
	ld	de,FCB+1
START0:
	ld	a,(HL)
	cp	020H		; Jump if A < 20h
	jr	nc,START1
	ld	(de),a
	inc	hl
	inc	de
	jr	START0
	
; Open file

START1:
	ld	de,FCB	;
	ld	c,FOPEN	;
	call	BDOS
	or	a
	jp	nz,ERROR1
	
; starts reading file, 128 bytes each time.

	ld	de,BUFFER
	ld	hl,080H
	ld	ix,0
	
; LOOP that reads 128 bytes each turn and writes in BUFFER
; DE = fist empty position of the buffer

START2:
	push	ix
	push	de
	push	hl
	ld	c,SETDTA
	call	BDOS

	ld	DE,FCB
	ld	C,RDSEQ
	call	BDOS
	or	a
	jr	nz,START3

	pop	de
	pop	hl
	pop	ix
	inc	ix
	add	hl,de
	ex	de,hl
	
; copy 128 bytes to VRAM

	push	hl
	push	de

	ex	de,hl
	ld	de,80h	; DE = FIRST BYTE EMPTY IN BUFFER
	sbc	hl,de	; HL = DE - 80H (HL = START OF BUFFER)
	push	hl	;

	ld	de,BUFFER
	sbc	hl,de
	ex	de,hl

	pop	hl
	push	ix	;

	ld	iy,(EXPTBL-1)
	ld	ix,ldirvm
	call	CALSLT

	pop	ix	;
	pop	de
	pop	hl
	jr	START2

	ld	de,FCB
	ld	c,FCLOSE
	call	BDOS
	rst	0	; Back to the DOS

START3:
ERROR1:
	rst	0	; Back to the DOS

ERROR2:
	rst	0	; Back to the DOS

TOTAL:	dw	0

FCB:
	db	0
	db	'        SC2'
	ds	44,0

BUFFER:
	end

بواسطة iamweasel2

Paladin (678)

صورة iamweasel2

03-12-2020, 15:07

Sandy Brand wrote:

You probably need to read or skip the first 7 bytes manually.

If you use BDOS _RDBLK, you can specify an amount of 'records' to read.

The size of the records is something you can set in the FCB (bytes 0Eh and 0Fh) after opening the file. If you just set it to 1, then you can specify the exact amount of bytes you want to read from the file using _RDBLK.

Thanks Sandy for your comments, I will change the code to use RDBLK instead of RDSEQ. I'm using RDSEQ (sequential read and AFAIK it has a 128 bytes fixed read). I was thinking about doing a single read outside the loop just to read the first 128 bytes and write only 121 bytes to VRAM, but I believe this would be a ugly solution to a problem that surely would have a better way to be dealt with.

بواسطة iamweasel2

Paladin (678)

صورة iamweasel2

03-12-2020, 20:28

gdx wrote:

Please use the 'CODE' tags to put your programs otherwise it's hard to read.
I modified your code a little. I haven't tested if it works now but at least it's more readable.

BDOS:	equ	00005H
STROUT:	equ	00009H
FOPEN:	equ	0000FH
FCLOSE:	equ	00010H
RDSEQ:	equ	00014H
SETDTA:	equ	0001AH
	
CHGMOD:	equ	005FH
ldirvm:	equ	0005CH
CALSLT:	equ	0001CH
EXPTBL:	equ	0FCC1H

	org	0100H
	
START:
	ld	a,2		; Sets screen 2
	ld	iy,(EXPTBL-1)
	ld	ix,CHGMOD
	call	CALSLT
	
; Gets the name of the file (without extension)
; and puts in the FCB.

	ld	hl,082H
	ld	de,FCB+1
START0:
	ld	a,(HL)
	cp	020H		; Jump if A < 20h
	jr	nc,START1
	ld	(de),a
	inc	hl
	inc	de
	jr	START0
	
; Open file

START1:
	ld	de,FCB	;
	ld	c,FOPEN	;
	call	BDOS
	or	a
	jp	nz,ERROR1
	
; starts reading file, 128 bytes each time.

	ld	de,BUFFER
	ld	hl,080H
	ld	ix,0
	
; LOOP that reads 128 bytes each turn and writes in BUFFER
; DE = fist empty position of the buffer

START2:
	push	ix
	push	de
	push	hl
	ld	c,SETDTA
	call	BDOS

	ld	DE,FCB
	ld	C,RDSEQ
	call	BDOS
	or	a
	jr	nz,START3

	pop	de
	pop	hl
	pop	ix
	inc	ix
	add	hl,de
	ex	de,hl
	
; copy 128 bytes to VRAM

	push	hl
	push	de

	ex	de,hl
	ld	de,80h	; DE = FIRST BYTE EMPTY IN BUFFER
	sbc	hl,de	; HL = DE - 80H (HL = START OF BUFFER)
	push	hl	;

	ld	de,BUFFER
	sbc	hl,de
	ex	de,hl

	pop	hl
	push	ix	;

	ld	iy,(EXPTBL-1)
	ld	ix,ldirvm
	call	CALSLT

	pop	ix	;
	pop	de
	pop	hl
	jr	START2

	ld	de,FCB
	ld	c,FCLOSE
	call	BDOS
	rst	0	; Back to the DOS

START3:
ERROR1:
	rst	0	; Back to the DOS

ERROR2:
	rst	0	; Back to the DOS

TOTAL:	dw	0

FCB:
	db	0
	db	'        SC2'
	ds	44,0

BUFFER:
	end

THANKS a LOT GDX, and sorry for not using the CODE tag, I was not aware that this tag was available.

I saw that you changed the JP 0 I was using for RST 0. Is this a better way to exit from a DOS software?

I saw that you changed the FCB as well. Is there anything else you changed?

From what I see (and fixed in my code here), this version I placed here won't work unless that the BUFFER is located above 4000H, due to the use of the BIOS function LDIRVM.

بواسطة gdx

Enlighted (4192)

صورة gdx

04-12-2020, 10:27

I Replaced two time

 	ld	d,h
 	ld	e,l

by ex de,hl

I also modified the condition to copy the file name but I realize now that it's not yet right,
So try that:

	ld	hl,05CH+1
	ld	de,FCB+1
	ld	bc,8
	ldir

instead of:

	ld	hl,082H
	ld	de,FCB+1
START0:
	ld	a,(HL)
	cp	020H		; Jump if A < 20h
	jr	nc,START1
	ld	(de),a
	inc	hl
	inc	de
	jr	START0

I also cleaned a little the code. RST 0 is just to visually clarify the back to DOS.